내가 한 풀이
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
from sklearn.preprocessing import StandardScaler
# 학습 데이터
X_train = [[1, 1], [2, 2], [3, 3], [6, 6], [7, 7], [8, 8]]
y_train = ['A', 'A', 'A', 'B', 'B', 'B']
# 테스트 데이터
X_test = [[4, 4], [5, 5]] # 예측이 뭘로 분류가 되느냐? 모델 만들기전에 스케일링 진행
scaler = StandardScaler() # 스케일러 생성
X_train_scaled = scaler.fit_transform(X_train) # X_train scaling진행, fit과 transform 동시에
X_test_scaled = scaler.transform(X_test) # 훈련 데이터의 기준으로 스케일링 진행
# KNN 모델 생성 (K=3)
knn = KNeighborsClassifier(n_neighbors=3)
# 학습 수행
knn.fit(X_train_scaled, y_train) #X_trainscaled, 타깃변수
# 예측 수행
pred = knn.predict(X_test_scaled) # 스케일된 데이터로 수행
print("예측 결과:", pred)
# 여러 K에 대해 시도
K_list = [1, 3, 5]
for k in K_list:
knn = KNeighborsClassifier(n_neighbors=k)
knn.fit(X_train_scaled, y_train)
pred = knn.predict(X_test_scaled) # 스케일된 데이터 바탕으로 예측 진행
print(f"K={k} → 예측: {pred}")
예측 결과: ['A' 'B']
K=1 → 예측: ['A' 'B']
K=3 → 예측: ['A' 'B']
K=5 → 예측: ['A' 'B']
트러블 슈팅
fit_transform - 학습과 적용(스케일링)
transform - 적용(스케일링)만
반복문 내에 k값 설정및 모델 학습
n_neighbors=k
fit에는 반드시 스케일링된 훈련데이터를
Iris 데이터셋을 사용하여 꽃의 품종(species)을 분류하는 KNN 모델을 만들어보세요.
iris.csv 파일을 읽고, 데이터 구조를 파악하세요.species 속성에 대해 라벨 인코딩(LabelEncoder 활용)을 수행하세요.내가 한 풀이
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
import pandas as pd
# 시각화 한글 깨짐 방지 설정
plt.rcParams['font.family'] ='Malgun Gothic'
plt.rcParams["axes.unicode_minus"] = False
# 1. 데이터셋 읽고, 데이터 구조 파악하기
df = pd.read_csv('iris.csv')
df
# species 인코딩 진행
# 2. 데이터 feature와 target으로 분리하기
X = df.drop('species', axis=1) # 특징(꽃받침/꽃잎 길이/너비)
y = df['species'] # 품종
# 3. 데이터셋 분할하기 (8:2)
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2,
random_state=42,
stratify=y # 클래스 비율 유지
)
# 4. 훈련/테스트 target 변수에 대해 '라벨 인코딩' 수행, species 0,1,2로 표현하기 위해
encoder = LabelEncoder()
y_train_encoded = encoder.fit_transform(y_train) # 훈련 데이터: 학습 + 적용
y_test_encoded = encoder.transform(y_test) # 테스트 데이터: 적용만
# 5. 훈련/테스트 feature에 대해 스케일링 수행(StandardScaler)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # 훈련 데이터: 학습 + 적용
X_test_scaled = scaler.transform(X_test) # 테스트 데이터: 적용만
# 6. K = 3 ~ 11 에 대해 정확도 비교
k_list = range(3, 12, 2) # K=1, 3, 5, 7, 9, 11
test_accuracies = [] # 각 K마다 정확도를 저장하는 리스트
for k in k_list: # 3, 5, 7, 9, 11
# 각 K에 대한 KNN 모델 생성 후, 학습 진행
model = KNeighborsClassifier(n_neighbors=k)
model.fit(X_train_scaled, y_train_encoded)
# 테스트 데이터에 대해 예측 진행
y_test_pred = model.predict(X_test_scaled)
# 정확도 측정
test_acc = accuracy_score(y_test_encoded, y_test_pred)
test_accuracies.append(test_acc) # 기록하기
# 7. 최적 K값 찾기 (테스트 정확도가 가장 높은 K 선택)
best_k_index = test_accuracies.index(max(test_accuracies))
# 정확도 리스트에서 정확도가 max에 해당되는 인덱스 가져오는 코드
best_k = k_list[best_k_index] # 해당 인덱스에 대한 K 값을 가져온다.
print("K 값별 Test 정확도 :", test_accuracies)
print(f"최적의 K 값: {best_k}")
print(f"최적 K에서의 Test 정확도: {test_accuracies[best_k_index]:.4f}")
# 8. 최적 K로 최종 KNN 모델로 학습하기
best_model = KNeighborsClassifier(n_neighbors=best_k)
# 위에서 구한 최적의 K로 KNN 모델 학습하기
best_model.fit(X_train_scaled, y_train_encoded)
# 9. 최종 테스트 예측 및 정확도
y_test_pred_final = best_model.predict(X_test_scaled)
final_test_acc = accuracy_score(y_test_encoded, y_test_pred_final) # 정확도 측정
print(f"최종 모델(최적 K={best_k}) Test 정확도: {final_test_acc:.4f}")
# 10. K 값에 따른 정확도 변화를 그래프로 시각화
plt.figure(figsize=(8, 5))
# 선 그래프로 K값이 변화할 때의 모델의 테스트 정확도
# X축이 K값, Y축이 정확도
plt.plot(k_list, test_accuracies, marker='s', label='Test Accuracy')
plt.xticks(k_list)
plt.xlabel('K (Number of Neighbors)')
plt.ylabel('Accuracy')
plt.title('K 값에 따른 KNN 모델 정확도 변화')
plt.legend()
plt.grid(True)
plt.show()
K 값별 Test 정확도 : [0.9333333333333333, 0.9333333333333333, 0.9666666666666667, 0.9666666666666667, 0.9666666666666667]
최적의 K 값: 7
최적 K에서의 Test 정확도: 0.9667
최종 모델(최적 K=7) Test 정확도: 0.9667

트러블 슈팅
X = df.drop('species', axis=1) # 특징(꽃받침/꽃잎 길이/너비)
species 제외한 컬럼이 X 데이터
y_train_encoded = encoder.fit_transform(y_train) # 훈련 데이터: 학습 + 적용
y_test_encoded = encoder.transform(y_test) # 테스트 데이터: 적용만
여기서 라벨 인코딩하는 이유 타깃 변수 정수형 변환
for k in k_list: # 3, 5, 7, 9, 11
# 각 K에 대한 KNN 모델 생성 후, 학습 진행
model = KNeighborsClassifier(n_neighbors=k)
model.fit(X_train_scaled, y_train_encoded)
여기서도 적용된 훈련데이터 넣기
# 7. 최적 K값 찾기 (테스트 정확도가 가장 높은 K 선택)
best_k_index = test_accuracies.index(max(test_accuracies))
# 정확도 리스트에서 정확도가 max에 해당되는 인덱스 가져오는 코드
이부분이 코드문이 어려웠다.
다음 과일 데이터를 사용하여 KNN 분류기를 만들어보세요.
요구사항:
내가 한 풀이
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt
# 1. 학습 데이터 (무게, 지름)
X_train = [[150, 7], [170, 7.5], [140, 6.5], [130, 6],
[180, 8], [200, 9], [190, 8.5], [210, 9.5]]
y_train = ['사과', '사과', '사과', '사과',
'오렌지', '오렌지', '오렌지', '오렌지']
# 테스트 데이터
X_test = [[160, 7], [195, 9]]
# 2. K=3인 KNN 모델 생성 및 학습
model = KNeighborsClassifier(n_neighbors=3)
model.fit(X_train, y_train)
# 3. 테스트 데이터 예측
y_pred = model.predict(X_test)
print("테스트 데이터:", X_test)
print("예측 결과:", y_pred)
y_proba = model.predict_proba(X_test)
print("\n--- 요구사항 3: 예측 확률 ---")
print("테스트 데이터:", X_test)
테스트 데이터: [[160, 7], [195, 9]]
예측 결과: ['사과' '오렌지']
--- 요구사항 3: 예측 확률 ---
테스트 데이터: [[160, 7], [195, 9]]
트러블 슈팅
특별히 어려운건 없었으나.
proba는
각 예측에 대한 확률적 정보를 얻기 위함입니다.
펭귄 데이터셋으로 펭귄의 종(species)을 분류해보세요.
요구사항:
['bill_length_mm', 'bill_depth_mm', 'flipper_length_mm', 'body_mass_g']species내가 한 풀이
import seaborn as sns
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
# 1. penguins 데이터 로드
penguins = pd.read_csv('penguins.csv')
# 2. 사용할 특성(Features)과 타깃(Target) '이름' 지정
features = ['bill_length_mm', 'bill_depth_mm', 'flipper_length_mm', 'body_mass_g']
target = 'species'
# 3. 결측치가 있는 행 제거하기
# data = penguins[features + [target]].isna()
data = penguins.dropna(subset=features+[target], ignore_index=True)
print(data.shape)
# 4. feature, target 분리
X = data[features]
y = data[target] # 문자열('Adelie', 'Chinstrap', 'Gentoo')
# # 5. 훈련/테스트 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.3,
random_state=42,
stratify=y
)
print("학습 데이터 크기:", X_train.shape)
print("테스트 데이터 크기:", X_test.shape)
# # 6. 타겟 변수(species) 인코딩
label_encoder = LabelEncoder()
y_train_encoded = label_encoder.fit_transform(y_train) # 학습 + 적용
y_test_encoded = label_encoder.transform(y_test) # 적용만
# # 7. StandardScaler로 스케일링
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # 학습 + 적용
X_test_scaled = scaler.transform(X_test) # 적용만
# # 8. K = 1 ~ 15 까지 정확도 비교
k_values = range(1, 16, 2)
test_acc_list = []
for k in k_values:
# KNN 모델 생성 및 학습하기
model = KNeighborsClassifier(n_neighbors=k)
model.fit(X_train_scaled, y_train_encoded)
# 훈련셋 predict 도 진행
# 예측 진행하기
y_train_pred = model.predict(X_train_scaled)
y_test_pred = model.predict(X_test_scaled)
# 테스트/예측 결과에 대한 정확도(accuracy_score) 평가
# Train 셋에 대한 예측 및 평가를 진행하기 또는 train_acc 제거하고 진행하기
train_acc = accuracy_score(y_train_encoded, y_train_pred)
test_acc = accuracy_score(y_test_encoded, y_test_pred)
test_acc_list.append(test_acc)
print(f"K={k}: Train Acc = {train_acc:.4f} | Test Acc = {test_acc:.4f}")
# 9. 최적 K값 선택 (테스트 정확도가 가장 높은 K)
best_index = test_acc_list.index(max(test_acc_list))
best_k = list(k_values)[best_index]
best_test_acc = test_acc_list[best_index]
print(f"최적 K 값: {best_k}")
print(f"최적 K에서의 Test Accuracy: {best_test_acc:.4f}")
# 10. 최적 K로 최종 모델 학습
best_model = KNeighborsClassifier(n_neighbors=best_k)
best_model.fit(X_train_scaled,y_train_encoded) # 여기도 훈련셋
# 11. 예측 예시 (앞 5개)
y_test_pred_best = best_model.predict(X_test_scaled)
print("테스트셋 앞 5개 실제 라벨 (숫자):", y_test[:5])
print("테스트셋 앞 5개 예측 라벨 (숫자):", y_test_pred_best[:5])
# 12. K값에 따른 정확도 변화를 선 그래프로 시각화
plt.figure(figsize=(8, 5))
plt.plot(k_values, test_acc_list, marker='s', label='Test Accuracy')
plt.xticks(k_values)
plt.xlabel("K (Number of Neighbors)")
plt.ylabel("Accuracy")
plt.title("K 값에 따른 KNN 정확도 변화 (펭귄 종 분류)")
plt.legend()
plt.grid(True)
plt.show()
(342, 7)
학습 데이터 크기: (239, 4)
테스트 데이터 크기: (103, 4)
K=1: Train Acc = 1.0000 | Test Acc = 0.9709
K=3: Train Acc = 1.0000 | Test Acc = 0.9903
K=5: Train Acc = 0.9916 | Test Acc = 1.0000
K=7: Train Acc = 0.9874 | Test Acc = 1.0000
K=9: Train Acc = 0.9749 | Test Acc = 0.9903
K=11: Train Acc = 0.9749 | Test Acc = 0.9903
K=13: Train Acc = 0.9749 | Test Acc = 0.9806
K=15: Train Acc = 0.9749 | Test Acc = 0.9806
최적 K 값: 5
최적 K에서의 Test Accuracy: 1.0000
테스트셋 앞 5개 실제 라벨 (숫자): 130 Adelie
277 Gentoo
210 Chinstrap
21 Adelie
14 Adelie
Name: species, dtype: object
테스트셋 앞 5개 예측 라벨 (숫자): [0 2 1 0 0]

트러블 슈팅
다른 코드문 멀쩡한데 결측치 제거 안해서 결과 좀 이상하게 나왔음
features = ['bill_length_mm', 'bill_depth_mm', 'flipper_length_mm', 'body_mass_g']
target = 'species'
# 3. 결측치가 있는 행 제거하기
# data = penguins[features + [target]].isna()
data = penguins.dropna(subset=features+[target], ignore_index=True)
print(data.shape)
이것도 2차원인거 맞춰서 컬럼 넣어야 함
그리고 실제값과 예측값 비교 이것도 잊지 말기
train_acc = accuracy_score(y_train_encoded, y_train_pred)
test_acc = accuracy_score(y_test_encoded, y_test_pred)
그리고 마찬가지로 최적의 k값 리스트 내에서 제일 높은 값
# 9. 최적 K값 선택 (테스트 정확도가 가장 높은 K)
best_index = test_acc_list.index(max(test_acc_list))
best_k = list(k_values)[best_index]
best_test_acc = test_acc_list[best_index]
Pima Indians Diabetes 데이터셋으로 당뇨병 발병(Outcome)을 예측해보세요.
요구사항:
내가 한풀이
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# 0. 데이터셋 읽어오기
df = pd.read_csv('diabetes.csv')
# print(df)
# 1. 데이터 탐색 및 기본 통계량 출력
# 2. feature과 target 분리 ('Outcome' 컬럼이 타겟 변수)
X = df.drop('Outcome', axis=1)
y = df['Outcome']
# 3. 데이터셋 훈련/테스트 8:2 분할
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2,
random_state=42,
stratify=y # 클래스 비율 유지
)
# print("학습 데이터 크기:", X_train.shape)
# print("테스트 데이터 크기:", X_test.shape)
# 4. 스케일링 (StandardScaler)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # 학습 + 적용
X_test_scaled = scaler.transform(X_test) # 적용만
# 5. K = 3, 5, 7, 9에 대해 모델 학습 및 정확도 비교
k_list = [3, 5, 7, 9]
results = [] # 결과를 저장할 리스트
for k in k_list:
# 모델을 각 k에 대해 생성 후, 학습 진행
model = KNeighborsClassifier(n_neighbors=k)
model.fit(X_train_scaled, y_train)
# 예측 및 평가
y_pred = model.predict(X_test_scaled)
accuracy = accuracy_score(y_pred, y_test) # 예측값과 실제값 비교
print(f"K = {k} 일 때 Test Accuracy: {accuracy:.4f}")
# 각 결과 저장
results.append({"K": k, "Test Accuracy": accuracy})
# 6. 저장한 결과를 표(DataFrame)로 정리 및 출력
results_df = pd.DataFrame(results)
print('results_df \n',results_df)
# 7. 위 표에서 가장 좋은 성능의 모델 선택
best_row = results_df.nlargest(1, 'Test Accuracy') # 가장 성능이 좋은 행(row) 추출하기
print('best_row', best_row)
best_k = best_row['K'].iloc[0]
best_acc = best_row['Test Accuracy'].iloc[0]
print(f"\n가장 좋은 성능의 K: {best_k}")
print(f"해당 K에서의 Test Accuracy: {best_acc:.4f}")
K = 3 일 때 Test Accuracy: 0.6948
K = 5 일 때 Test Accuracy: 0.7013
K = 7 일 때 Test Accuracy: 0.7468
K = 9 일 때 Test Accuracy: 0.7338
results_df
K Test Accuracy
0 3 0.694805
1 5 0.701299
2 7 0.746753
3 9 0.733766
best_row K Test Accuracy
2 7 0.746753
가장 좋은 성능의 K: 7
해당 K에서의 Test Accuracy: 0.7468
트러블 슈팅
# 7. 위 표에서 가장 좋은 성능의 모델 선택
best_row = results_df.nlargest(1, 'Test Accuracy') # 가장 성능이 좋은 행(row) 추출하기
print('best_row', best_row)
best_k = best_row['K'].iloc[0]
best_acc = best_row['Test Accuracy'].iloc[0]
여기서
nlargest쓰는건 배운 적이 없다. Test Accuracy가 일등인 행
그리고 그 행중 k값, Test Accuracy값 '
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
df = pd.DataFrame({
'X': [25, 34, 22, 27, 33, 33, 31, 22, 35, 34, 67, 54, 57, 43, 50, 57, 59, 52, 65, 47, 49, 48, 35, 33, 44, 45, 38, 43, 51, 46],
'y': [79, 51, 53, 78, 59, 74, 73, 57, 69, 75, 51, 32, 40, 47, 53, 36, 35, 58, 59, 50, 25, 20, 14, 12, 20, 5, 29, 27, 8, 7]
})
# 모델 생성 및 학습
# n_clusters: K(=군집의 개수)
# 초기 센트로이드 값 랜덤이라서 random_state=42 지정해야 랜덤 안뜸
# init='k-means++'라는 값 있음 더 똑똑하게 클러스터 정해줌
kmeans = KMeans(n_clusters=4, init='k-means++', random_state=42).fit(df) # 클러스터를 생성(클러스터를 만들 데이터), 다만, x트레인 y트레인 형태가 아닌 전체를, 통째로 넣어주면 됨
centroids = kmeans.cluster_centers_ # 각 클러스터의 중심좌표(centroid)
print(centroids)
'''
[[43.2 16.7]
[29.6 66.8]
[55.1 46.1]]
'''
print(kmeans.labels_)
'''
각 실제 데이터마다의 속한 클러스터 레이블, 매번 출력할때마다 데이터가 바뀜, 데이터 무작위 선택 ,
[1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0] 사실 kmeans도 거리기반이라 스케일링 하는게 맞다고 함
'''
# labels_ : 클러스터가 만들어지고 난 다음에 각 데이터마다 어느 클러스터에 속하는지
# 군집 시각화
# 1. 데이터 포인트들에 대한 산점
# c=점의 색상 지정 (리스트 형태로 값에 따라 색을 다른게 설정)
# labels_ 1111122220000
# alpha=투명도 조절
plt.scatter(df['X'], df['y'], c=kmeans.labels_.astype(float), alpha=0.5)
# 2. 중심정(centroid)에 대한 선점도
plt.scatter(centroids[:, 0], centroids[:, 1], c='red') # x좌표 y좌표 센트로이드 값 빨간색 표시
plt.show()
[[55.1 46.1 ]
[30.83333333 74.66666667]
[27.75 55. ]
[43.2 16.7 ]][1 2 2 1 2 1 1 2 1 1 0 0 0 0 0 0 0 0 0 0 3 3 3 3 3 3 3 3 3 3]

import pandas as pd
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
df = pd.DataFrame({
"X": [
2, 3, 2.5, 3.2, 4, 3.8, 2.9, 3.5, 4.1, 3.3,
12, 13, 12.4, 14, 13.5, 15.2, 14.8, 13.1, 12.9, 15,
3, 4, 2.7, 3.3, 4.5, 3.8, 3.1, 2.9, 4.2, 3.6,
12.5, 13.8, 14.1, 15.3, 16, 14.7, 13.9, 15.8, 16.2, 14.4,
7, 7.5, 6.8, 8, 7.2, 8.5, 7.7, 7.9, 8.3, 6.9
],
"y": [
2, 2.5, 3, 3.2, 2.8, 3.5, 2.7, 3.1, 3.6, 2.9,
3, 2.7, 3.2, 2.9, 3.5, 3.1, 2.8, 2.6, 3.3, 2.7,
12, 11.8, 13, 12.2, 11.5, 12.8, 13.1, 11.7, 12.5, 12.9,
13.5, 14, 14.2, 13.8, 15, 14.5, 13.9, 15.2, 14.8, 13.7,
7, 7.3, 6.8, 7.5, 7.7, 8, 7.2, 8.1, 7.6, 7.4
]})
# Elbow Method
sse = [] # 각 K마다 SSE 값을 저장하기 위한 리스트
k_range = range(1, 10)
for k in k_range:
kmeans = KMeans(n_clusters=k, random_state=42) # 각 K에 대한 K-Means 학습 진행
kmeans.fit(df)
sse.append(kmeans.inertia_) # inertia_ = SSE 값(군집 내 거리의 합)
# Elbow 시각화하기: K값의 변화에 따른 SSE 감소량 선 그래프
plt.plot(k_range, sse, marker='o') # x축: K, y축 값: sse
plt.title('Elbow Method')
plt.xlabel('K')
plt.ylabel('SSE')
plt.grid(True, alpha=0.3)
plt.show()
'''
Q. 최적의 K는?
K=5
'''

import pandas as pd
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt
df = pd.DataFrame({
"X": [
2, 3, 2.5, 3.2, 4, 3.8, 2.9, 3.5, 4.1, 3.3,
12, 13, 12.4, 14, 13.5, 15.2, 14.8, 13.1, 12.9, 15,
3, 4, 2.7, 3.3, 4.5, 3.8, 3.1, 2.9, 4.2, 3.6,
12.5, 13.8, 14.1, 15.3, 16, 14.7, 13.9, 15.8, 16.2, 14.4,
7, 7.5, 6.8, 8, 7.2, 8.5, 7.7, 7.9, 8.3, 6.9
],
"y": [
2, 2.5, 3, 3.2, 2.8, 3.5, 2.7, 3.1, 3.6, 2.9,
3, 2.7, 3.2, 2.9, 3.5, 3.1, 2.8, 2.6, 3.3, 2.7,
12, 11.8, 13, 12.2, 11.5, 12.8, 13.1, 11.7, 12.5, 12.9,
13.5, 14, 14.2, 13.8, 15, 14.5, 13.9, 15.2, 14.8, 13.7,
7, 7.3, 6.8, 7.5, 7.7, 8, 7.2, 8.1, 7.6, 7.4
]})
# 실루엣 점수를 저장하기 위한 리스트 정의
scores = [] # 실루엣 점수를 보관하는 리스트
k_range = range(2, 10) # k의 범위를 2~9
for k in k_range:
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(df) # 전체 데이터에 대해 클러스터 생성
# 각 k마다의 클러스터의 점수를 기록
scores.append(silhouette_score(df, kmeans.labels_))# 군집 안에서 거리
# 각 K마다의 실루엣 점수 출력(-1 ~ 1)
print(scores)
# 실루엣 점수 시각화
# K가 변화할 때 실루엣 점수의 변화를 선그래프 형태
plt.plot(k_range, scores, marker='o', color='orange')
plt.xticks(k_range)
plt.show()
# 최적의 K로 군집화하기
optimal_k = k_range[scores.index(max(scores))]
# 실루엣 점수가 최대가 되는 scores의 인덱스를 반환
# 그 인덱스 바로 최적의 K이므로, 그 인덱스를 k_range에서 가져옴
k_means = KMeans(n_clusters=optimal_k, random_state=42).fit(df) # 최적의 K로 클러스터링
centroids = k_means.cluster_centers_ # 중심좌표
print(centroids) # 2차원 형태 데이터: 각 데이터의 첫번째 값=X좌표, 두번째 값=Y좌표
print(k_means.labels_) # 각 데이터의 레이블(군집)
# 최적의 K로 군집화한 결과 시각화하기
plt.scatter(df['X'], df['y'], c=k_means.labels_.astype(float), s=50, alpha=0.5) # 각각 x,y좌표값 가져오기
plt.scatter(centroids[:, 0], centroids[:, 1], c='red', s=50)
plt.show()
[0.37359000319675295, 0.49052800987090983, 0.7109293140658948, 0.8308446663891611, 0.7835117927282009, 0.6896371242012326, 0.6369416434304874, 0.6169291166432447]

[[13.59 2.98]
[ 7.58 7.46]
[ 3.23 2.93]
[14.67 14.26]
[ 3.51 12.35]][2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3
3 3 3 1 1 1 1 1 1 1 1 1 1]

요구사항:
내가 한 풀이
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples, silhouette_score
# [수정금지] 데이터 생성
np.random.seed(42)
X = np.array([[1, 2], [1.5, 1.8], [5, 8], [8, 8], [1, 0.6],
[9, 11], [8, 2], [10, 2], [9, 3], [2, 1]])
# 1. K=3으로 K-Means 학습/예측 수행하기
kmeans_3 = KMeans(n_clusters=3, init='k-means++', random_state=42)
y_pred_3 = kmeans_3.fit_predict(X) # fit_predict 활용
centroids_3 = kmeans_3.cluster_centers_
# 2. 군집화 결과 시각화하기
plt.scatter(X[:, 0], X[:, 1], c=kmeans_3.labels_.astype(float), s=50, alpha=0.5) # 데이터 X에 대한 x축, y축 데이터 포인트
plt.scatter(centroids_3[:, 0], centroids_3[:, 1], c='red', s=50)
plt.show()
# 3. Elbow Method 수행하기
k_range = range(1, 11)
sse = []
for k in k_range:
# 모델 생성 및 학습 진행
knn = KMeans(n_clusters=k, init='k-means++', random_state=42)
knn.fit(X, y_pred_3)
sse.append(knn.inertia_) # SSE(inertia) 저장
# 3-1. Elbow 시각화
# Elbow Method 시각화
plt.figure(figsize=(10, 6))
plt.plot(k_range, sse, 'bo-', linewidth=2, markersize=10)
plt.xlabel('Number of Clusters (K)', fontsize=12, fontweight='bold')
plt.ylabel('SSE', fontsize=12, fontweight='bold')
plt.title('Elbow Method', fontsize=14, fontweight='bold')
plt.grid(True, alpha=0.3)
plt.show()
'''
Q. Elbow Method를 통해 최적의 K는? 그리고 이유는?
답:
'''
# 4. Silhouette Score
k_range_silh = range(2, 7) # 2~6 범위
silhouette_scores = []
for k in k_range_silh:
kmeans = KMeans(n_clusters=k, init='k-means++', random_state=42)
kmeans.fit(X)
silhouette_scores.append(silhouette_score(X, kmeans.labels_)) # 실루엣 점수 저장하기 interia_
# 5. 최적의 K 구하기
optimal_k = k_range_silh[silhouette_scores.index(max(silhouette_scores))]
print(optimal_k)
# 6. 최적의 K로 군집화 수행
kmeans_final = KMeans(n_clusters=optimal_k, init='k-means++', random_state=42)
cluster_labels = kmeans_final.fit_predict(X) # 학습 및 예측 동시(fit_predict 활용)
print(cluster_labels)
# # 7. 각 샘플의 실루엣 점수 출력
silhouette_avg = max(silhouette_scores) # 최적의 K로 수행한 실루엣 점수 저장
sample_silhouette_values = silhouette_samples(X, cluster_labels)
print(f"전체 평균 Silhouette Score: {silhouette_avg:.4f}")
for idx, score in enumerate(sample_silhouette_values):
print(f" 데이터 {idx} (Cluster {cluster_labels[idx]+1}): {score:.4f}")


3
[1 1 2 2 1 2 0 0 0 1]
전체 평균 Silhouette Score: 0.7157
데이터 0 (Cluster 2): 0.8607
데이터 1 (Cluster 2): 0.8769
데이터 2 (Cluster 3): 0.4264
데이터 3 (Cluster 3): 0.4695
데이터 4 (Cluster 2): 0.8465
데이터 5 (Cluster 3): 0.5311
데이터 6 (Cluster 1): 0.7445
데이터 7 (Cluster 1): 0.7792
데이터 8 (Cluster 1): 0.7825
데이터 9 (Cluster 2): 0.8397
트러블 슈팅
for k in k_range:
# 모델 생성 및 학습 진행
knn = KMeans(n_clusters=k, init='k-means++', random_state=42)
knn.fit(X, y_pred_3)
sse.append(knn.inertia_) # SSE(inertia) 저장
항상 SSE 저장 하는거 잊지 말기.
그리고
for k in k_range_silh:
kmeans = KMeans(n_clusters=k, init='k-means++', random_state=42)
kmeans.fit(X)
silhouette_scores.append(silhouette_score(X, kmeans.labels_)) # 실루엣 점수 저장하기 interia_
이 방식은 최적의 군집갯수 k를 찾기 위해 실루엣 점수를 계산 하는 방식이라
silhouette_scores항상 써주기
최적의 k 구하기는 항상 최댓값.. 항상 코드문이 어렵다..
# 5. 최적의 K 구하기
optimal_k = k_range_silh[silhouette_scores.index(max(silhouette_scores))]
print(optimal_k)
# 6. 최적의 K로 군집화 수행
kmeans_final = KMeans(n_clusters=optimal_k, init='k-means++', random_state=42)
여기서도 파이썬에서 배운 max함수 잊지 말기
# 7. 각 샘플의 실루엣 점수 출력
silhouette_avg = max(silhouette_scores) # 최적의 K로 수행한 실루엣 점수 저장
고객 세분화 데이터를 사용하여 고객 군집을 분석하시오.
Mall_Customers.csvCustomerID, Gender, Age, Annual Income, Spending Score 포함
요구사항:
내가 한 풀이
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
# 시각화 한글 깨짐 방지 설정
plt.rcParams['font.family'] ='Malgun Gothic'
plt.rcParams["axes.unicode_minus"] = False
# 1. 데이터 로드 및 데이터 구조 등 살펴보기(간단한 EDA 진행하기)
df = pd.read_csv('Mall_Customers.csv')
plt.scatter(df['CustomerID'], df['Spending Score (1-100)'], s=50, alpha=0.5)
plt.title('데이터 구조')
plt.xlabel('customerId')
plt.ylabel('Spending Score')
plt.show()
# 2. 데이터프레임에서 'Annual Income'과 'Spending Score' 두 feature만 사용하도록 추출
X = df[['Annual Income (k$)', 'Spending Score (1-100)']]
# 2-1. 스케일링 진행
# +추가로 추출된 데이터에 스케일링(StandardScaler)을 진행합니다.
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 3. Elbow Method와 실루엣 점수를 활용하여 최적의 K 찾기
sse = [] # SSE 저장 리스트
silhouette_scores = [] # 실루엣 점수 저장 리스트
k_range = range(2, 12) # 2부터 11까지
for k in k_range:
k_means = KMeans(n_clusters=k, init='k-means++', random_state=42)
k_means.fit(X_scaled) # 학습 진행하기
sse.append(k_means.inertia_) # SSE 결과 저장 inertia_ = SSE 값(군집 내 거리의 합)
silhouette_scores.append(silhouette_score(X, k_means.labels_)) # 실루엣 점수 저장
# 4. Elbow Method와 실루엣 점수 시각화하기
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))
# 4-1. Elbow Method
ax1.plot(k_range, sse, 'bo-', linewidth=2, markersize=8)
ax1.set_xlabel('Number of Clusters (K)', fontsize=12)
ax1.set_ylabel('Inertia (Within-Cluster Sum of Squares)', fontsize=12)
ax1.set_title('Elbow Method', fontsize=14, fontweight='bold')
ax1.grid(True, alpha=0.3)
# 4-2. Silhouette Score
ax2.plot(k_range, silhouette_scores, 'ro-', linewidth=2, markersize=8)
ax2.set_xlabel('Number of Clusters (K)', fontsize=12)
ax2.set_ylabel('Silhouette Score', fontsize=12)
ax2.set_title('Silhouette Score', fontsize=14, fontweight='bold')
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# # 5. Elbow와 실루엣 점수를 통해 최적의 K 찾기
optimal_k = k_range[silhouette_scores.index(max(silhouette_scores))]# 엘보우 육안(하드코딩), 실루엣 최댓값 구하기
print(f'최적의 K: {optimal_k}')
# # 6. 최적의 K로 군집화하기
k_means_final = KMeans(n_clusters=optimal_k, init='k-means++', random_state=42)
pred = k_means_final.fit_predict(X) # fit_predict: 학습과 동시에 라벨(군집)을 반환하는 역할
centroids = k_means_final.cluster_centers_ # 중심점 반환
# # # 7. 산점도로 군집화 그리기 (X축: Annual Income, Y축: Spending Score)
plt.scatter(X['Annual Income (k$)'], X['Spending Score (1-100)'], c=k_means_final.labels_.astype(float), s=50, alpha=0.5)
plt.scatter(centroids[:, 0], centroids[:, 1], c='red', s=50) # 중심점
plt.show()
# 8. 각 군집에 대한 인사이트 제공
df['Cluster'] = pred # 최종 학습/예측이 완료된 데이터에 대한 클러스터 정보 새 컬럼으로 새로 추가
for cluster_id in range(optimal_k):
# 현재 cluster_id에 해당되는 데이터만 추출
cluster_data = df[df['Cluster'] == cluster_id]
# 추출된 데이터에서 Annual Income과 Spending Score의 평균 구하기
avg_income = cluster_data['Annual Income (k$)'].mean()
avg_spending = cluster_data['Spending Score (1-100)'].mean()
print(f"\nCluster {cluster_id + 1}:")
print(f" - 평균 연소득: ${avg_income:.1f}k")
print(f" - 평균 지출점수: {avg_spending:.1f}")
# 고객 군집 구분에 따른 구체적인 인사이트(예시)
# - 평균 소득이 60 초과: 고소득
# - 평균 소득이 40 미만: 저소득
# - 평균 지출이 60 초과: 고지출
# - 평균 지출이 40 미만: 저지출
if avg_income > 60:
insight = "[VIP]: 고소득-고지출 → 프리미엄 제품 및 멤버십 프로그램 제공"
elif avg_income < 40:
insight = "[잠재고객]: 고소득-저지출 → 가치 제안 강화 및 맞춤형 프로모션 필요"
elif avg_spending > 60:
insight = "[위험군]: 저소득-고지출 → 할부 상품 및 적립 프로그램 제공"
elif avg_spending < 40:
insight = "[가격민감군]: 저소득-저지출 → 저가 상품 라인 및 할인 쿠폰 제공"
else:
insight = "[일반고객]: 중소득-중지출 → 균형잡힌 마케팅 전략 적용"
print(insight) # 인사이트 출력
# 9. 요약 테이블 정리: 군집 별로 그룹화를 진행 후
# agg(): 각 컬럼을 어떤 집계함수로 요약할 것인지에 대한 함수
# agg() 인자의 딕셔너리 key:value 구조 = '컬럼 이름' : '집계 함수 이름'
summary = df.groupby('Cluster').agg({
'CustomerID' : 'count', # 고객의 수
'Annual Income (k$)' : 'mean', # 소득의 평균
'Spending Score (1-100)' : 'mean', # 지출의 평균
'Age' : 'mean', # 나이의 평균
}).round(2)
print(summary) # 출력


최적의 K: 5

Cluster 1:
Cluster 2:
Cluster 3:
Cluster 4:
Cluster 5:
트러블 슈팅
silhouette_scores.append(silhouette_score(X, k_means.labels_)) # 실루엣 점수 저장
이것도 잊지말기
kmeans.labels
의 각 데이터 포인트(샘플)가 최종적으로 할당된 군집(클러스터)의 번호(레이블)**를 담고 있는 배열, 모델이 수행한 군집화의 결과 자체를 의미
# 추출된 데이터에서 Annual Income과 Spending Score의 평균 구하기
avg_income = cluster_data['Annual Income (k$)'].mean()
avg_spending = cluster_data['Spending Score (1-100)'].mean()
순간 이것도 당황함 mean함수가 생각 안남
# 9. 요약 테이블 정리: 군집 별로 그룹화를 진행 후
# agg(): 각 컬럼을 어떤 집계함수로 요약할 것인지에 대한 함수
# agg() 인자의 딕셔너리 key:value 구조 = '컬럼 이름' : '집계 함수 이름'
summary = df.groupby('Cluster').agg({
'CustomerID' : 'count', # 고객의 수
'Annual Income (k$)' : 'mean', # 소득의 평균
'Spending Score (1-100)' : 'mean', # 지출의 평균
'Age' : 'mean', # 나이의 평균
}).round(2)
agg 함수도 주석내용을 보며 겨우 풀었다.