1. 程式人生 > >Python_sklearn機器學習庫學習筆記(五)k-means(聚類)

Python_sklearn機器學習庫學習筆記(五)k-means(聚類)

# K的選擇:肘部法則

如果問題中沒有指定K的值,可以通過肘部法則這一技術來估計聚類數量。肘部法則會把不同K值的
成本函式值畫出來。隨著K值的增大,平均畸變程度會減小;每個類包含的樣本數會減少,於是樣本
離其重心會更近。但是,隨著K值繼續增大,平均畸變程度的改善效果會不斷減低。K值增大過程
中,畸變程度的改善效果下降幅度最大的位置對應的K值就是肘部。

複製程式碼

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
#隨機生成一個實數,範圍在(0.5,1.5)之間
cluster1=np.random.uniform(0.5,1.5,(2,10))
cluster2=np.random.uniform(3.5,4.5,(2,10))
#hstack拼接操作
X=np.hstack((cluster1,cluster2)).T
plt.figure()
plt.axis([0,5,0,5])
plt.grid(True)
plt.plot(X[:,0],X[:,1],'k.')

複製程式碼

 

%matplotlib inline
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\msyh.ttc", size=10)

複製程式碼

#coding:utf-8
#我們計算K值從1到10對應的平均畸變程度:
from sklearn.cluster import KMeans
#用scipy求解距離
from scipy.spatial.distance import cdist
K=range(1,10)
meandistortions=[]
for k in K:
    kmeans=KMeans(n_clusters=k)
    kmeans.fit(X)
    meandistortions.append(sum(np.min(
            cdist(X,kmeans.cluster_centers_,
                 'euclidean'),axis=1))/X.shape[0])
plt.plot(K,meandistortions,'bx-')
plt.xlabel('k')
plt.ylabel(u'平均畸變程度',fontproperties=font)
plt.title(u'用肘部法則來確定最佳的K值',fontproperties=font)

複製程式碼

 

複製程式碼

import numpy as np 
x1 = np.array([1, 2, 3, 1, 5, 6, 5, 5, 6, 7, 8, 9, 7, 9])
x2 = np.array([1, 3, 2, 2, 8, 6, 7, 6, 7, 1, 2, 1, 1, 3])
X=np.array(list(zip(x1,x2))).reshape(len(x1),2) 
plt.figure() 
plt.axis([0,10,0,10]) 
plt.grid(True) 
plt.plot(X[:,0],X[:,1],'k.')

複製程式碼

複製程式碼

from sklearn.cluster import KMeans
from scipy.spatial.distance import cdist
K=range(1,10)
meandistortions=[]
for k in K:
    kmeans=KMeans(n_clusters=k)
    kmeans.fit(X)
    meandistortions.append(sum(np.min(cdist(
            X,kmeans.cluster_centers_,"euclidean"),axis=1))/X.shape[0])
plt.plot(K,meandistortions,'bx-')
plt.xlabel('k')
plt.ylabel(u'平均畸變程度',fontproperties=font)
plt.title(u'用肘部法則來確定最佳的K值',fontproperties=font)

複製程式碼

 

# 聚類效果的評價
#### 輪廓係數(Silhouette Coefficient):s =ba/max(a, b)

複製程式碼

import numpy as np
from sklearn.cluster import KMeans
from sklearn import metrics

plt.figure(figsize=(8,10))
plt.subplot(3,2,1)
x1 = np.array([1, 2, 3, 1, 5, 6, 5, 5, 6, 7, 8, 9, 7, 9])
x2 = np.array([1, 3, 2, 2, 8, 6, 7, 6, 7, 1, 2, 1, 1, 3])
X = np.array(list(zip(x1, x2))).reshape(len(x1), 2)
plt.xlim([0,10])
plt.ylim([0,10])
plt.title(u'樣本',fontproperties=font)
plt.scatter(x1, x2)
colors = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'b']
markers = ['o', 's', 'D', 'v', '^', 'p', '*', '+']
tests=[2,3,4,5,8]
subplot_counter=1
for t in tests:
    subplot_counter+=1
    plt.subplot(3,2,subplot_counter)
    kmeans_model=KMeans(n_clusters=t).fit(X)
#     print kmeans_model.labels_:每個點對應的標籤值
    for i,l in enumerate(kmeans_model.labels_):
        plt.plot(x1[i],x2[i],color=colors[l],
             marker=markers[l],ls='None')
        plt.xlim([0,10])
        plt.ylim([0,10])
        plt.title(u'K = %s, 輪廓係數 = %.03f' % 
                  (t, metrics.silhouette_score
                   (X, kmeans_model.labels_,metric='euclidean'))
                  ,fontproperties=font)

複製程式碼

# 影象向量化

複製程式碼

import numpy as np
from sklearn.cluster import KMeans
from sklearn.utils import shuffle
import mahotas as mh

original_img=np.array(mh.imread('tree.bmp'),dtype=np.float64)/255
original_dimensions=tuple(original_img.shape)
width,height,depth=tuple(original_img.shape)
image_flattend=np.reshape(original_img,(width*height,depth))

print image_flattend.shape
image_flattend

複製程式碼

輸出結果:

(102672L, 3L)

Out[96]:

array([[ 0.55686275,  0.57647059,  0.61960784],
       [ 0.68235294,  0.70196078,  0.74117647],
       [ 0.72156863,  0.7372549 ,  0.78039216],
       ..., 
       [ 0.75686275,  0.63529412,  0.46666667],
       [ 0.74117647,  0.61568627,  0.44705882],
       [ 0.70588235,  0.57647059,  0.40784314]])

 然後我們用K-Means演算法在隨機選擇1000個顏色樣本中建立64個類。每個類都可能是壓縮調色盤中的一種顏色

image_array_sample=shuffle(image_flattend,random_state=0)[:1000]
image_array_sample.shape
estimator=KMeans(n_clusters=64,random_state=0)
estimator.fit(image_array_sample)

#之後,我們為原始圖片的每個畫素進行類的分配
cluster_assignments=estimator.predict(image_flattend)

print cluster_assignments.shape
cluster_assignments

輸出結果:

(102672L,)

Out[105]:

array([59, 39, 33, ..., 46,  8, 17])

複製程式碼

#最後,我們建立通過壓縮調色盤和類分配結果建立壓縮後的圖片:
compressed_palette = estimator.cluster_centers_
compressed_img = np.zeros((width, height, compressed_palette.shape[1]))
label_idx = 0
for i in range(width):
    for j in range(height):
        compressed_img[i][j] = compressed_palette[cluster_assignments[label_idx]]
        label_idx += 1
plt.subplot(122)
plt.title('Original Image')
plt.imshow(original_img)
plt.axis('off')
plt.subplot(121)
plt.title('Compressed Image')
plt.imshow(compressed_img)
plt.axis('off')
plt.show()

複製程式碼