物以類聚, 「聚類算法」 使用最優(yōu)化的算法來(lái)計(jì)算數(shù)據(jù)點(diǎn)之間的距離,并將它們分組到最近的簇中。
Scipy
的聚類模塊中,進(jìn)一步分為兩個(gè)聚類子模塊:
vq
(vector quantization):提供了一種基于向量量化的聚類算法。
「vq模塊」 支持多種向量量化算法,包括K-means
、GMM
(高斯混合模型)和WAVG
(均勻分布)。
hierarchy
:提供了一種基于層次聚類的聚類算法。
「hierarchy模塊」 支持多種層次聚類算法,包括ward
、elbow
和centroid
。
總之,Scipy
中的vq
和hierarchy
模塊都提供了一種基于最小化平方誤差的聚類算法,
它們可以幫助我們快速地對(duì)大型數(shù)據(jù)集進(jìn)行分組,從而更好地理解數(shù)據(jù)的分布和模式。
1. vq 聚類
vq
聚類算法的原理是將數(shù)據(jù)點(diǎn)映射到一組稱為“超空間”的低維向量空間中,然后將它們分組到最近的簇中。
首先,我們創(chuàng)建一些測(cè)試數(shù)據(jù):(創(chuàng)建3個(gè)類別的測(cè)試數(shù)據(jù))
import numpy as np
import matplotlib.pyplot as plt
data1 = np.random.randint(0, 30, (100, 3))
data2 = np.random.randint(30, 60, (100, 3))
data3 = np.random.randint(60, 100, (100, 3))
data = np.concatenate([data1, data2, data3])
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
ax.scatter(data[:, 0], data[:, 1], data[:, 2])
plt.show()
data1
,data2
,data3
分布在3個(gè)區(qū)域,
每個(gè)數(shù)據(jù)集有 「100條」 數(shù)據(jù),每條數(shù)據(jù)有 「3個(gè)屬性」 。
1.1. 白化數(shù)據(jù)
「聚類」 之前,一般會(huì)對(duì)數(shù)據(jù)進(jìn)行 「白化」 ,所謂 「白化數(shù)據(jù)」 ,是指將數(shù)據(jù)集中的每個(gè)特征或每個(gè)樣本的值都統(tǒng)一為同一個(gè)范圍。
這樣做的目的是為了消除特征之間的量綱和數(shù)值大小差異,使得不同特征具有相似的重要性,從而更容易進(jìn)行聚類算法。
在聚類之前對(duì)數(shù)據(jù)進(jìn)行 「白化處理」 也被稱為 「預(yù)處理」 階段。
from scipy.cluster.vq import whiten
# 白化數(shù)據(jù)
normal_data = whiten(data)
# 繪制白化后的數(shù)據(jù)
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
ax.scatter(normal_data[:, 0], normal_data[:, 1], normal_data[:, 2])
plt.show()
從圖中可以看出,數(shù)據(jù)的分布情況沒(méi)有改變,只是數(shù)據(jù)的范圍從0~100
變成0.0~3.5
。
這就是白化的效果。
1.2. K-means
白化之后,就可以用K-meas方法來(lái)進(jìn)行聚類運(yùn)算了。scipy
的vq
模塊中有2個(gè)聚類函數(shù):kmeans
和kmeans2
。
kmeans
函數(shù)最少只要傳入兩個(gè) 「參數(shù)」 即可:
- 需要聚類的數(shù)據(jù),也就是上一步白化的數(shù)據(jù)
- 聚類的數(shù)目
「返回值」 有2部分:
- 各個(gè)聚類的中心點(diǎn)
- 各個(gè)點(diǎn)距離聚類中心點(diǎn)的歐式距離的平均值
from scipy.cluster.vq import kmeans
center_points, distortion = kmeans(normal_data, 3)
print(center_points)
print(distortion)
# 運(yùn)行結(jié)果
[[1.632802 1.56429847 1.51635413]
[0.48357948 0.55988559 0.48842058]
[2.81305235 2.84443275 2.78072325]]
0.5675874109728244
把三個(gè)聚類點(diǎn)繪制在圖中來(lái)看更加清楚:
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
ax.scatter(normal_data[:, 0],
normal_data[:, 1],
normal_data[:, 2])
ax.scatter(
center_points[:, 0],
center_points[:, 1],
center_points[:, 2],
color="r",
marker="^",
linewidths=5,
)
plt.show()
圖中3個(gè)紅色的點(diǎn)就是聚類的中心點(diǎn)。
1.3. K-means2
kmeans2
函數(shù)使用起來(lái)和kmeans
類似,但是返回值有區(qū)別,kmeans2
的返回的是:
- 聚類的中心點(diǎn)坐標(biāo)
- 每個(gè)聚類中所有點(diǎn)的索引
from scipy.cluster.vq import kmeans2
center_points, labels = kmeans2(normal_data, 3)
print(center_points)
print(labels)
# 運(yùn)行結(jié)果
[[2.81305235 2.84443275 2.78072325]
[1.632802 1.56429847 1.51635413]
[0.48357948 0.55988559 0.48842058]]
[2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
... ...
0 0 0 0]
可以看出,計(jì)算出的聚類中心點(diǎn)center_points
和kmeans
一樣(只是順序不一樣),labels
有0,1,2
三種值,代表normal_data
中每個(gè)點(diǎn)屬于哪個(gè)分類。
kmeans2
除了返回了聚類中心點(diǎn),還有每個(gè)數(shù)據(jù)點(diǎn)屬于哪個(gè)聚類的信息,
所以我們繪圖時(shí),可以將屬于不同聚類的點(diǎn)標(biāo)記不同的顏色。
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
arr_data = [[], [], []]
for idx, nd in enumerate(normal_data):
arr_data[labels[idx]].append(nd)
data = np.array(arr_data[0])
ax.scatter(data[:, 0], data[:, 1], data[:, 2], color='lightblue')
data = np.array(arr_data[1])
ax.scatter(data[:, 0], data[:, 1], data[:, 2], color='lightgreen')
data = np.array(arr_data[2])
ax.scatter(data[:, 0], data[:, 1], data[:, 2], color='lightyellow')
ax.scatter(
center_points[:, 0],
center_points[:, 1],
center_points[:, 2],
color="r",
marker="^",
linewidths=5,
)
plt.show()
2. hierarchy 聚類
hierarchy
聚類算法的步驟比較簡(jiǎn)單:
- 將每個(gè)樣本視為一個(gè)簇
- 計(jì)算各個(gè)簇之間的距離,將距離最近的兩個(gè)簇合并為一個(gè)簇
- 重復(fù)第二個(gè)步驟,直至到最后一個(gè)簇
from scipy.cluster.hierarchy import ward, fcluster, dendrogram
from scipy.spatial.distance import pdist
# 計(jì)算樣本數(shù)據(jù)之間的距離
# normal_data是之前白化之后的數(shù)據(jù)
dist = pdist(normal_data)
# 在距離上創(chuàng)建Ward連接矩陣
Z = ward(dist)
# 層次聚類之后的平面聚類
S = fcluster(Z, t=0.9, criterion='distance')
print(S)
# 運(yùn)行結(jié)果
[20 26 23 18 18 22 18 28 21 22 28 26 27 27 20 17 23 20 26 23 17 25 20 22
... ...
5 13 3 4 2 9 9 13 13 8 11 6]
返回的S
中有 「300個(gè)數(shù)據(jù)」 ,和normal_data
中的數(shù)據(jù)一樣多,S
中數(shù)值接近的點(diǎn),分類越接近。
從數(shù)值看聚類結(jié)果不那么明顯,scipy
的層次聚類提供了一個(gè)dendrogram
方法,內(nèi)置了matpltlib
的功能,
可以把層次聚類的結(jié)果用圖形展示出來(lái)。
P = dendrogram(Z, no_labels=True)
plt.show()
從這個(gè)圖可以看出每個(gè)數(shù)據(jù)分別屬于哪個(gè)層次的聚類。
最底層的葉子節(jié)點(diǎn)就是normal_data
中的各個(gè)數(shù)據(jù),這些數(shù)據(jù)的索引信息可以從 P
中獲取。
# P是一個(gè)字典,包含聚類之后的信息
# key=ivl 是圖中最底層葉子節(jié)點(diǎn)在 normal_data 中的索引
print(P["ivl"])
# 運(yùn)行結(jié)果
['236', '269', '244', ... ... '181', '175', '156', '157']
3. 總結(jié)
聚類分析可以幫助我們發(fā)現(xiàn)數(shù)據(jù)集中的內(nèi)在結(jié)構(gòu)、模式和相似性,從而更好地理解數(shù)據(jù)。
使用Scipy
庫(kù),可以幫助我們高效的完成數(shù)據(jù)的聚類分析,而不用去具體了解聚類分析算法的實(shí)現(xiàn)方式。
-
處理器
+關(guān)注
關(guān)注
68文章
19286瀏覽量
229852 -
向量機(jī)
+關(guān)注
關(guān)注
0文章
166瀏覽量
20879 -
GMM
+關(guān)注
關(guān)注
0文章
5瀏覽量
7258
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論