비지도 학습이란 레이블이 없는 학습 데이터로 머신 러닝 모델을 만드는 기법이다. 비지도 학습은 시장 세분화, 주식 시장 분석, 자연어 처리, 컴퓨터 비전을 비롯한 다양한 분야에서 활용된다. 비지도 학습 알고리즘은 주어진 데이터 집합에 담긴 데이터 유사도에 따라 소그룹으로 나누는 방식으로 학습 모델을 만든다.
군집화는 유사도 또는 비유사도 측정 기준에 따라 서로 비슷한 원소끼리 소그룹으로 묶는 일종의 데이터 조직화 과정을 말한다. 군집화를 하기 위해서는 개별 데이터들을 하나의 그룹으로 묶는 고유한 속성을 찾아야 한다.
K-평균 알고리즘은 중심점의 첫 위치가 매우 중요하다. 결과에 직접적으로 영향을 미치기 때문이다. 첫 중심점을 기준으로 모든 데이터를 분류하고 나면 각 군집들의 중심점을 다시 계산한다. 그리고는 데이터를 다시 분류하고 중심점을 계산하기를 반복한다.
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn import metrics
# Load input data
X = np.loadtxt('data_clustering.txt', delimiter=',')
num_clusters = 5
# 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(())
# Create KMeans object
kmeans = KMeans(init='k-means++', n_clusters=num_clusters, n_init=10)
# Train the KMeans clustering model
kmeans.fit(X)
# Step size of the mesh
step_size = 0.01
# Define the grid of points to plot the boundaries
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()
평균 이동 알고리즘은 비모수적 기법으로서 중심점의 위치를 찾는 것을 목적으로 한다. 윈도우를 정의하고 각 윈도우의 중심점을 계산한다. 다시 윈도우를 지정하고 중심점을 갱신하는 것을 반복한다.
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import MeanShift, estimate_bandwidth
from itertools import cycle
# Load data from input file
X = np.loadtxt('data_clustering.txt', delimiter=',')
# Estimate the bandwidth of X
bandwidth_X = estimate_bandwidth(X, quantile=0.1, n_samples=len(X))
# Cluster data with MeanShift
meanshift_model = MeanShift(bandwidth=bandwidth_X, bin_seeding=True)
meanshift_model.fit(X)
# Extract the centers of clusters
cluster_centers = meanshift_model.cluster_centers_
print('\nCenters of clusters:\n', cluster_centers)
# Estimate the number of clusters
labels = meanshift_model.labels_
num_clusters = len(np.unique(labels))
print("\nNumber of clusters in input data =", num_clusters)
# Plot the points and cluster centers
plt.figure()
markers = 'o*xvs'
for i, marker in zip(range(num_clusters), markers):
# Plot points that belong to the current cluster
plt.scatter(X[labels==i, 0], X[labels==i, 1], marker=marker, color='black')
# Plot the cluster center
cluster_center = cluster_centers[i]
plt.plot(cluster_center[0], cluster_center[1], marker='o',
markerfacecolor='black', markeredgecolor='black',
markersize=15)
plt.title('Clusters')
plt.show()
실루엣 기법이란 데이터에 존재하는 군집의 일관성을 검사하는 방법이다. 실루엣 지수란 특정한 데이터가 다른 군집에 비해 자신이 속한 군집에 얼마나 가까운지를 측정하는 지표다.
silhouette score = (p - q) / max(p, q)
여기서 p는 현재 데이터가 속하지 않은 군집 중에서 가장 가까운 군집에 있는 점들 사이의 거리에 대한 평균이고, q는 자신이 속한 군집에 있는 모든 점과 다른 군집 사이의 거리에 대한 평균이다.
score = metrics.silhouette_score(X, kmeans.labels_,
metric='euclidean', sample_size=len(X))
print("\nNumber of clusters =", num_clusters)
print("Silhouette score =", score)
scores.append(score)
# Plot silhouette scores
plt.figure()
plt.bar(values, scores, width=0.7, color='black', align='center')
plt.title('Silhouette score vs number of clusters')
# Extract best score and optimal number of clusters
num_clusters = np.argmax(scores) + values[0]
print('\nOptimal number of clusters =', num_clusters)
# Plot data
plt.figure()
plt.scatter(X[:,0], X[:,1], color='black', s=80, marker='o', facecolors='none')
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(())
plt.show()
혼합 모델이란 데이터 여러 개의 성분 분포를 따른다고 가정하는 확률 밀도 모델이다. 이때 각 성분 분포가 가우시안 분포인 모델을 가우시안 혼합 모델이라고 한다.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import patches
from sklearn import datasets
from sklearn.mixture import GMM
from sklearn.cross_validation import StratifiedKFold
# Load the iris dataset
iris = datasets.load_iris()
# Split dataset into training and testing (80/20 split)
indices = StratifiedKFold(iris.target, n_folds=5)
# Take the first fold
train_index, test_index = next(iter(indices))
# Extract training data and labels
X_train = iris.data[train_index]
y_train = iris.target[train_index]
# Extract testing data and labels
X_test = iris.data[test_index]
y_test = iris.target[test_index]
# Extract the number of classes
num_classes = len(np.unique(y_train))
# Build GMM
classifier = GMM(n_components=num_classes, covariance_type='full',
init_params='wc', n_iter=20)
# Initialize the GMM means
classifier.means_ = np.array([X_train[y_train == i].mean(axis=0)
for i in range(num_classes)])
# Train the GMM classifier
classifier.fit(X_train)
# Draw boundaries
plt.figure()
colors = 'bgr'
for i, color in enumerate(colors):
# Extract eigenvalues and eigenvectors
eigenvalues, eigenvectors = np.linalg.eigh(
classifier._get_covars()[i][:2, :2])
# Normalize the first eigenvector
norm_vec = eigenvectors[0] / np.linalg.norm(eigenvectors[0])
# Extract the angle of tilt
angle = np.arctan2(norm_vec[1], norm_vec[0])
angle = 180 * angle / np.pi
# Scaling factor to magnify the ellipses
# (random value chosen to suit our needs)
scaling_factor = 8
eigenvalues *= scaling_factor
# Draw the ellipse
ellipse = patches.Ellipse(classifier.means_[i, :2],
eigenvalues[0], eigenvalues[1], 180 + angle,
color=color)
axis_handle = plt.subplot(1, 1, 1)
ellipse.set_clip_box(axis_handle.bbox)
ellipse.set_alpha(0.6)
axis_handle.add_artist(ellipse)
# Plot the data
colors = 'bgr'
for i, color in enumerate(colors):
cur_data = iris.data[iris.target == i]
plt.scatter(cur_data[:,0], cur_data[:,1], marker='o',
facecolors='none', edgecolors='black', s=40,
label=iris.target_names[i])
test_data = X_test[y_test == i]
plt.scatter(test_data[:,0], test_data[:,1], marker='s',
facecolors='black', edgecolors='black', s=40,
label=iris.target_names[i])
# Compute predictions for training and testing data
y_train_pred = classifier.predict(X_train)
accuracy_training = np.mean(y_train_pred.ravel() == y_train.ravel()) * 100
print('Accuracy on training data =', accuracy_training)
y_test_pred = classifier.predict(X_test)
accuracy_testing = np.mean(y_test_pred.ravel() == y_test.ravel()) * 100
print('Accuracy on testing data =', accuracy_testing)
plt.title('GMM classifier')
plt.xticks(())
plt.yticks(())
plt.show()