【火爐煉AI】機器學習020-使用K-means演算法對資料進行聚類分析

煉丹老頑童發表於2018-09-03

【火爐煉AI】機器學習020-使用K-means演算法對資料進行聚類分析

(本文所使用的Python庫和版本號: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )

前面的機器學習類文章(編號從010-019)都是關於監督學習,但是從本篇文章開始,煉丹老頑童要開始講解無監督學習方面,無監督學習是指處理的資料沒有任何形式的標記,我們沒有對訓練資料集進行實現的類別劃分,故而相當於抹黑處理,要讓機器學習自己找出樣本所屬的類別,那麼機器學習通過什麼方式來找出“所屬類別”了?這就是聚類演算法的作用了。

聚類演算法,其核心思想就是中國的“人以類聚,物以群分”,就是機器學習將通過一定的演算法來將樣本劃分類別,使得相互之間相似的樣本劃分為一個類別,不相似的樣本劃分為不同的類別中。

K-means演算法是最流行的聚類演算法之一,這種演算法常常利用資料的不同屬性將輸入資料劃分為K組,這種劃分是使用最優化的技術實現的,讓各組內的資料點與該組中心點的距離平方和最小化。

說起來很抽象,讓人感覺雲裡霧裡,那麼我們看一個簡單的例項吧。


1. 準備資料集

本次所使用的資料集是我前面的文章【火爐煉AI】機器學習010-用樸素貝葉斯分類器解決多分類問題中所採用的資料集,一個具有四種不同類別,兩種不同features的小資料集,其載入方法和顯示方法如下所示。

# 準備資料集
data_path='E:\PyProjects\DataSet\FireAI/data_multivar.txt'
df=pd.read_csv(data_path,header=None)
# print(df.head())
# print(df.info()) # 檢視資料資訊,確保沒有錯誤
dataset_X,dataset_y=df.iloc[:,:-1],df.iloc[:,-1]
# print(dataset_X.head())
print(dataset_X.info())
print('-'*100)
print(dataset_y.head())
dataset_X=dataset_X.values
dataset_y=dataset_y.values
# print(dataset_X.shape) # (400, 2)
# print(dataset_y.shape) # (400,)
複製程式碼

-------------------------------------輸---------出--------------------

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 400 entries, 0 to 399
Data columns (total 2 columns):
0 400 non-null float64
1 400 non-null float64
dtypes: float64(2)
memory usage: 6.3 KB
None

--------------------------------------------完------------------------

表明結果資料集已經正確地載入到記憶體中,且每一個features中都沒有Null值,我們無需做進一步的缺失值處理。

下面將這個資料集進行2D視覺化,如下是視覺化的程式碼:

# 無標籤資料集視覺化,將第一列feature作為X,第二列feature作為y
def visual_2D_dataset_dist(dataset):
    '''將二維資料集dataset顯示在散點圖中'''
    assert dataset.shape[1]==2,'only support dataset with 2 features'
    plt.figure()
    X=dataset[:,0]
    Y=dataset[:,1]
    plt.scatter(X,Y,marker='v',c='g',label='dataset')
    
    X_min,X_max=np.min(X)-1,np.max(X)+1
    Y_min,Y_max=np.min(Y)-1,np.max(Y)+1
    plt.title('dataset distribution')
    plt.xlim(X_min,X_max)
    plt.ylim(Y_min,Y_max)
    plt.xlabel('feature_0')
    plt.ylabel('feature_1')
    plt.legend()
    
visual_2D_dataset_dist(dataset_X)
複製程式碼

得到的結果如下:

無標籤資料集的視覺化

########################小**********結#####################

1. 本資料集的載入很簡單,只需用Pandas就可以直接載入,且不需要做其他處理。

2. 此處需要注意,無標籤資料集的二維平面視覺化,不能使用label資料,故而此處的視覺化函式和我以往文章中的視覺化函式是不一樣的,此處需要額外注意。

3. 從二維平面散點圖中可以看出,這個資料集大概可以分為4個不同的類別,即資料都分佈在四個族群裡,這就是我們可以用K-mean演算法的基礎。

########################################################


2. 構建K-means演算法

構建K-means演算法的過程很簡單,和其他的SVM,隨機森林演算法的構建方式一樣,如下程式碼:

# 定義一個k-means物件
from sklearn.cluster import KMeans
kmeans=KMeans(init='k-means++',n_clusters=4,n_init=10)
# 這幾個引數是初始化設定的,其中n_clusters是從二維散點圖中看出大概有4個族群
kmeans.fit(dataset_X)
複製程式碼

-------------------------------------輸---------出------------------

KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,
n_clusters=4, n_init=10, n_jobs=1, precompute_distances='auto',
random_state=None, tol=0.0001, verbose=0)

--------------------------------------------完---------------------

雖然此處我們定義了一個KMeans物件,且使用我們的無標籤資料集進行了訓練,可是訓練結果怎麼樣了?我們怎麼知道k-means演算法是否正確的劃分了不同類別?

所以我們需要一個視覺化的結果,就像前面文章中提到的SVM分類結果圖一樣,此處我們定義了一個專門用於視覺化K-means聚類結果的函式,並用該函式來檢視此處聚類的效果。程式碼如下:

def visual_kmeans_effect(k_means,dataset):
    assert dataset.shape[1]==2,'only support dataset with 2 features'
    X=dataset[:,0]
    Y=dataset[:,1]
    X_min,X_max=np.min(X)-1,np.max(X)+1
    Y_min,Y_max=np.min(Y)-1,np.max(Y)+1
    X_values,Y_values=np.meshgrid(np.arange(X_min,X_max,0.01),
                                  np.arange(Y_min,Y_max,0.01))
    # 預測網格點的標記
    predict_labels=k_means.predict(np.c_[X_values.ravel(),Y_values.ravel()])
    predict_labels=predict_labels.reshape(X_values.shape)
    plt.figure()
    plt.imshow(predict_labels,interpolation='nearest',
               extent=(X_values.min(),X_values.max(),
                       Y_values.min(),Y_values.max()),
               cmap=plt.cm.Paired,
               aspect='auto',
               origin='lower')
    
    # 將資料集繪製到圖表中
    plt.scatter(X,Y,marker='v',facecolors='none',edgecolors='k',s=30)
    
    # 將中心點回執到圖中
    centroids=k_means.cluster_centers_
    plt.scatter(centroids[:,0],centroids[:,1],marker='o',
                s=100,linewidths=2,color='k',zorder=5,facecolors='b')
    plt.title('K-Means effect graph')
    plt.xlim(X_min,X_max)
    plt.ylim(Y_min,Y_max)
    plt.xlabel('feature_0')
    plt.ylabel('feature_1')
    plt.show()
    
visual_kmeans_effect(kmeans,dataset_X)
複製程式碼

K-means聚類對本資料集的聚類結果

########################小**********結###################

1. 定義K-means聚類演算法的方法很簡單,只需要從sklearn.cluster中匯入KMeans,並定義一個KMeans物件即可,直接用fit()函式可以直接訓練。

2. 此處使用k-means聚類演算法對資料進行了聚類分析,可以使用函式visual_kmeans_effect()來直接檢視聚類後的效果圖。

3. 雖然可以直觀看到效果圖,但效果圖還是難以量化k-means聚類演算法的準確度,這些內容將在後續文章中講解。

#######################################################


注:本部分程式碼已經全部上傳到(我的github)上,歡迎下載。

參考資料:

1, Python機器學習經典例項,Prateek Joshi著,陶俊傑,陳小莉譯

相關文章