728x90
반응형
2023-0901
** Clustering(군집)
1. 군집
- 비슷한 샘플들을 구별해서 하나의 클러스터로 묶는 작업
- 비지도 학습 : 레이블이 없는 학습 (정답이 없는 학습)
1.1) 군집이 이용되는 분야
- 고객 분류
- 데이터 분석 : 각 클러스터로 나눈 후 따로 분석
- 차원 축소
- 이상치 탐색 : 모든 클러스터에 친화적이지 않은 데이터를 이상치로 간주
- 준 지도 학습 : 레이블이 일부분만 존재하는 경우 군집을 수행해서 레이블을 생성
- 검색 엔진
1.2) 이미지 분할
- sklearn 에서는 다양한 유형의 군집화 알고리즘을 테스트 해보기 위한 샘플 데이터를 생성하는 API 를 제공
make_blobs(), make_classification, make_circle(), make_moon()
군집을 얼마나 효율적으로 했는지 확인하기 위한 target 을 같이 생성
1.3) 군집 실습 데이터 생성
#데이터 생성
from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=200, n_features=2, centers=3, cluster_std=0.8, random_state=42)
print(X.shape, y.shape)
# y target 값의 분포를 확인
unique, counts = np.unique(y, return_counts=True)
print(unique,counts)
## 결과
(200, 2) (200,)
[0 1 2] [67 67 66]
#DataFrame 으로 변환
import pandas as pd
clusterDF = pd.DataFrame(data=X, columns=['ftr1', 'ftr2'])
clusterDF['target'] = y
clusterDF.head(3)
#3개의 집단으로 군집
from sklearn.mixture import GaussianMixture
y_pred = GaussianMixture(n_components=3, random_state=42).fit(X).predict(X)
print(y_pred)
print(y)
#매핑된 결과 확인
from scipy import stats
mapping={}
for class_id in np.unique(y):
mode, _ = stats.mode(y_pred[y == class_id])
mapping[mode[0]] = class_id
print(mapping)
## {1: 0, 2: 1, 0: 2}
#데이터 분포 확인
target_list = np.unique(y)
# 각 target별 scatter plot 의 marker 값들.
markers=['o', 's', '^', 'P','D','H','x']
# 3개의 cluster 영역으로 구분한 데이터 세트을 생성했으므로 target_list는 [0,1,2]
# target==0, target==1, target==2 로 scatter plot을 marker별로 생성.
for target in target_list:
target_cluster = clusterDF[clusterDF['target']==target]
plt.scatter(x=target_cluster['ftr1'], y=target_cluster['ftr2'], edgecolor='k', marker=markers[target] )
plt.show()
2. 과일 이미지 군집
- 과일 이미지 파일 : fruits_300.npy(npy 는 numpy 배열을 저장한 파일)
# 이미지 출력
fruits = np.load('./fruits_300.npy')
print(fruits.shape)
# 3차원이면 흑백, 4차원이면 컬러가 있는 것임.
print(fruits[0, 0, :])
plt.imshow(fruits[0], cmap='gray')
plt.show()
fig, axs = plt.subplots(1, 2)
axs[0].imshow(fruits[100], cmap='gray_r')
axs[1].imshow(fruits[200], cmap='gray_r')
plt.show()
#이미지 데이터를 비교하기 위해서 1차원으로 변경
apple = fruits[0:100].reshape(-1, 100*100)
pineapple = fruits[100:200].reshape(-1, 100*100)
banana = fruits[200:300].reshape(-1, 100*100)
print(apple.shape)
# or
#print(fruits[0].flatten())
#차원 축소 다른 방법
차원 축소 후, 평균 출력
plt.hist(np.mean(apple, axis=1), alpha=0.8)
plt.hist(np.mean(pineapple, axis=1), alpha=0.8)
plt.hist(np.mean(banana, axis=1), alpha=0.8)
plt.legend(['apple', 'pineapple', 'banana'])
plt.show()
#픽셀 단위 출력
fig, axs = plt.subplots(1, 3, figsize=(20, 5))
axs[0].bar(range(10000), np.mean(apple, axis=0))
axs[1].bar(range(10000), np.mean(pineapple, axis=0))
axs[2].bar(range(10000), np.mean(banana, axis=0))
plt.show()
#평균을 가지고 이미지 출력
apple_mean = np.mean(apple, axis=0).reshape(100, 100)
pineapple_mean = np.mean(pineapple, axis=0).reshape(100, 100)
banana_mean = np.mean(banana, axis=0).reshape(100, 100)
fig, axs = plt.subplots(1, 3, figsize=(20, 5))
axs[0].imshow(apple_mean, cmap='gray_r')
axs[1].imshow(pineapple_mean, cmap='gray_r')
axs[2].imshow(banana_mean, cmap='gray_r')
plt.show()
#평균값과 가장 가까운 사진 고르기
abs_diff = np.abs(fruits - apple_mean)
abs_mean = np.mean(abs_diff, axis=(1,2))
print(abs_mean.shape)
apple_index = np.argsort(abs_mean)[:100]
fig, axs = plt.subplots(10, 10, figsize=(10,10))
for i in range(10):
for j in range(10):
axs[i, j].imshow(fruits[apple_index[i*10 + j]], cmap='gray_r')
axs[i, j].axis('off')
plt.show()
- 비슷한 샘플끼리 묶는 것이 군집(clustering)
- 묶인 그룹을 cluster 라고 합니다.
3. k-Means
3.1) 개요
- 몇 번의 반복으로 데이터 세트를 빠르고 효율적으로 클러스터링하는 알고리즘
- PCM(Pulse - Code Modulation)을 구현하기 위해서 등장
3.2) 알고리즘
- 무작위로 centroid를 선정
- 각 데이터들을 각 centroid에 배정
- 배정된 데이터들의 거리가 최소가 되도록 centorid를 수정해서 다시 데이터들을 할당
- centroid가 더 이상 변경되지 않으면 종료
3.3) 클래스
- sklearn.cluster.KMeans(n_clusters=8, init='k-means++', n_init=10, max_iter=300. tol=0.0001,precomput_distance='auto', verbose=0, random_state=None, copy_x=True, n_jobs=1, algorithm='auto')
- n_clusters: 클러스터 개수
- init 은 군집 중심점의 좌표를 설정하는 방법
- max_iter : 최대 반복횟수
- 훈련은 fit 이나 fit_transform 함수를 호출
- labels_ 속성에 군집 중심점 레이블을 저장
- cluster_centers_ 속성에 각 군집 중심점 좌표를 소유
3.4) 임의로 만든 데이터를 가지고 군집 분석 수행 - KMeans 이용
# 임의 데이터 생성과 시각화
from sklearn.datasets import make_blobs
blob_centers = np.array(
[[ 0.2, 2.3],
[-1.5 , 2.3],
[-2.8, 1.8],
[-2.8, 2.8],
[-2.8, 1.3]])
blob_std = np.array([0.4, 0.3, 0.1, 0.1, 0.1])
X, y = make_blobs(n_samples=2000, centers=blob_centers,
cluster_std=blob_std, random_state=7)
def plot_clusters(X, y=None):
plt.scatter(X[:, 0], X[:, 1], c=y, s=1)
plt.xlabel("$x_1$", fontsize=14)
plt.ylabel("$x_2$", fontsize=14, rotation=0)
plt.figure(figsize=(8, 4))
plot_clusters(X)
save_fig("blobs_plot")
plt.show()
#결정 경계 확인 - veronoi diagram(평면을 특정 점까지의 거리가 가까운 점의 집합으로 )
def plot_data(X):
plt.plot(X[:, 0], X[:, 1], 'k.', markersize=2)
def plot_centroids(centroids, weights=None, circle_color='w', cross_color='k'):
if weights is not None:
centroids = centroids[weights > weights.max() / 10]
plt.scatter(centroids[:, 0], centroids[:, 1],
marker='o', s=35, linewidths=8,
color=circle_color, zorder=10, alpha=0.9)
plt.scatter(centroids[:, 0], centroids[:, 1],
marker='x', s=2, linewidths=12,
color=cross_color, zorder=11, alpha=1)
def plot_decision_boundaries(clusterer, X, resolution=1000, show_centroids=True,
show_xlabels=True, show_ylabels=True):
mins = X.min(axis=0) - 0.1
maxs = X.max(axis=0) + 0.1
xx, yy = np.meshgrid(np.linspace(mins[0], maxs[0], resolution),
np.linspace(mins[1], maxs[1], resolution))
Z = clusterer.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(Z, extent=(mins[0], maxs[0], mins[1], maxs[1]),
cmap="Pastel2")
plt.contour(Z, extent=(mins[0], maxs[0], mins[1], maxs[1]),
linewidths=1, colors='k')
plot_data(X)
if show_centroids:
plot_centroids(clusterer.cluster_centers_)
if show_xlabels:
plt.xlabel("$x_1$", fontsize=14)
else:
plt.tick_params(labelbottom=False)
if show_ylabels:
plt.ylabel("$x_2$", fontsize=14, rotation=0)
else:
plt.tick_params(labelleft=False)
#결정 경계 확인 함수 호출
plt.figure(figsize=(8, 4))
plot_decision_boundaries(kmeans, X)
save_fig("voronoi_plot")
plt.show()
3.5) k-means 의 문제점
- 데이터를 클러스터에 할당할 때 거리만을 고려하기 때문에 클러스터의 크기가 많이 다르면 제대로 동작하지 않ㅇ르 수 있습니다.
클러스터의 크기가 유사할 때 잘 동작함
- 샘플을 하나의 클러스터에 할당하는 방식을 하드 군집(Hard Clustering) 이라고 하고 클러스터 마다 샘플에 점수를 부여하는 방식은 소프트 군집(Soft Clustering) 이라고 하는데 이 점수는 샘플과 centroid 간의 거리가 될 수도 있고 유사도 점수 일 수도 있습니다.
- K-Means 클래스의 trasform()을 이용하면 각 샘플과 centroid 사이의 거리를 반환
print(kmeans.transform(X_new))
print(kmeans.predict(X_new))
3.6) 복잡도
- 샘플 개수와 클러스터 개수 그리고 차원 개수에 선형
- 일반적으로 갖아 빠른 군집 알고리즘
3.7) Centroid 초기화
- Centroid 위치를 근사하게 알고있다면 init 하이퍼 파라미터에 centroid 리스트를 담은 numpy의 ndarray를 이용해서 지정하고 n_init을 1로 설정
init 하이퍼 파라미터를 설정하지 않으면 랜덤하게 centroid를 설정하게 되는데, 처음 이 값이 잘못 설정되면 최적화를 하지 못할 수 있음.
- n_init은 centroid를 옮기는 횟수
#centroid 초기화
kmeans_iter1 = KMeans(n_clusters=5, init="random", n_init=1,
algorithm="full", max_iter=1, random_state=0)
kmeans_iter2 = KMeans(n_clusters=5, init="random", n_init=1,
algorithm="full", max_iter=2, random_state=0)
kmeans_iter3 = KMeans(n_clusters=5, init="random", n_init=1,
algorithm="full", max_iter=3, random_state=0)
kmeans_iter1.fit(X)
kmeans_iter2.fit(X)
kmeans_iter3.fit(X)
#centroid 초기화 시각화
plt.figure(figsize=(10, 8))
plt.subplot(321)
plot_data(X)
plot_centroids(kmeans_iter1.cluster_centers_, circle_color='r', cross_color='w')
plt.ylabel("$x_2$", fontsize=14, rotation=0)
plt.tick_params(labelbottom=False)
plt.title("Update the centroids (initially randomly)", fontsize=14)
plt.subplot(322)
plot_decision_boundaries(kmeans_iter1, X, show_xlabels=False, show_ylabels=False)
plt.title("Label the instances", fontsize=14)
plt.subplot(323)
plot_decision_boundaries(kmeans_iter1, X, show_centroids=False, show_xlabels=False)
plot_centroids(kmeans_iter2.cluster_centers_)
plt.subplot(324)
plot_decision_boundaries(kmeans_iter2, X, show_xlabels=False, show_ylabels=False)
3.8) 성능 평가 지표
- 각 샘플과 가장 가까운 centroid 사이의 평균 제곱 거리 (inertia 라고 함)
- inertia_ 라는 속성을 이용해서 확인이 가능하고 score()를 호출하면 inertia를 음수 값으로 반환
inertia는 거리의 개념이기 때문에 작은 숫자가 잘 만들어진 모델
- sklearn은 높은 점수가 좋다라는 원칙을 가지고 있음
# 평가지표 출력
print(kmeans.inertia_)
print(kmeans.score(X))
## result
211.59853725816836
-211.59853725816836
3.9) K-Means++
- K-Means는 랜덤하게 중심점을 초기화하는데 K-Means ++은 성능향상을 위해서 첫번째 중심점을 선택한 후 다음 중심점은 거리가 먼 중심점을 선택하는 방식
- sklearn의 K-Means 클래스는 이 방식이 기본이며 랜덤한 초기화를 하고자 하는 경우에는 init 매개변수를 random으로 설정하면 됩니다.
3.10) 속도 개선
- 불필요한 계산을 줄이기 위해서 삼각 부등식을 사용 : centroid 사이의 거리를 위한 하한선과 상한선을 유지 - 기본적으로 이 방식을 사용하고 있으며 algorithm 매개변수를 full로 설정하면 이전 방식을 사용
- 기본 K-Means 는 전체 데이터 세트를 가지고 centroid를 수정하는 방식을 사용하는데 반에 Mini Batch는 일부의 데이터만 가지고 centroid를 수정하도록 해서 속도를 3~4 배 정도 향상 시킴
미니 배치를 사용하고자 하는 경우에는 MiniBatchKMeans 클래스를 활용
%%time
k = 5
kmeans = KMeans(n_clusters=k, random_state = 42)
y_pred = kmeans.fit_predict(X)
%%time
from sklearn.cluster import MiniBatchKMeans
k = 5
miniBatchKMeans = MiniBatchKMeans(n_clusters=k, random_state=42)
y_pred = miniBatchKMeans.fit_predict(X)
print(miniBatchKMeans.inertia_)
## result
#미니배치 미 사용
CPU times: total: 1.67 s
Wall time: 527 ms
#미니배치 사용
211.652398504332
CPU times: total: 1.16 s
Wall time: 406 ms
3.11) 클러스터 개수 설정
- 최적의 클러스터 개수를 설정하는 방법은 2가지를 확인해서 수행
- inertia 의 elbow를 찾아서 설정(inertia 값이 급격하게 변하는 지점)를 찾아서 설정
- 실루엣 계수를 이용하는 방식 - 권장
#이너셔를 이용한 최적의 클러스터 개수 찾기
kmeans_per_k = [KMeans(n_clusters=k, random_state=42).fit(X)
for k in range(1, 10)]
inertias = [model.inertia_ for model in kmeans_per_k]
plt.figure(figsize=(8, 3.5))
plt.plot(range(1, 10), inertias, "bo-")
plt.xlabel("$k$", fontsize=14)
plt.ylabel("Inertia", fontsize=14)
plt.annotate('Elbow',
xy=(4, inertias[3]),
xytext=(0.55, 0.55),
textcoords='figure fraction',
fontsize=16,
arrowprops=dict(facecolor='black', shrink=0.1)
)
plt.axis([1, 8.5, 0, 1300])
save_fig("inertia_vs_k_plot")
plt.show()
plot_decision_boundaries(kmeans_per_k[4-1], X)
plt.show()
- 실루엣 계수를 이용하는 방식 - 이 방법을 권장
샘플의 실루엣 계수는 (b-a)/max(a, b) 로 구하는데 a 는 동일한 클러스터에 있는 다른 데이터 와의 평균 거리이고 b 는 가장 가까운 클러스터까지의 평균 거리
실루엣 계수는 -1 ~ + 1 까지
+1 에 가까워지면 자신의 클러스터 안에 잘 속해 있고 다른 클러스터 와는 멀리 떨어져 있음
실루엣 계수가 0에 가까워지면 경계에 위치한다는 의미이고 -1에 가까우면 샘플이 클러스터에 잘 못 할당된 것
- sklearn.metrics.silhouette_samples(X, labels, metric= ’euclidean ’ **kwds):
인자로 X feature 데이터 세트와 각 피처 데이터 세트가 속한 군집 레이블 값인 labels 데이터를 입력해주면 각 데이터 포인트의 실루엣 계수를 계산해 반환
- sklearn.metrics.silhouette_score(X, labels, metric= ’euclidean ’, sample_size=None, **kwds):
인자로 X feature 데이터 세트와 각 피처 데이터 세트가 속한 군집 레이블 값인 labels 데이터를 입력해주면 전체 데이터의 실루엣 계수 값을 평균해 반환
#실루엣 점수 출력
from sklearn.metrics import silhouette_score
silhouette_score(X, kmeans.labels_)
## 결과
0.655517642572828
silhouette_scores = [silhouette_score(X, model.labels_)
for model in kmeans_per_k[1:]]
plt.figure(figsize=(8, 3))
plt.plot(range(2, 10), silhouette_scores, "bo-")
plt.xlabel("$k$", fontsize=14)
plt.ylabel("Silhouette score", fontsize=14)
plt.axis([1.8, 8.5, 0.55, 0.7])
save_fig("silhouette_score_vs_k_plot")
plt.show()
3.12) K-Means 의 한계
- 속성의 개수가 많으면 정확도가 떨어짐
- 클러스터의 크기나 밀집도가 원형이 아니면 잘 작동하지 않음
from sklearn.datasets import make_moons
X, y = make_moons(200, noise=.05, random_state=42)
plt.scatter(X[:, 0], X[:, 1], s=50, cmap='viridis');
labels = KMeans(2, random_state=0).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=labels,
s=50, cmap='viridis');
3.13) 군집을 이용한 이미지 분할
- 이미지를 세그먼트 여러 개로 분할할 때 사용이 가능
- 복잡한 이미지의 경우는 Deep Learning의 CNN 을 많이 이용하는데 구별해야 할 이미지나 색상이 단순한 경우에는 KMeans 로도 충분함.
#군집을 이용한 이미지 분할
#이미지를 읽어와서 출력하기
from matplotlib.image import imread
image = imread('./ladybug.jpg')
print(image.shape)
plt.figure(figsize=(10,5))
plt.subplots_adjust(wspace=0.05, hspace=0.1)
plt.subplot(231)
plt.imshow(image)
plt.title("Original image")
plt.axis('off')
#색상을 가지고 군집을 수행
X = image.reshape(-1, 3)
kmeans = KMeans(n_clusters=8, random_state=42).fit(X)
#각 픽셀이 속한 클러스터의 중앙 좌표를 저장
segmented_img = kmeans.cluster_centers_[kmeans.labels_]
segmented_img = segmented_img.reshape(image.shape)
segmented_imgs = []
n_colors = (10, 8, 6, 4, 2)
for n_clusters in n_colors:
kmeans = KMeans(n_clusters=n_clusters, random_state=42).fit(X)
segmented_img = kmeans.cluster_centers_[kmeans.labels_]
segmented_imgs.append(segmented_img.reshape(image.shape))
for idx, n_clusters in enumerate(n_colors):
plt.subplot(232 + idx)
plt.imshow(segmented_imgs[idx].astype('uint8'))
plt.title("{} colors".format(n_clusters))
plt.axis('off')
save_fig('image_segmentation_diagram', tight_layout=False)
plt.show()
- 흑백 이미지의 경우는 0 ~ 255 사이의 숫자로 하나의 픽셀을 나타내는데 대비를 명확하게 하고자 할 때는 threshold를 설정하고 0과 1로 수정해서 사용
3.14) 군집을 이용한 준 지도 학습
- 군집을 수행한 후 분류 모델을 학습하면 조금 더 나은 성능을 발휘하는 경우가 있음.
- 차원 축소하는 개념을 이용
#군집을 이용한 차원 축소 후 분류
#8*8 크기의 흑백 숫자 이미지 1797개 가져오기
from sklearn.datasets import load_digits
X_digits, y_digits = load_digits(return_X_y=True)
print(X_digits.shape)
print(y_digits.shape)
## result
(1797, 64)
(1797,)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X_digits, y_digits, random_state=42)
#로지스틱 회귀 수행
from sklearn.linear_model import LogisticRegression
log_reg = LogisticRegression(multi_class="ovr", solver="lbfgs", max_iter=5000, random_state=42)
log_reg.fit(X_train, y_train)
log_reg_score = log_reg.score(X_test, y_test)
log_reg_score
## result
0.9688888888888889
#차원 축소
#k-Means 를 이용한 전처리 후 로지스틱 회귀 수행
from sklearn.pipeline import Pipeline
pipeline = Pipeline([
("kmeans", KMeans(n_clusters=50, random_state=42)),
("log_reg", LogisticRegression(multi_class="ovr", solver="lbfgs", max_iter=5000, random_state=42)),
])
pipeline.fit(X_train, y_train)
pipeline_score = pipeline.score(X_test, y_test)
pipeline_score
## result
0.9777777777777777 !
#오차율 확인
1 - (1 - pipeline_score) / (1 - log_reg_score)
## result
0.28571428571428414
%%time
#최적의 클러스터 개수 찾기
from sklearn.model_selection import GridSearchCV
param_grid = dict(kmeans__n_clusters=range(2, 100))
grid_clf = GridSearchCV(pipeline, param_grid, cv=3, verbose=2)
grid_clf.fit(X_train, y_train)
print(grid_cif.best_params_)
print(gird_cif.score(X_test, y_test))
4. 계층적 클러스터링
4.1) 개요
- 계층적인 트리로 클러스터를 조직화하는 방법
- 특이점 또는 비정상적인 그룹이나 레코드를 발견하는데 민감
- 직관적인 시각화가 가능하기 때문에 클러스터를 해석하기가 용이
4.2) 용어
- Dendrogram : 계층적 클러스터를 시각화 한것
- Distance : 한 레코드가 다른 레코드와 얼마나 가까운지를 보여주는 지표
- Dissimilarity(비유사도) : 한 클러스터가 다른 클러스터들과 얼마나 가까운지를 보여주는 지표
4.3) 사용하는 경우
- 컴퓨터 자원을 많이 소모하기 때문에 수만 개 정도의 레코드까지만 사용
4.4) 방법
- 분할 계층 군집 : 전체 데이터를 하나의 클러스터에 할당하고 더 작은 클러스터로 반복적으로 나누는 방식
- 병합 계층 군집 : 하나의 데이터를 하나의 클러스터로 만들고 가장 가까운 클러스터를 병합해나가는 방식
구현을 할 때는 가장 비슷한 샘플의 거리를 계산해서 병합할 수 도 있고 가장 먼 거리의 샘플을 이용해서 병합하기도 합니다.
평균 연결과 중심 연결 그리고 와드 연결(군집 내 편차들의 제곱합) 3가지 알고리즘을 이용
#병합군집
#샘플 데이터 생성
np.random.seed(42)
variables = ['X', 'Y', 'Z']
labels = ['ID_0','ID_1','ID_2', 'ID_3', 'ID_4']
X = np.random.random_sample([5,3])*10
df = pd.DataFrame(X, columns=variables, index=labels)
print(df)
##result
X Y Z
ID_0 3.745401 9.507143 7.319939
ID_1 5.986585 1.560186 1.559945
ID_2 0.580836 8.661761 6.011150
ID_3 7.080726 0.205845 9.699099
ID_4 8.324426 2.123391 1.818250
#거리 계산 - 유클리디안 거리
from scipy.spatial.distance import pdist, squareform
row_dist = pd.DataFrame(squareform(pdist(df, metric='euclidean')),
columns=labels,
index=labels)
print(row_dist)
## result
ID_0 ID_1 ID_2 ID_3 ID_4
ID_0 0.000000 10.067500 3.527332 10.163608 10.283767
ID_1 10.067500 0.000000 9.973350 8.323293 2.418558
ID_2 3.527332 9.973350 0.000000 11.285037 10.967857
ID_3 10.163608 8.323293 11.285037 0.000000 8.205581
ID_4 10.283767 2.418558 10.967857 8.205581 0.000000
#계층적 클러스터링 수행
from scipy.cluster.hierarchy import linkage
row_clusters = linkage(row_dist, method='complete')
pd.DataFrame(row_clusters,
columns=['row label 1', 'row label 2','distance','no. of items in clust.'],
index=['cluster %d' %(i+1) for i in range(row_clusters.shape[0])])
#첫번째와 두번째는 병합된 클러스터 이름이고 세번째는 거리, 네번째는 아이템 개수
#처음에는 클러스터가 데이터 개수만큼 -> 5개
#가까운 것끼리 합쳐지면서 1-4 / 0-2/ 3-5/ 6-7 합쳐지면서 데이터 5개
##result
row label 1 row label 2 distance no. of items in clust.
cluster 1 1.0 4.0 3.570507 2.0
cluster 2 0.0 2.0 5.159321 2.0
cluster 3 3.0 5.0 13.182329 3.0
cluster 4 6.0 7.0 18.782841 5.0
#덴드로그램 출력
#계층적 군집을 시각화하는 도구
from scipy.cluster.hierarchy import dendrogram
# 검은색 덴드로그램 만들기
# from scipy.cluster.hierarchy import set_link_color_palette
# set_link_color_palette(['black']
row_dendr = dendrogram(row_clusters,labels=labels)
plt.tight_layout()
plt.ylabel('유클리디안 거리')
plt.show()
#히트맵에 덴드로그램 연결
#새로운 figure 객체를 만들고 add_axes 함수를 사용해서 덴드로그램의 x축 위치, y축 위치, 너비, 높이를 지정
#덴드로그램을 반시계 방향으로 90도 회전
fig = plt.figure(figsize=(8,8), facecolor='white')
axd = fig.add_axes([0.09,0.1,0.2,0.6])
row_dendr = dendrogram(row_clusters, orientation='left')
#파이썬 딕셔너리인 덴드로그램 객체의 leaves 키에서 얻은 클러스터 레이블을 따라 원 본 DataFrame에 있는 데이터를 재정렬
df_rowclust = df.iloc[row_dendr['leaves'][::-1]]
#재정렬된 DataFrame에서 히트맵을 만들고 덴드로그램 다음에 위치
axm = fig.add_axes([0.23,0.1,0.6,0.6])
cax = axm.matshow(df_rowclust,
interpolation='nearest',
cmap='hot_r')
# 축 눈금을 제거하고 그래프 테두리를 숨김
# 컬러 막대를 추가하고 특성과 샘플 이름을 각각 x축과 y축 눈금의 레이블로 할당
axd.set_xticks([])
axd.set_yticks([])
for i in axd.spines.values():
i.set_visible(False)
fig.colorbar(cax)
axm.set_xticklabels([''] + list(df_rowclust.columns))
axm.set_yticklabels([''] + list(df_rowclust.index))
plt.show()
from sklearn.cluster import AgglomerativeClustering
ac = AgglomerativeClustering(n_clusters=3,
affinity='euclidean',
linkage='complete')
labels = ac.fit_predict(X)
print('클러스터 레이블: %s' % labels)
## result
클러스터 레이블: [0 1 0 2 1]
#계층적 클러스터링 수행
from scipy.cluster.hierarchy import linkage, dendrogram, fcluster
from scipy.stats import multivariate_normal
syms1 = ['AAPL', 'AMZN', 'AXP', 'COP', 'COST', 'CSCO', 'CVX', 'GOOGL', 'HD',
'INTC', 'JPM', 'MSFT', 'SLB', 'TGT', 'USB', 'WFC', 'WMT', 'XOM']
df = sp500_px.loc[sp500_px.index >= '2011-01-01', syms1].transpose()
Z = linkage(df, method='complete')
print(Z.shape)
##result
5. GMM(가우시안 혼합 모델)
5.1) 개요
- 샘플이 파라미터가 알려지지 않은 여러 개의 혼합된 Gaussian 분포(정규 분포)에서 생성되었다고 가정하는 확률 모델
- 정규 분포 : 평균이 0이고 표준 편차가 1인 정규분포
표준 편차의 1배 내의 68.27%
표준 편차의 2배 내에 95.45%
표준 편차의 3배 내에 99.73%
5.2) 클래스
- sklearn.mixture의 GaussianMixture
- 가장 중요한 하이퍼파라미터는 n_comonents로 몇 개의 군집을 생성할 것인지 여부를 설정
- 생성 모델이라서 sample 함수를 이용해서 새로운 데이터 생성 가능
#샘플 데이터를 3개의 군집으로 묶기
X1, y1 = make_blobs(n_samples=1000, centers=((4, -4), (0, 0)), random_state=42)
X1 = X1.dot(np.array([[0.374, 0.95], [0.732, 0.598]]))
X2, y2 = make_blobs(n_samples=250, centers=1, random_state=42)
X2 = X2 + [6, -8]
X = np.r_[X1, X2]
y = np.r_[y1, y2]
from sklearn.mixture import GaussianMixture
gm = GaussianMixture(n_components=3, n_init=10, random_state=42)
gm.fit(X)
print(gm.weights_) #가중치 확인
print(gm.means_) #중심점 좌표
print(gm.covariances_) #공분산
print(gm.converged_)
print(gm.n_iter_) #횟수
print(gm.predict(X)) #예측
print(gm.predict_proba(X)) #확률
#생성 모델이라서 sample 함수를 이용해서 새로운 데이터 생성 가능
X_new, y_new = gm.sample(6)
X_new
#모델의 밀도 확인
gm.score_samples(X)
반응형
LIST
'LG 헬로비전 DX DATA SCHOOL > Python' 카테고리의 다른 글
차원 축소 (DimensionalityReduction) (0) | 2023.09.04 |
---|---|
군집 분석 2 (0) | 2023.09.04 |
회귀분석 (0) | 2023.08.30 |
Pandas 의 연산 (0) | 2023.08.16 |
Python 탐색적 시각화 (2) | 2023.08.11 |