分類問題概述
前面,我們已經(jīng)討論了關(guān)于數(shù)據(jù)預(yù)處理的一些細(xì)節(jié)。而在數(shù)據(jù)分析實(shí)戰(zhàn)中,我們面對的一項(xiàng)重要工作,就是對數(shù)據(jù)進(jìn)行分類。
舉個(gè)例子,如果你拿到了一份來自電力部門的數(shù)據(jù)集,里面包含了一個(gè)城市的個(gè)人及企業(yè)每個(gè)月的用電數(shù)據(jù),繳費(fèi)數(shù)據(jù)等。我們就可以使用這份數(shù)據(jù)去對個(gè)人用戶進(jìn)行信用評估分類,調(diào)整不同類別用戶的電卡授信額度,對高概率拖欠電費(fèi)用戶每月進(jìn)行短信催繳提醒。我們也可以對企業(yè)用電進(jìn)行分析,根據(jù)用電量和用電時(shí)段進(jìn)行分類,然后做一些保障性供電的方案。這里面就涉及到大量的數(shù)據(jù)分類應(yīng)用。
除此之外,像深度學(xué)習(xí)中會(huì)遇到的圖像識別也是分類問題的應(yīng)用。判斷一張照片中的主體是貓還是狗?這都是典型的分類問題。生活中,像上面例子的情況還非常之多,幾乎每個(gè)行業(yè)都會(huì)面臨大量需要分類的問題。分類問題也是我們在數(shù)據(jù)分析中,遇到頻率最高的問題。
分類的方法主要有
- 線性和非線性分類
- 支持向量機(jī)
- 決策樹
- 隨機(jī)森林
- 神經(jīng)網(wǎng)絡(luò)
程序如何進(jìn)行一個(gè)簡單分類?
在討論各種分類方法前,我想先討論一個(gè)可以幫助入門用戶的問題,那就是程序如何進(jìn)行一個(gè)簡單的分類?
首先,我們回想一下人是如何在生活中完成事物分類的。例如區(qū)分房子和車?其實(shí),當(dāng)我們?nèi)嗽趨^(qū)分事物時(shí),一般是抓住了一個(gè)或多個(gè)特征。例如,車有輪子、金屬外殼、擋風(fēng)玻璃等。所以,特征是對事物分類的關(guān)鍵要素。
當(dāng)程序在進(jìn)行分類是,它也是抓住了特征,只是這里的特征和我們所看到的特征有一些區(qū)別。一般情況下,我們看到的是圖像,而程序看到的是數(shù)值。
如果我們想讓程序來區(qū)分房子和車,最簡單的方法就是先確定它們具有的共同特征。例如,物體都包含長度和高度。然后,我們讓程序記錄下一些數(shù)據(jù)(訓(xùn)練數(shù)據(jù))。
為什么要聚類?
當(dāng)我們拿到一些原始數(shù)據(jù)時(shí),這些數(shù)據(jù)是沒有任何規(guī)律可循的。聚類,就是發(fā)生數(shù)據(jù)之間內(nèi)在聯(lián)系的方法。舉個(gè)形象一點(diǎn)的例子:動(dòng)物園里有很多動(dòng)物,在沒有聚類的情況下,每一種動(dòng)物都是單獨(dú)的類別。如果我們統(tǒng)計(jì)每種動(dòng)物特點(diǎn),腿的數(shù)量、有無耳朵、皮毛顏色、有無尾巴等。最終,我們就可以使用聚類將所有的動(dòng)物分成數(shù)個(gè)大類。除此之外,書籍聚類、文檔聚類、房屋類型聚類等,都會(huì)使用到聚類算法。
聚類分析與分類的區(qū)別
有可能你會(huì)在分類和聚類之間疑惑。一般來講,在一個(gè)機(jī)器學(xué)習(xí)任務(wù)或者數(shù)據(jù)分析實(shí)例中,我們會(huì)先采用聚類算法對數(shù)據(jù)進(jìn)行處理。使用聚類算法對歷史數(shù)據(jù)處理之后,就可以人為的給每一種類別打上標(biāo)簽。而這些存在標(biāo)簽的數(shù)據(jù),就可以被應(yīng)用到下一步的分類學(xué)習(xí)中。簡而言之、在執(zhí)行聚類之前,我們的數(shù)據(jù)沒有任何類別可言。但在執(zhí)行分類之前,我們應(yīng)該已經(jīng)有了類別,才能對新數(shù)據(jù)進(jìn)行分類。
下面這張圖,可能讓你對分類和聚類理解的更加到位:
K-均值聚類是最常用的聚類方法之一。從它的名字來講,K 代表最終將全部樣本數(shù)據(jù)集和聚為 K 個(gè)類別。而「均值」代表在聚類的過程中,我們計(jì)算聚類中心點(diǎn)的特征向量時(shí),需要采用求相鄰樣本點(diǎn)特征向量均值的方式進(jìn)行。例如,我們將 X1=(x1, y1), X2=(x2, y2), X3=(x3, y3) 聚為一類時(shí),中心點(diǎn)坐標(biāo) O(o1, o1) 為:o1 = (x1+x2+x3)/3, o2=(y1+y2+y3)/3。
在一個(gè)標(biāo)準(zhǔn)的 k 均值聚類過程中,我們首先要人為確定 k 值的大小,也就是聚類的數(shù)量。然后,我們會(huì)使用一種叫Forgy的方法初始化聚類,F(xiàn)orgy 也就是隨機(jī)地從數(shù)據(jù)集中選擇 k 個(gè)觀測作為初始的均值點(diǎn)。例如,下圖中,我們定 k=3,然后隨機(jī)選擇 3 個(gè)數(shù)據(jù)點(diǎn)初始化聚類。
然后,我們以這三個(gè)樣本點(diǎn)(紅色)為基準(zhǔn),將剩余的數(shù)據(jù)點(diǎn)按照與其距離最近的標(biāo)準(zhǔn)進(jìn)行類別劃分。
這樣,就得到了通過綠色線條劃分的 A, B, C 三個(gè)區(qū)域。
接下來,我們求解各區(qū)域中數(shù)據(jù)點(diǎn)集的中心點(diǎn), 這一步也就是更新。然后得到三個(gè)紫色中心點(diǎn)。重復(fù)上面的步驟,得到由黃色線條劃分的 D, E, F 三個(gè)區(qū)域。
重復(fù)上面的步驟,直到三個(gè)區(qū)域的中心點(diǎn)變化非常小或沒有變化時(shí),終止迭代。最終,就將全部數(shù)據(jù)劃分為 3 了類別。
k 均值的迭代過程非常簡單,但是非常有效。
K 值選擇
看完上面的示例,你應(yīng)該對聚類的過程比較清晰了。簡而言之,完成一項(xiàng)聚類任務(wù)分為三步:
- 第一步:選擇聚類數(shù)量,也就是 K 值的大小。
- 第二步:實(shí)施聚類算法,k-均值等。
- 第三步:對聚類結(jié)果進(jìn)行人工標(biāo)注和分析。
接下來,我們就來討論一下如何選擇 k 值。我們要相信,k 值的大小并不是一拍腦袋就隨便選一個(gè)。一個(gè)數(shù)據(jù)集該聚為多少個(gè)類,應(yīng)該有一個(gè)比較合理的選擇機(jī)制。
當(dāng)我們在使用 K-Means 聚類時(shí),我們一般通過計(jì)算輪廓系數(shù),來確定 k 值的大小。輪廓系數(shù)(Silhouette Coefficient),是聚類效果好壞的一種評價(jià)方式。輪廓系數(shù)結(jié)合內(nèi)聚度(Cohesion)和分離度(Separation)兩種因素,可以用來在相同原始數(shù)據(jù)的基礎(chǔ)上用來評價(jià)不同算法、或者算法不同運(yùn)行方式對聚類結(jié)果所產(chǎn)生的影響。
對于某一點(diǎn) i,我們用 a(i) 表示 i 距離同類中其它點(diǎn)之間的距離的平均值,而 b(i) 表示 i 到所有非同類點(diǎn)的平均距離,然后取最小值。于是,i 的輪廓系數(shù)計(jì)算如下:
然后,我們計(jì)算數(shù)據(jù)集中所有點(diǎn)的輪廓系數(shù),最終以平均值作為當(dāng)前聚類的整體輪廓系數(shù)。整體輪廓系數(shù)介于 [-1,1] ,越趨近于 1 代表聚類的效果越好。
scikit-learn 中,sklearn.metrics.silhouette_score() 方法可以用來計(jì)算所聚類數(shù)據(jù)集的輪廓系數(shù)。
接下來,我們就舉一個(gè)例子來計(jì)算聚類過程中的輪廓系數(shù),這里我們使用 three_class_data.csv 數(shù)據(jù)集用于演示,你需要先下載該文件:
wget http://labfile.oss.aliyuncs.com/courses/764/three_class_data.csv
輪廓系數(shù)計(jì)算如下:
from sklearn.cluster import k_means
from sklearn.metrics import silhouette_score
from matplotlib import pyplot as plt
import pandas as pd
# 導(dǎo)入數(shù)據(jù)
data = pd.read_csv(r"c:\users\clemente\Desktop\three_class_data.csv", header=0)
x = data[["x", "y"]]
# 建立模型
score = []
# 依次計(jì)算 2 到 12 類的輪廓系數(shù)
for i in range(10):
model = k_means(x, n_clusters=i + 2)
score.append(silhouette_score(x, model[1]))
plt.subplot(1, 2, 1)
plt.scatter(data['x'], data['y'])
plt.subplot(1, 2, 2)
plt.plot(range(2, 12, 1), score)
plt.show()
我們可以看到,下方左圖為原數(shù)據(jù)集散點(diǎn)圖。而右圖是依次計(jì)算 2,3,……,12 類的輪廓系數(shù)折線圖。右圖明顯看到,當(dāng)k取3 時(shí),輪廓系數(shù)最大。也就是說,推薦我們將原數(shù)據(jù)集聚為 3 類。這也印證了我們?nèi)庋鄣挠^測結(jié)果。
其實(shí),我們在計(jì)算輪廓系數(shù)時(shí),已經(jīng)用到了 k 均值算法,將數(shù)據(jù)集從 2 類依次變化到 12 類。我們將 k 均值算法選擇 k=3 時(shí)的聚類結(jié)果繪制出來。
from sklearn.cluster import k_means
from matplotlib import pyplot as plt
import pandas as pd
# 導(dǎo)入數(shù)據(jù)
data = pd.read_csv("three_class_data.csv", header=0)
x = data[["x", "y"]]
# 建立模型
model = k_means(x, n_clusters=3)
# 繪圖
plt.scatter(data['x'], data['y'], c=model[1])
plt.show()
同樣,我們可以繪制出k-均值聚類的決策邊界。
其他聚類方法
除了我們會(huì)經(jīng)常用到的 K-均值聚類算法,Scikit-learn 還為我們提供了一些常見的聚類算法。
Mini Batch K-Means Mini Batch K-Means 整體上和 K-Means 很相似,它是 K-Means 的一個(gè)變種形式。與 K-Means 不同的地方在于,其每次從全部數(shù)據(jù)集中抽樣小數(shù)據(jù)集進(jìn)行迭代。Mini Batch K-Means 算法在不對聚類效果造成較大影響的前提下,大大縮短了計(jì)算時(shí)間。
Affinity Propagation Affinity Propagation 又被稱為親和傳播聚類。Affinity Propagation 是基于數(shù)據(jù)點(diǎn)進(jìn)行消息傳遞的理念設(shè)計(jì)的。與 K-Means 等聚類算法不同的地方在于,親和傳播聚類不需要提前確定聚類的數(shù)量,即 K 值。但是運(yùn)行效率較低。
均值漂移聚類 Mean Shift MeanShift 。Mean Shift 聚類的目的是找出最密集的區(qū)域, 同樣也是一個(gè)迭代過程。在聚類過程中,首先算出初始中心點(diǎn)的偏移均值,將該點(diǎn)移動(dòng)到此偏移均值,然后以此為新的起始點(diǎn),繼續(xù)移動(dòng),直到滿足最終的條件。Mean Shift 也引入了核函數(shù),用于改善聚類效果。除此之外,Mean Shift 在圖像分割,視頻跟蹤等領(lǐng)域也有較好的應(yīng)用。
譜聚類 Spectral Clustering Spectral Clustering 。譜聚類同樣也是一種比較常見的聚類方法,它是從圖論中演化而來的。譜聚類一開始將特征空間中的點(diǎn)用邊連接起來。其中,兩個(gè)點(diǎn)距離越遠(yuǎn),那么邊所對應(yīng)的權(quán)值越低。同樣,距離越近,那么邊對應(yīng)的權(quán)值越高。最后,通過對所有特征點(diǎn)組成的網(wǎng)絡(luò)進(jìn)行切分,讓切分后的子圖互相連接的邊權(quán)重之和盡可能的低,而各子圖內(nèi)部邊組成的權(quán)值和經(jīng)可能高,從而達(dá)到聚類的效果。譜聚類的好處是能夠識別任意形狀的樣本空間,并且可以得到全局最優(yōu)解。
層次聚類 Agglomerative Clustering Agglomerative Clustering 。層次聚類算法是將所有的樣本點(diǎn)自下而上合并組成一棵樹的過程,它不再產(chǎn)生單一聚類,而是產(chǎn)生一個(gè)聚類層次。層次聚類通過計(jì)算各樣本數(shù)據(jù)之間的距離來確定它們的相似性關(guān)系,一般情況下,距離越小九代表相似度越高。最后,將相似度越高的樣本歸為一類,依次迭代,直到生成一棵樹。由于層次聚類涉及到循環(huán)計(jì)算,所以時(shí)間復(fù)雜度比較高,運(yùn)行速度較慢。
基于層次方法的平衡迭代規(guī)約和聚類 Birch Birch 是英文 Balanced Iterative Reducing and Clustering Using Hierarchies 的簡稱,名字實(shí)在太長。Birch 引入了聚類特征樹(CF樹),先通過其他的聚類方法將其聚類成小的簇,然后再在簇間采用 CF 樹對簇聚類。Birch 的優(yōu)點(diǎn)是,只需要單次掃描數(shù)據(jù)集即可完成聚類,運(yùn)行速度較快,特別適合大數(shù)據(jù)集。
基于空間密度與噪聲應(yīng)用的聚類方法 DBSCAN DBSCAN 是英文 Density-based spatial clustering of applications with noise 的簡稱,名字同樣很長。DBSCAN 基于密度概念,要求聚類空間中的一定區(qū)域內(nèi)所包含的樣本數(shù)目不小于某一給定閾值。算法運(yùn)行速度快,且能夠有效處理特征空間中存在的噪聲點(diǎn)。但是對于密度分布不均勻的樣本集合,DBSCAN 的表現(xiàn)較差。
接下來,我們利用上面的數(shù)據(jù)集對 8 種不同的聚類方法,來一次簡單的橫向?qū)Ρ取?/p>
我們可以看出,結(jié)果比較理想的有:KMeans, MiniBatchKMeans, MeanShift, SpectralClustering, AgglomerativeClustering。而 Birch 和 DBSCAN 在默認(rèn)參數(shù)下只得到一個(gè)有效類別,AffinityPropagation 卻得到了太多的類別。從聚類用時(shí)來看,AgglomerativeClustering 聚類效果不錯(cuò),且用時(shí)較短。
聚類算法選擇
面對上面的對比結(jié)果,并不是某幾個(gè)算法不好,而是每一種方法適用的情況都各不相同。下面,我們就簡單地說明一下,聚類算法的選擇步驟:
- 如果已知 K 值,即聚類的數(shù)量:
樣本數(shù)量 < 1 萬,首選 Kmeans,效果不好再選擇 SpectralClustering。
樣本數(shù)量 > 1 萬,首選 MiniBatch Kmeans。
- 如果 K 值未知:
樣本數(shù)量 < 1 萬,首選 MeanShift。
樣本數(shù)量 > 1 萬,依靠經(jīng)驗(yàn)靈活應(yīng)對了。