【火爐煉AI】機器學習024-無監督學習模型的效能評估--輪廓係數

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

【火爐煉AI】機器學習024-無監督學習模型的效能評估--輪廓係數

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

前面我們學習過監督學習模型的效能評估,由於資料集有標記,所以我們可以將模型預測值和真實的標記做比較,計算兩者之間的差異,從而來評估監督學習模型的好壞。

但是,對於無監督學習模型,由於沒有標記資料,我們該怎麼樣評估一個模型的好壞了?顯然,此時我們不能採用和監督學習模型一樣的評估方式了,而要另闢蹊徑。


1. 度量聚類模型的好壞---輪廓係數

有很多種度量聚類模型的演算法,其中一個比較好用的演算法就是輪廓係數(Silhouette Coefficient)指標。這個指標度量模型將資料集分類的離散程度,即判斷資料集是否分離的合理,判斷一個叢集中的資料點是不是足夠緊密(即內聚度),一個叢集中的點和其他叢集中的點相隔是否足夠遠(即分離度),故而輪廓係數結合了內聚度和分離度這兩種因素,可以用來在相同原始資料的基礎上用來評價不同演算法,或者演算法不同執行方式對聚類結果所產生的影響。

以下是百度對輪廓係數的說明,此處我直接搬過來用了。

輪廓係數的計算方式說明

【火爐煉AI】機器學習024-無監督學習模型的效能評估--輪廓係數


2. 使用輪廓係數評估K-means模型

首先是用pandas載入資料集,檢視資料集載入是否正確,這部分可以看我的具體程式碼,此處省略。

然後我隨機的構建一個K-means模型,用這個模型來訓練資料集,並用輪廓係數來評估該模型的優虐,程式碼如下:

from sklearn.cluster import KMeans
# 構建一個聚類模型,此處用K-means演算法
model=KMeans(init='k-means++',n_clusters=3,n_init=10) 
# 原始K-means演算法最開始隨機選取資料集中K個點作為聚類中心,
# 分類結果會因為初始點的選取不同而有所區別
# 而K-means++演算法改變這種隨機選取方法,能顯著的改善分類結果的最終誤差
# 此處我隨機的指定n_cluster=3,看看評估結果
model.fit(dataset)
複製程式碼
# 使用輪廓係數評估模型的優虐
from sklearn.metrics import silhouette_score
si_score=silhouette_score(dataset,model.labels_,
                          metric='euclidean',sample_size=len(dataset))
print('si_score: {:.4f}'.format(si_score))
複製程式碼

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

si_score: 0.5572

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

從上面的程式碼可以看出,計算輪廓係數是非常簡單的。

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

1, sklearn中已經整合了輪廓係數的計算方法,我們只需要呼叫該函式即可,使用非常簡單。

2, 有了模型的評估指標,我們就可以對模型進行一些優化,提升模型的效能,或者用該指標來比較兩個不同模型在相同資料集上的效果,從而為我們選擇模型提供指導。

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


3. K-means模型效能的提升方法

上面在評價K-means模型時,我們隨機指定了劃分的族群數量,即K值,但是有了評估指標之後,我們就可以優化這個K值,其基本思路是:遍歷各種可能的K值,計算每種K值之下的輪廓係數,選擇輪廓係數最大的K值,即為最優的族群數量。

下面我先定義一個函式,專門用來計算K-means演算法的最優K值,這個函式具有一定的通用性,也可以用於其它場合。如下為程式碼:

# K-means模型的提升
# 在定義K-means時,往往我們很難知道最優的簇群數量,即K值,
# 故而可以通過遍歷得到最優值
def get_optimal_K(dataset,K_list=None):
    k_lists=K_list if K_list else range(2,15)
    scores=[]
    for k in k_lists:
        kmeans=KMeans(init='k-means++',n_clusters=k,n_init=10)
        kmeans.fit(dataset)
        scores.append(silhouette_score(dataset,kmeans.labels_,
                                      metric='euclidean',
                                      sample_size=len(dataset)))
    return k_lists[scores.index(max(scores))],scores
複製程式碼

有了這個通用性求解最優K值的函式,我們就可以用來獲取這個資料集的最佳K值,如下為程式碼:

optimal_K, scores=get_optimal_K(dataset)
print('optimal_K is: {}, all scores: {}'.format(optimal_K,scores))

# or:
# optimal_K, scores=get_optimal_K(dataset,[2,4,6,8,10,12])
# print('optimal_K is: {}, all scores: {}'.format(optimal_K,scores))
複製程式碼

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

optimal_K is: 5, all scores: [0.5290397175472954, 0.5551898802099927, 0.5832757517829593, 0.6582796909760834, 0.5823584119482567, 0.5238070812131604, 0.4674788136779971, 0.38754867890367795, 0.41013511008667664, 0.41972398760085106, 0.41614459998617975, 0.3485105795903397, 0.357222732243728]

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

從上面的結果可以看出,函式計算出來的最優K值為5,即最好的情況是將本資料集劃分為5個類別,且在K=5時的輪廓係數為0.6583。

下面我們來看一下這個資料集在平面上的分佈情況,看看是不是資料集有5種類別,如下所示是使用visual_2D_dataset()函式之後得到的平面分佈圖。

本專案資料集在二維平面上的分佈情況

從上圖中可以看出,的確資料集中到五個不同的簇群中。那麼用最優的引數來聚類這些資料集,得到什麼樣的效果了?如下是平面的聚類效果圖。

使用最優K引數來聚類資料得到的效果圖

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

1, 使用輪廓係數可以對模型進行引數優化,此處我們定義了一個通用性函式,可以直接計算出資料集的最佳K值。

2, 當然,也可以用輪廓係數來優化其他引數,只要稍微修改一下上面的通用函式即可。

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


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

參考資料:

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

相關文章