김자영 강사님
# 독립 변수 X
X = df.drop(['Launched?], axis=1)
# 종속 변수 y
y = df['Launched?']
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier(random_state=42, max_depth=5)
model.fit(X_train, y_train)
pred_test = model.predict(X_test) # 테스트 세트 예측
pred_train = model.predict(X_train) # 훈련 세트 예측
predict(X_test)
: 테스트 데이터를 사용해 모델이 예측한 발사 여부 계산predict(X_train)
: 훈련 데이터를 사용해 모델이 예측한 발사 여부 계산from sklearn.metrics import classification_report
print(f'''test score >>>>>>>>>>
{classification_report(y_test, pred_test)}''')
print(f'''train score >>>>>>>>>>
{classification_report(y_train, pred_train)}''')
classification_report(y_test, pred_test)
: 테스트 세트에 대한 모델 성능을 평가하는 보고서 출력classification_report(y_train, pred_train)
: 훈련 세트에 대한 성능 평가 출력# 테스트 세트에 대한 성능
test_accuracy = accuracy_score(y_test, pred_test)
test_precision = precision_score(y_test, pred_test)
test_recall = recall_score(y_test, pred_test)
test_f1_score = f1_score(y_test, pred_test)
test_cm = confusion_matrix(y_test, pred_test)
# 훈련 세트에 대한 성능
train_accuracy = accuracy_score(y_train, pred_train)
train_precision = precision_score(y_train, pred_train)
train_recall = recall_score(y_train, pred_train)
train_f1_score = f1_score(y_train, pred_train)
train_cm = confusion_matrix(y_trian, pred_train)
accuracy_score
: 전체 데이터 중에서 모델이 올바르게 예측한 비율precision_score
: '발사됨(Y)'으로 예측한 것들 중에서 실제로 발사된 경우의 비율recall_score
: 실제로 발사된 것들 중에서 모델이 올바르게 발사됨으로 예측한 비율f1_score
: 정밀도와 재현율의 조화 평균을 계산confusion_matrix
: 예측값과 실제값의 비교를 통해 혼동행렬 만들기# StratifiedKFold 설정
from sklearn.model_selection import StratifiedKFold, cross_val_score
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42
# cross_val_score 함수로 교차검증 수행
cross_val_score(model, X_train, y_train, scoring='f1', cv=skf).mean()
cv=skf
: Stratified KFold로 데이터를 5등분하여 교차검증 수행
# 모델 최종 학습 및 테스트 세트 평가
model.fit(X_train, y_train)
pred = model.predict(X_test)
from sklearn.metrics import classification_report
print(classification_report(y_test, pred)
# 결정 트리 시각화
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt
plt.figure(figsize=(15, 10)) # 그림 크기 설정
plot_tree(model, feature_names=X.columns, filled=True)
plt.show())
plot_tree
: 결정 트리 모델을 시각화하는 함수feature_names=X.columns
: 트리의 각 노드에 변수 이름 표시filled=True
: 노드 색상을 통해 예측된 클래스 비율을 시각적으로 나타냄# 트리 깊이 확인
model.get_depth()
학습된 트리 모델의 깊이 반환. 깊이가 깊으면 트리가 더 복잡하게 학습한 것으로, 과적합 가능성을 높일 수 있다.
# 특성 중요도 시각화
import seaborn as sns
print(f'특성의 중요도 >>> {model.feature_importances_}')
# 막대 그래프
plt.figure(figsize=(4, 3))
sns.barplot(x=model.feature_importances_, y=X.columns)
plt.show()
model.feature_importances_
: 각 특성의 중요도 반환. 값이 클수록 해당 특성이 예측에 더 많은 영향을 미쳤음을 의미sns.barplot
: 특성 중요도를 막대 그래프로 시각화. x
에 중요도 값, y
에 특성 이름을 넣어 그래프를 그린다.# 특정 특성에 따른 발사 여부 히스토그램
sns.histplot(data=df, x='Wind Speed at Launch Time', hue='Launched?')
sns.histplot
: 히스토그램을 그리는 함수로 x
에 분석할 특성을 넣고, hue
에 색상으로 구분할 범주형 변수를 넣는다.x='Wind Speed at Launch Time
: 발사 시점 바람의 속도hue='Launched?'
: 로켓 발사 여부에 따라 바람 속도 분포를 색상으로 구분# 변수 재선택하여 다시 학습 및 평가
# 사용할 특성(X)에서 특정 변수 제거
X = X.drop(['Wind Speed at Launch Time', 'Temp at Launch Time', 'Crewed or Uncrewed'], axis=1)
X.drop(...)
: 지정한 열 제거axis=1
: 열을 제거하겠다는 의미# 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
# 모델 생성 및 훈련
model = DecisionTreeClassifier(random_state=42)
# 모델 학습
model.fit(X_train, y_train)
# 예측
pred_train = model.predict(X_train)
pred_test = model.predict(X_test)
# 평가
print(f'test >> {classification_report(y_test, pred_test)}')
print(confusion_matrix(y_test, pred_test))
print(f'train >> {classification_report(y_train, pred_train)}')
# 모델 학습 결과
# 결정 트리 시각화
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt
plt.figure(figsize=(5, 5))
plot_tree(model, feature_names=X.columns, filled=True)
plt.show()
feature_names=X.columns
: 각 노드에 해당 변수 이름 표시 계속 까먹는 부분은 한 번 더 적기
# 특성 중요도 시각화
import seaborn as sns
sns.barplot(y=X.columns, x=model.feature_importances_)
model.feature_importances_
: 모델이 학습한 각 특성의 중요도를 반환. 값이 높을수록 해당 특성이 예측에 더 많은 영향을 미침을 의미!# 박스플롯 시각화
sns.boxplot(data=df, y='Ave Temp', hue='Launched?')
hue='Launched?'
: 'Launched?' 변수에 따라 박스를 색상으로 구분하여 시각화
# 트리 깊이 확인
model.get_depth()
categorical_var = ['Wind Direction', 'Condition']
numeric_var = ['High Temp', 'Low Temp', 'Ave Temp', 'Hist High Temp', 'Hist Low Temp', 'Hist Ave Temp', 'Hist Ave Percipitation', 'Max Wind Speed', 'Visibility']
X['Launched?'] = y
categorical_var
: 범주형 변수 리스트.numeric_var
: 수치형 변수 리스트.X['Launched?'] = y
: 원래 데이터프레임 X
에 y
에 저장되어 있는 값을 Launched?
라는 이름의 열으로 추가plt.figure(figsize=(15, 15))
for i, col in enumerate(numeric_var):
plt.subplot(3, 3, i+1)
sns.boxplot(data=X, y=col, hue='Launched?') # 'Launched?'에 따라 색상 구분
plt.title(col)
plt.subplot(3, 3, i+1)
: 3*3 그리드에서 i번째 서브플롯 생성plt.title(col)
: 각 플롯의 제목으로 해당 변수 이름 설정plt.figure(figsize=(15, 4))
for i, col in enumerate(categorical_var):
plt.subplot(1, 2, i+1)
sns.countplot(data=X, x=col, hue='Launched?')
plt.title(col)
plt.subplot(1, 2, i+1)
: 1*2 그리드에서 i번째 서브플롯 생성# 필요한 라이브러리 임포트
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 테스트 데이터 생성
from sklearn.datasets import make_blobs
features, targets = make_blobs(n_samples=200,
n_features=2,
centers=3,
cluster_std=0.8,
random_state=0)
make_blobs
: 데이터를 군집화 테스트에 사용할 수 있도록 가상의 데이터 생성n_samples=200
: 200개의 데이터 생성n_features=2
: 2개의 특성(변수)을 가진 데이터 만들기centers=3
: 3개의 군집 만들기cluster_std=0.8
: 군집 내 데이터가 퍼져 있는 정도(표준편차)를 0.8로 설정random_state=0
: 동일한 결과를 재현할 수 있도록 난수 시드 고정# 생성된 데이터 형태 출력
print(features.shape, targets.shape)
features
: (200, 2) 형태의 200개 데이터와 2개 특성을 가진 배열targets
: (200,) 형태의 각 데이터가 속한 군집(0, 1, 2 중 하나)을 나타내는 레이블#DataFrame으로 변환
cluster_df = pd.DataFrame(features, columns=['feature1', 'feature2'])
clsuter_df['target'] = targets
pd.DataFrame(features, columns=['feature1', 'feature2'])
: features
데이터를 pandas
데이터프레임으로 변환, feature1
, feature2
라는 두 개 열로 데이터를 구성cluster_df['target'] = targets
: 각 데이터가 속한 군집(0, 1, 2)을 target
열에 추가# 타겟 데이터 빈도수 확인
cluster_df['target'].value_counts()
value_counts()
: 각 군집(0, 1, 2)에 속하는 데이터의 개수를 세어준다.
# 데이터 시각화
sns.scatterplot(data=cluster_df, x='feature1', y='feature2', hue='target', palette='muted')
plt.title('original Data')
plt.show()
sns.scatterplot
: seaborn
을 이용해 각 데이터 포인트를 군집별로 시각화x='feature1'
, y='feature2
: 두 개의 특성(변수)을 각각 x축과 y축에 표시hue='target'
: 각 데이터 포인트를 군집별로 색상을 다르게 표시palette='muted'
: 색상을 약간 부드럽게 표현# KMeans 객체 생성
from sklearn.cluster import KMeans
km = KMeans(n_clusters=3)
KMeans(n_clusters=3)
: K-means
알고리즘을 사용해 3개의 군집으로 데이터를 나누는 객체 생성n_clusters=3
: 3개의 군집을 만들겠다는 의미# 데이터 학습 및 군집화
kmeans_cluster = km.fit_predict(features)
fit_predict()
: 주어진 데이터를 학습하고 각 데이터가 어느 군집에 속하는지 예측fit
: 데이터를 학습하여 군집의 중심을 찾는다.predict
: 각 데이터 포인트를 가장 가까운 군집 중심에 할당kmeans_cluster
: 각 데이터가 속한 군집의 레이블(0, 1, 2)을 담고 있다.# 군집 결과를 데이터프레임에 추가
cluster_df['kmeans_cluster'] = kmeans_cluster
kmeans_cluster
로 예측한 군집 레이블을 cluster_df
에 kmeans_cluster
라는 새로운 열로 추가
# 클러스터 중심 확인
km.cluster_centers_
cluster_centers_
: 각 군집의 중심 좌표 반환. 이 촤표는 2차원 공간에서 각 군집을 대표하는 중심이다.
# 군집화 결과 시각화
sns.scatterplot(data=cluster_df,
x='feature1',
y='feature2',
hue='kmeans_cluster',
palette='muted')
hue='kmeans_cluster'
: 각 군집별로 데이터 포인트의 색상을 다르게 표시
# 군집의 중심 시각화
sns.scatterplot(x=km.cluster_centers_[:,0],
y=km.cluster_centers_[:,1],
color='magenta',
marker='X')
km.cluster_centers_[:,0]
, km.cluster_centers_[:,1]
: 각 군집 중심의 x, y 좌표를 가져온다.marker='X'
: 각 군집 중심을 X 모양으로 표시color='magenta'
: 군집 중심은 자주색으로 표시# 그래프 표시
plt.title('k-means Clustering')
plt.show()
엘보우 방법(Elbow Method) 은 군집의 개수를 늘려가면서 각 군집 내 데이터 포인트들이 중심에 얼마나 가까이 있는지를 측정하는 이너셔(Inertia) 값을 기반으로 한다. 이너셔는 클러스터 중심과 데이터 포인트들 사이 거리의 제곱합을 나타내며, 군집 내 데이터들이 얼마나 밀집되어 있는지 보여준다.
# 이너셔(Inertia) 계산
inertia = []
for n in range(2,7):
km = KMeans(n_clusters=n)
inertia.append(km.inertia_)
# 이너셔 값을 시각화
plt.plot(range(2, 7), inertia, marker='o')
plt.xlabel('k')
plt.ylabel('Inertia')
plt.show()
실루엣 분석은 군집화가 얼마나 잘 되었는지 평가하는 지표인 실루엣 계수(Silhouette Coefficient) 를 사용한다. 각 데이터 포인트가 자신이 속한 군집 내에서 얼마나 잘 묶여 있는지와 다른 군집과는 얼마나 잘 분리되어 있는지를 측정한다.
# 개별 실루엣 계수 계산
from sklearn.metrics import silhouette_samples
cluster_df['silhouette'] = silhouette_samples(features, kmeans_cluster)
silhouette_samples
: 각 데이터 포인트에 대한 실루엣 계수 계산cluster_df
에 silhouette
열을 추가하여 각 데이터 포인트의 실루엣 계수 확인# 잘못 할당된 데이터 확인
cond = cluster_df['silhouette'] < 0
cluster_df.loc[cond]
cluster_df['silhouette'] < 0
: 실루엣 계수가 0보다 작은 데이터(다른 군집에 잘못 할당된 데이터)를 찾는다.cluster_df.loc[cond]
: cond
가 True
인 행만 선택한다. (잘못된 군집에 할당된 데이터만 반환한다.)# 평균 실루엣 계수 계산
from sklearn.metrics import silhouette_score
silhouette_score(features, kmeans_cluster)
silhouette_score
: 전체 군집화의 품질을 평가하는 평균 실루엣 계수를 계산
# 실루엣 분석 시각화 함수
import silhouette_analysis as s
for k in range(2, 7):
s.silhouette_plot(features, k)
silhouette_plot(features, k)
: 실루엣 분석을 시각화하는 함수. 다양한 군집 개수(K)에 대해 군집화 결과를 실루엣 그래프로 시각화하여 최적의 군집 개수를 찾을 수 있다. 강사님이 주신 모듈 안에 들어있던 함수
DBSCAN은 밀도 기반 군집화 알고리즘으로 데이터가 밀집된 영역을 군집으로 인식한다.
1. Epsilon(ε): 한 점을 중심으로 하는 반경의 크기.
2. MinPts: 이 반경 내에 포함되어야 할 최소 데이터 포인트 수.
DBSCAN은 불규칙한 모양의 군집을 탐지하고 이상치(노이즈) 를 잘 식별하는 장점이 있다.
# 데이터 생성
from sklearn.datasets import make_circles
X, y = make_circles(n_samples=1000, shuffle=True, noise=0.05, random_state=0, factor=0.5)
make_circles
: Scikit-learn의 함수로, 두 개의 동심원(circle) 형태의 2D 데이터를 생성한다.n_samples=1000
: 총 1000개의 샘플(포인트)을 생성.shuffle=True
: 데이터를 무작위로 섞는다.noise=0.05
: 원형 데이터를 약간의 노이즈를 추가해 비선형적으로 만든다.factor=0.5
: 작은 원과 큰 원의 크기 비율을 설정. factor=0.5
는 작은 원의 반지름이 큰 원의 절반임을 의미한다.X
: 생성된 데이터 포인트 (각각 feature1
과 feature2
로 이뤄진 2차원 좌표값)y
: 각 데이터 포인트가 속하는 클래스(0 또는 1).# 데이터프레임 생성
df = pd.DataFrame(X, columns=['feature1', 'feature2'])
df['target'] = y
# 데이터 시각화
sns.scatterplot(data=df, x='feature1', y='feature2', hue='target', palette='muted')
plt.show()
# K-means 클러스터링
from sklearn.cluster import KMeans
km = KMeans(n_clusters=2)
df['kmeans'] = km.fit_predict(X)
KMeans(n_clusters=2)
: K-means 알고리즘을 사용해 데이터에서 2개의 클러스터를 찾는다.km.fit_predict(X)
: K-means 알고리즘을 학습하고 각 데이터 포인트가 어느 군집에 속하는지 예측df['kmeans'] = km.fit_predict(X)
: 예측된 군집 번호를 데이터프레임 df
에 새로운 열 'kmeans'
로 추가하여 각 데이터 포인트가 속한 클러스터를 기록# 데이터 시각화
sns.scatterplot(df, x='feature1', y='feature2', hue='kmeans', palette='muted')
feature1
과 feature2
값을 기준으로 데이터 포인트를 그린다.hue='kmeans'
: K-means에 의해 예측된 클러스터 번호(kmeans
열에 저장된 값)에 따라 색상을 다르게 지정# 클러스터 중심 시각화
sns.scatterplot(x=km.cluster_centers_[:,0], y=km.cluster_centers_[:,1],
marker='D', color='magenta')
km.cluster_centers_
: K-means 알고리즘이 찾은 두 군집의 중심 좌표 반환km.cluster_centers_[:,0]
, km.cluster_centers_[:,1]
: 두 군집의 중심 좌표에서 각각 x
와 y
값을 추출marker='D'
: 클러스터 중심을 다이아몬드(D
) 모양으로 표시# 플롯 타이틀 추가 및 그래프 출력
plt.title('k-means clustering')
plt.show()
# DBSCAN 클러스터링
from sklearn.cluster import DBSCAN
dbscan = DBSCAN(eps=0.2, min_samples=10)
df['dbscan'] = dbscan.fit_predict(X)
eps=0.2
: 각 데이터 포인트를 중심으로 탐색할 반경(입실론, ε)을 설정. 이 반경 내에 다른 포인트들이 있으면 군집이 형성된다.min_samples=10
: 각 데이터 포인트가 Core Point로 간주되려면 반경 eps
내에 최소 10개의 이웃이 있어야 한다.dbscan.fit_predict(X)
: DBSCAN 알고리즘을 X
데이터에 적용하여 각 데이터 포인트가 어느 군집에 속하는지 또는 이상치인지 예측한다. 군집에 속하지 않는 이상치 포인트는 -1로 표시된다.df['dbscan'] = dbscan.fit_predict(X)
: 예측된 군집 번호 또는 노이즈 정보를 데이터프레임 df
에 'dbscan'
이라는 새 열로 추가하여 저장# 데이터 시각화
sns.scatterplot(df, x='feature1', y='feature2', hue='dbscan')
hue=dbscan
: DBSCAN에 의해 예측된 군집 번호 혹은 노이즈 값에 따라 색상을 다르게 지정. 군집에 속한 포인트는 각 군집마다 다른 색상으로 나타나며 노이즈(-1) 로 분류된 포인트는 별도의 색상으로 구분된다.
# 그래프 타이틀 추가 및 출력
plt.title('DBSCAN')
plt.show()
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_iris
iris = load_iris()
df_iris = pd.DataFrame(iris.data, columns=iris.feature_names)
df_iris['species'] = iris.target
iris = load_iris()
: 붓꽃 데이터를 로딩하여 변수 iris
에 저장. 이 데이터셋은 iris.data
와 iris.target
으로 구성된다.pd.DataFrame(iris.data, columns=iris.feature_names)
: iris.data
는 붓꽃 데이터의 특성 값들이며, 이를 판다스 데이터프레임으로 변환. feature_names
는 각각의 특성 이름.df_iris['species'] = iris.target
: 데이터프레임에 'species' 라는 새로운 열 추가. 여기에는 붓꽃의 종을 나타내는 타겟 값(0, 1, 2) 이 저장된다. 이 값은 각각 Setosa(0), Versicolor(1), Virginica(2) 로 구분된다.df_iris.sample(3)
데이터프레임에서 임의의 3개의 샘플 데이터를 출력하여 데이터를 미리 확인할 수 있다.
# K-means 클러스터링 및 이너셔(Inertia) 계산
from sklearn.cluster import KMeans
inertia = []
for n in range(2, 7):
km = KMeans(n_clusters=n)
km.fit(iris.data)
print(km.inertia_)
inertia.append(km.inertia_)
KMeans(n_clusters=n)
: K-means 알고리즘에서 n_clusters
를 n
으로 설정하여 n
개의 클러스터로 데이터를 군집화. 여기서 n
은 2부터 6까지 반복된다.km.fit(iris.data)
: Iris 데이터셋을 이용해 K-Means 모델을 학습시킨다.km.inertia_
: 이너셔(Inertia) 는 군집 내 데이터포인트들이 군집의 중심(centroid)과 얼마나 가까운지 나타내는 값이다. 이너셔 값이 작을수록 각 군집의 중심으로 데이터가 더 밀집해 있음을 의미한다. 이 값은 클러스터 내 데이터 포인트 간의 거리 제곱합으로 계산된다.# 엘보우 기법 그래프 시각화
plt.plot(range(2, 7), inertia, marker='o')
plt.xticks(range(2, 7))
plt.xlabel('k')
plt.ylabel('inertia')
plt.show()
plt.plot(range(2, 7), inertia, marker='o')
: x축에 클러스터 개수 k
, y축에 이너셔 값을 대응시킨 엘보우 그래프를 그린다. marker='o'
는 데이터 포인트를 원형 마커로 표시한다.plt.xticks(range(2, 7))
: x축 값(클러스터 개수)을 2에서 6까지 표시plt.xlabel('k')
, plt.ylabel('inertia')
: x축에는 클러스터 개수 k
, y축에는 이너셔 값을 라벨로 표시for k in range(2, 5):
s.silhoette_plot(iris.data, k)
위에서 사용했던 silhouette_analysis
모듈을 사용하여 실루엣 분석을 진행. 주어진 데이터 iris.data
에 대해 클러스터 수를 2부터 4까지 바꾸면서 실루엣 점수를 계산, 그 결과를 시각화한다.
km = KMeans(n_clusters=3)
df_iris['kmeans'] = km.fit_predict(iris.data)
df_iris.sample(3)
# 클러스터링 결과 확인
df_iris[['species', 'kmeans']].value_counts()
species
데이터를 비교하여 각 클러스터에 할당된 데이터 개수를 확인한다.# 시각화
df = df_iris.iloc[:,[0,1,2,3,5]]
sns.pairplot(df, hue='kmeans', palette='muted')
df_iris
에서 필요한 열들(특성 4개와 K-means 결과)을 선택, pairplot
을 그린다.
from sklearn.cluster import DBSCAN
dbscan = DBSCAN(eps=0.8, min_samples=5)
df_iris['dbscan'] = dbscan.fit_predict(iris.data)
eps=0.8
: 반경, 각 데이터 포인트 주변에 이 거리 내에 최소한 min_samples=5
개의 데이터가 있어야 같은 클러스터로 묶인다.fit_predict()
: 데이터를 학습, 클러스터 할당 결과를 반환. 결과는 df_iris
의 dbscan
열에 저장된다.# 클러스터링 결과 출력
display(df_iris.sample(3))
print(df_iris['dbscan'].value_counts())
df_iris['dbscan'].value_counts()
: 각 클러스터에 할당된 데이터 포인트의 수를 출력-1
: 노이즈 포인트# DBSCAN 결과 시각화
df = df_iris.iloc[:,[0,1,2,3,6]]
sns.pairplot(df, hue='dbscan', palette='muted')
plt.show()
df_iris
에서 4개의 특성과 DBSCAN 결과를 확인하여 pairplot
을 그린다.hue='dbscan'
으로 각 클러스터를 서로 다른 색으로 구분하여 시각화import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
np.set_printoptions(suppress=True, precision=8)
np.set_printoptions
: 출력될 배열이나 숫자 형식을 지정suppress=True
: 지수 표기법 억제precision=8
: 소수점 이하 8자리까지 숫자를 표시하도록 설정# CSV 파일 불러오기
hitter1 = pd.read_csv('https://github주소')
hitter2 = "
hitter3 = "
github 주소로도 데이터를 불러올 수 있다는 걸 강사님 통해서 배웠다.
이 실습에서 배운 건 아니고, 전에 언제 실습에서 배웠는데,, 기억 안남.
# 데이터 크기 확인
print(f'hitter1 >>> {hitter1.shape}')
print(f'hitter2 >>> {hitter2.shape}')
print(f'hitter3 >>> {hitter3.shape}')
shape
속성은 데이터의 행(row)과 열(column) 개수를 나타낸다.hitter1.shape
: hitter1
데이터 프레임의 행과 열 수를 알려준다.hitter_concat = pd.concat([hitter1, hitter2, hitter3], ignore_index=True)
pd.concat()
: 여러 데이터프레임을 세로로 연결(병합)하는 함수[]
안에 합치고자 하는 데이터프레임들을 순서대로 넣는다.ignore_index=True
: 기존 인덱스를 무시, 새로운 연속적인 인덱스를 부여X = hitter_concat[['OPS', 'ISO', ..., 'XR']]
y = hitter_concat['YrPlayer']
# StandardScaler 임포트 및 객체 생성
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
StandardScaler
: sklearn
에서 제공하는 표준화 도구scaler = StandardScaler()
: StandardScaler
객체 생성
scaler = StandardScaler()
처럼 객체를 미리 생성하는 이유는 코드의 유연성과 재사용성을 높이고 여러 번 사용할 수 있도록 하기 위함이다. (출처: ChatGPT)
# 데이터 변환
X.loc[:, 'OPS':'XR'] = scaler.fit_transform(X)
X.loc[:, 'OPS':'XR']
: loc
를 사용해 X
데이터 프레임에서 OPS
부터 XR
까지의 열을 선택. 이 열들을 스케일링 대상으로 설정.fit_transform(X)
: StandardScaler
의 fit_transform()
메소드를 사용해 데이터를 표준화fit
: 데이터의 평균과 표준편차를 계산transform
: 이를 이용해 각 열의 값을 표준화# 라이브러리 임포트
from sklearn.cluster import KMeans
# 클러스터 개수별 KMeans 실행 및 관성 값 저장
inertia = []
for n in range(2,7):
km = KMeans(n_clusters=n)
km.fit(X)
print(km.inertia_)
inertia.append(km.inertia_)
inertia = []
: 관성 값을 저장할 빈 리스트for n in range(2,7)
: 클러스터 개수 k를 2부터 6까지 변경하면서 K-평균을 반복 실행n_clusters=n
: k-means의 클러스터 개수 설정km.fit(X)
: 선택한 클러스터 개수로 데이터 X에 KMeans 모델을 학습시킨다.km.inertia_
: 관성 값을 반환. 관성 값이 클수록 클러스터 내 데이터 점들이 멀리 퍼져 있다는 뜻.# 엘보우 그래프 그리기
plt.plot(range(2,7), inertia, marker='o')
plt.xticks(range(2,7))
plt.xlabel('k')
plt.ylabel('inertia')
plt.show()
plt.plot(range(2,7), inertia, marker='o'
: k 값(2~6) 을 x축에, 관성 값을 y축에 두고 선 그래프 를 그린다. marker='o'
는 각 점을 동그라미로 표시.plt.xticks(range(2,7))
: x축의 눈금을 2부터 6까지 설정plt.xlabel('k')
, plt.ylabel('inertia')
: x축 레이블을 'k', y축 레이블을 'inertia'로 설정# 실루엣 분석을 통한 최적의 k 찾기
import silhouette_analysis as s
for k in range(2,6):
s.silhouette_plot(X, k)
강사님께서 주신 silhouette_analysis 모듈 사용.
# k-means clustering
from sklearn.cluster import KMeans
km = KMeans(n_clusters=4, random_state=42)
kmeans_cluster = km.fit_predict(X)
kmeans_cluster
n_clusters=4
: 실루엣 분석 결과에서 k=4가 적합하다고 판단되어 4개의 클러스터로 설정.km.fit_predict(X)
: KMeans
객체의 fit_predict()
메소드를 사용해 X 데이터를 학습시키고 각 데이터가 속하는 클러스터 레이블을 예측kmeans_cluster
변수에 저장되며 이는 데이터가 속하는 클러스터 번호를 나타낸다.df = pd.DataFrame(X, columns=X.columns)
df['kmeans_cluster'] = kmeans_cluster
df.head()
pd.DataFrame(X, columns=X.columns)
: 표준화된 데이터 X
를 사용하여 새로운 데이터 프레임 df
를 생성. X.columns
는 원래의 열 이름을 유지.df[kmeans_cluster'] = kmeans_cluster
: 클러스터링 결과(kmeans_cluster
)를 데이터프레임 df
에 추가.# pairplot을 사용한 시각화
sns.pairplot(df, hue='kmeans_cluster', palette='muted')
plt.show()
sns.pairplot()
: Seaborn의 pairplot 함수는 여러 변수 간의 쌍변수 관계를 그려주는 함수이다. 즉 각 변수들의 2D 산점도를 만들어 데이터의 분포를 시각화한다.# 변수 선택
cols = df.columns[:-1]
df.columns[:-1]
: 데이터프레임 df
에서 마지막 열(kmeans_cluster)을 제외한 나머지 열들을 선택. 즉 클러스터링에 사용된 X만 대상으로 시각화 준비.
# 박스플롯 그리기
plt.figure(figsize=(15,8))
for i, col in enumerate(cols):
plt.subplot(2,4,i+1)
sns.boxplot(data=df, y=col, hue='kmeans_cluster', palette='muted')
plt.title(col)
plt.tight_layout()
for i, col in enumerate(cols)
: cols
에 포함된 각 변수에 대해 반복적으로 박스플롯을 그린다.plt.subplot(2,4,i+1)
: 한 화면에 2행 4열의 서브플롯을 그리고, i+1
번째 위치에 해당 변수의 박스플롯을 그린다.plt.tight_layout()
: 그래프 간 간격을 자동 조정하여 겹치지 않고 보기 좋게 배치되도록 한다.# 주성분 계산
from sklearn.decomposition import PCA
pca = PCA()
principal_components = pca.fit_transform(X)
printcipal_components.shape
from sklearn.decomposition import PCA
: scikit-learn
라이브러리에서 PCA 모듈을 가져온다.pca = PCA()
: PCA 객체 생성. 기본적으로 모든 주성분을 계산하도록 설정된다.principal_components = pca.fit_transform(X)
: 데이터 X
에 대해 PCA를 수행하여 주성분을 계산fit_transform
: PCA를 적용(fit) 하고 변환(transfrom) 하여 주성분을 반환# 컬럼별 설명된 분산 비율 확인
explained_variance = pca.explained_variance_ratio_
explained_variance = pca.explained_variance_ratio_
: 각 주성분이 설명하는 분산 비율을 저장. 이 값은 각 주성분이 데이터의 전체 변동성을 얼마나 설명하는지 나타낸다. (explained_variance[0]
: 첫번째 주성분이 설명하는 분산 비율)
# 누적 분산 확인
cumulative_variance = explained_variance.cumsum()
cumulative_variance = explained_variance.cumsum()
: 각 주성분의 설명된 분산 비율의 누적 합 계산. 이를 통해 몇 개의 주성분을 사용해야 전체 변동성의 몇 %를 설명할 수 있는지 알 수 있다. (cumulative_variance[2]
: 첫번째, 두번째, 세번째 주성분이 합쳐서 설명하는 변동성을 나타낸다.)
# screeplot 그리기
plt.figure(figsize=(4,3))
plt.plot(explained_variance, marker='o', ls='--')
plt.xlabel('Principal Component')
plt.title('Scree Plot')
plt.ylabel('Explained Variance Ratio')
plt.gird(ls=':')
plt.show()
ls='--'
: 선을 점선으로 설정plt.grid(ls=':')
: 그래프에 점선 그리드 추가# 2개의 주성분 추출
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
principal_components = pca.fit_transform(X)
pca = PCA(n_components=2)
: PCA 객체를 생성하면서 추출할 주성분의 개수를 2로 설정.
# 데이터프레임 생성
df_pca = pd.DataFrame(principal_components, columns=['pca1', 'pca2'])
추출된 주성분을 사용하여 새로운 데이터 프레임 df_pca
생성
from sklearn.cluster import KMeans
# 최적의 k 찾기
inertia = []
for k in range(2, 7):
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(df_pca)
inertia.append(kmeans.inertia_)
kmeans = KMeans(n_clusters=k, random_state=42)
: 클러스터 수를 k로 설정하여 KMeans 객체를 생성.kmeans.fit(df_pca)
: PCA로 변환된 데이터프레임 df_pca
에 k-means clustering을 적합시킨다. 클러스터 중심이 계산된다.inertia.append(kmeans.inertia_)
: 현재 k 값에 대한 관성을 리스트 inertia
에 추가.# 결과 시각화
`plt.figure(figsize=(5, 4))
plt.plot(range(2, 7), inertia, marker='o')
plt.xticks(range(2, 7))
plt.xlabel('k')
plt.ylabel('inertia')
plt.show()
# k-means clustering
kmeans = KMeans(n_clusters=4, random_state=42)
df_pca['pca_cluster'] = kmeans.fit_predict(df_pca)
kmeans = KMeans(n_clusters=4, random_state=42)
: 클러스터 수를 4로 설정하여 KMeans 객체 생성df_pca['pca_cluster'] = kmeans.fit_predict(df_pca)
: PCA로 변환된 데이터프레임 df_pca
에 k-means clustering을 적용하여 각 데이터 포인트가 속하는 클러스터를 예측, 그 결과를 'pca_cluster'
라는 새로운 열에 저장.# 군집 결과 시각화
sns.scatterplot(data=df_pca, x='pca1', y='pca2', hue='pca_cluster', palette='muted')
x='pca1'
, y='pca2'
: x축과 y축에 각각 첫번째 주성분과 두번째 주성분을 사용hue='pca_cluster'
: 데이터 포인트 색상을 클러스터 레이블에 따라 다르게 표시# 원본 데이터프레임에 군집 정보 추가
df['pca_cluster'] = df_pca['pca_cluster']
PCA 클러스터 레이블을 원본 데이터프레임 df
에 새로운 열 'pca_cluster'
로 추가
# 클러스터 값의 빈도수 확인
df[['kmeans_cluster', 'pca_cluster']].value_counts()
원본 데이터프레임 df
에서 'kmeans_cluster'
와 'pca_cluster'
두 열의 조합에 대한 빈도 수를 계산. >> 각 군집의 조합 개수를 보여준다.
df['player'] = y
from sklearn.metrics import silhouette_samples
df['silhouette'] = silhouette_samples(X, kmeans_cluster)
from sklearn.metrics import silhouette_samples
: scikit-kearn
라이브러리에서 실루엣 계수를 계산하는 함수를 가져온다.df['silhouette'] = silhouette_samples(X, kmeanscluster)
: 각 데이터 포인트에 대해 실루엣 계수를 계산하고 그 결과를 데이터프레임 df
에 새로운 열 'silhouette'
로 추가. 실루엣 계수는 -1에서 1 사이의 값을 가지고, 값이 클수록 해당 데이터 포인트가 클러스터 내에 잘 속해 있다는 것을 의미.# 클러스터 별 중심 선수 찾기
max_idx = df.groupby('kmeans_cluster')['silhouette'].idxmax()
df.loc[max_idx]
max_idx = df.groupby('kmeans_cluster')['silhouette'].idxmax()
: 각 클러스터에 대해 실루엣 계수가 가장 큰 데이터 포인트의 인덱스를 찾는다. groupby
메소드를 사용하여 클러스터별로 데이터를 그룹화하고, idxmax()
로 각 그룹의 최댓값을 가진 인덱스를 가져온다.df.loc[max_idx]
: 최댓값 인덱스를 사용하여 해당 선수 정보를 출력한다. 이는 클러스터에서 실루엣 계수가 가장 높은 선수(해당 클러스터에 제일 적합한 선수)를 나타낸다.# 클러스터별 주변 선수 찾기
min_idx = df.groupby('kmeans_cluster')['silhouette'].idxmin()
df.loc[min_idx]
min_idx = df.groupby('kmeans_cluster')['silhouette'].idxmin()
: 각 클러스터에 대해 실루엣 계수가 가장 작은 데이터 포인트의 인덱스를 찾는다. idxmin()
함수를 사용, 각 그룹의 최소값을 가진 인덱스를 가져온다.df.loc[min_idx]
: 최소값 인덱스를 사용하여 해당 선수의 정보를 출력. 이는 각 클러스터에서 실루엣 계수가 가장 낮은 선수(해당 클러스터에서 덜 적합한 선수)를 나타낸다.# 군집 오류 대상 찾기
df.loc[df['silhouette'] < 0]
실루엣 계수가 0보다 작은 데이터 포인트를 찾아 출력한다. 실루엣 계수가 0보다 낮은 경우 해당 데이터 포인트는 자신의 클러스터보다 다른 클러스터와 더 가깝다는 것을 의미하고, 이는 군집 오류 대상일 가능성이 크다.