비지도학습은 언제 쓰냐!
데이터에 라벨링이 안 되어 있을 때 쓴다. 라벨 = 정답값이라고 쉽게 생각하자.
내가 뭔가 데이터를 이용해서 예측이나 분류를 하는 모델을 만들고 싶어.. 그럼 예측값이나 분류값이 약간은 있어야될거아님..그래야 학습을 시킬거아님? 근데 그게 없어
이럴 때 쓴다 ㅎ
비지도 학습도 당연히 여러가지 대표 모델들이 있는데 기본적으로는 "유사성" 을 이용해서 주어진 데이터셋을 하위 데이터셋으로 분류함.그래서 분류된거끼리 묶으면 고걸 클러스팅이라고 부른다! 요번 포스팅은 그 여러가지 비지도 학습 중에서 정말 제일 쉽고 간단하고 자주 쓰이는 k-means 알고리즘을 다뤄보겠어.
1. k-means algorithm 개념과 작동원리
k-means 알고리즘은 기본적으로 means 의 개수(k개) 를 정해주고 몇개로 분류해줘 ~ 명령내리는 애다. 사용자가 k 를 지정해줘야 한다는 게 중요한 포인트며 그걸 기준으로 분류 알고리즘이 작동한다
여기서 핵심은 분류를 반복할 때마다 중심centroid 가 업데이트된다는 점이다. 이 중심이 최적의 위치에 올 때 까지 계속해서 반복을 하게 된다. 그렇게 k-means 는 지정된 횟수만큼 반복해서 무작위로 나열된 점들이 서로 가장 가까운 유클리스 거리를 가질 때 까지 중심을 업데이트할거다. 유클리드 거리는.. 작을수록 비슷한 데이터라고 보면 된다. 일단 이건 넘어가겠다
이 때! 초기 중심값을 선택해주는 방법이 두 가지가 있다
1. 무작위 random 으로 돌리기 k-means
2. 사용자가 판단해 배치해주기 k-means ++
일반적으로는 후자가 더 좋은 결과를 낸다. 왜냐면 초기값이 지정된 경우 더 빠르게 알고리즘이 수렴하고 작업이 끝날테니깐. 가능한 경우에는 훈련데이터셋을 먼저 살펴보고 각 데이터 포인트를 가장 가까운 중심에 할당하는게 좋다. 근데 딱히 그런거 모르겠는 경우 그냥 랜덤으로 돌리자.. 되도 않는 선택을 했다가 정확도가 되려 떨어질지도..모르니
2. 예제코드
2.1. 라이브러리와 데이터 import
불러와서 일단 데이터를 시각화해보자.
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn import metrics
# Load input data
# delimiter = 구분자
X = np.loadtxt('df', delimiter=',')
# Plot input data
plt.figure()
plt.scatter(X[:,0], X[:,1], marker='o', facecolors='none',
edgecolors='black', s=80)
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
plt.title('Input data')
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)
plt.xticks(())
plt.yticks(())
이렇게 생김. 근데 이게 가능한 이유는 일단 데이터가 2차원이기 때문이다. 3차원까지 시각화를 할 수 있다지만 그 이상 차원이 많다면 (속성이 많다면) 시각화 뿐만 아니라 어떤 속성을 기반으로 데이터가 분류됐는지 알기 좀 어려울 수 있다.
2.2. 최적의 k 값 찾기
그리고 이런 류의 데이터는 딱 분포만 봐도 사실 클러스터링이 되어있는 형태의 데이터셋이다. 만약에 저렇게 데이터를 시각화 해 볼 수 없는 경우이거나 분류가 잘 안된다면 튜닝을 하면 된다. elbow method 를 이용할 수 있음. 평가지표인 interia 를 기준으로 반복문을 돌려서 fit 해보자.
#interia = 평가지표, 얼마나 응집성이 있는지 봄
k_list = []
cost_list = []
for k in range (2, 7):
kmeans = KMeans(n_clusters=k).fit(X)
interia = kmeans.inertia_
print ("k:", k, "| cost:", interia)
k_list.append(k)
cost_list.append(interia)
plt.plot(k_list, cost_list)
그러면 요런식으로 k 값 별로 cost 값이 나와 줌. 값이 확 꺾이는 구간을 이용하자 (이 예제에선 4나 5가 적절)
k: 2 | cost: 228671013638.4617
k: 3 | cost: 154450862150.5793
k: 4 | cost: 93438696006.9793
k: 5 | cost: 60814830876.553154
k: 6 | cost: 46125419994.00405
[<matplotlib.lines.Line2D at 0x7f6495111890>]
이 엘보우 메서드는 무엇을 의미하냐! 언제 클러스터 세트가 데이터 분산의 "대부분" 을 의미하는지 알려준다. 데이터가 얼마나 잘 응집되었는지, 분산의 얼만큼을 클러스터가 포함하는지를 기준으로 나눠준다. 이 때 저 엘보우 메서드에서 확 꺾이는 부분 ( 이 예제에서는 4) 를 이용하는 이유는 그때가 바로 분산 증가율이 뚝 떨어지는 구간이기 때문이다.
다만, 비지도학습이니만큼 클러스터의 개수를 정확히 얻는 완벽한 방법은 존재하지 않는다.
2.3. 객체 선언 ~ 훈련 ~예측
어찌되었건 k-means 를 써보겠다
객체를 선언하고 바로 fit 해주면 끝 엄청쉬움. 조절을 해볼만한 파라미터들은 다음과 같음. 알고리즘 방식과 init 에 따라 성능편차가 꽤나 있음
# Create KMeans object
#init{‘k-means++’, ‘random’} 디폴트는 전자
#n_init = 반복할 횟수, 디폴트가 10, 높일수록 inerita 값 개선됨
# algorithm{“lloyd”, “elkan”, “auto”, “full”}, default=”lloyd”
kmeans = KMeans(init='k-means++', n_clusters=num_clusters, n_init=10)
# Train the KMeans clustering model
kmeans.fit(X)
2.3. 클러스터링 시각화 with 경계
경계를 설정하기 위해.. 넘파이의 meshgrid 를 이용하자
# Step size of the mesh
#경계를 시각화하기 위함임! gird 의 사이즈 조절
step_size = 0.01
# Define the grid of points to plot the boundaries
# meshgrid() = 격자 만드는 메서드
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
x_vals, y_vals = np.meshgrid(np.arange(x_min, x_max, step_size),
np.arange(y_min, y_max, step_size))
# Predict output labels for all the points on the grid
output = kmeans.predict(np.c_[x_vals.ravel(), y_vals.ravel()])
# Plot different regions and color them
output = output.reshape(x_vals.shape)
plt.figure()
plt.clf()
plt.imshow(output, interpolation='nearest',
extent=(x_vals.min(), x_vals.max(),
y_vals.min(), y_vals.max()),
cmap=plt.cm.Paired,
aspect='auto',
origin='lower')
# Overlay input points
# 색칠한 경계 위에 입력 포인트 오버레이# 색칠한 경계 위에 입력 포인트 오버레이
plt.scatter(X[:,0], X[:,1], marker='o', facecolors='none',
edgecolors='black', s=80)
# Plot the centers of clusters
# 클러스터의 중심 칠하기
cluster_centers = kmeans.cluster_centers_
plt.scatter(cluster_centers[:,0], cluster_centers[:,1],
marker='o', s=210, linewidths=4, color='black',
zorder=12, facecolors='black')
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
plt.title('Boundaries of clusters')
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)
plt.xticks(())
plt.yticks(())
plt.show()
그럼 요렇게 결과물이 나올거임.. 안 예쁘다.. 색이랑 사이즈랑 x y 까지 입력해주면 좀 봐줄만한 그래프가 되겠지만 나라면 예측 데이터 태블로로 넘겨서 시각화하겠음...
'데이터 과학 Data Science > 비지도학습' 카테고리의 다른 글
계층적 클러스터링 (0) | 2022.10.18 |
---|---|
DBSCAN으로 클러스터링 (1) | 2022.10.04 |
유사도 전파 Affinity Propagation 모델로 클러스터링 (1) | 2022.09.20 |
가우시안 혼합 모델로 클러스터링 (1) | 2022.09.19 |
평균 이동 알고리즘으로 데이터 클러스터링 (1) | 2022.09.19 |