「機械学習の公式導出とコード実装」の学習ノート、自分の学習プロセスを記録します。詳細な内容については、著者の本を購入してください。
クラスター分析と K-means クラスタリング アルゴリズム
聚类分析
( cluster analysis
) は古典的な教師なし学習アルゴリズムのクラスであり、特定のサンプルの場合、クラスター分析では、特征相似度
またはを測定することにより距离
、サンプルが自動的にいくつかのカテゴリに分割されます。
1 距離測定と類似性測定
距離測定と類似性測定はクラスター分析の中核概念であり、ほとんどのクラスタリング アルゴリズムは距離測定に基づいています。一般的に使用される距離の尺度には闵氏距离
とが含まれ马氏距离
、一般に使用される類似性の尺度には相关系数
など夹角余弦
があります。
(1)闵氏距离
つまり闵可夫斯基距离
( Minkowski distance
)、距離は次のように定義されます。m
次元ベクトル サンプル のセットX
、xi
、xj
∈ X
、xi
=が与えられ(x1i,x2i,...xmi)T
た場合、サンプル xi とサンプル xj の間の最小距離は次のように定義できます。
dij = ( ∑ k = 1 m ∣ xki − xkj ∣ p ) 1 p , p ≥ 1 d_{ij}=\left ( \sum_{k=1}^{m}\left | x_{ki}-x_{kj} \right | ^ {p} \right )^{\frac{1}{p} }、ページ 1dイジ=(k = 1∑メートル∣ xに−バツkj∣p )p1、p≥1そのとき、 ()になることが
容易にわかります: dij = ∑ k = 1 m ∣ xki − xkj ∣ d_{ij}=\sum_{k=1}^{m}\left | x_{ki }-x_{kj} \right |p=1
闵氏距离
曼哈顿距离
Manhatan distance
dイジ=k = 1∑メートル∣ xに−バツkj∣
そのときp=2
、()闵氏距离
となる: dij = ( ∑ k = 1 m ∣ xki − xkj ∣ 2 ) 1 2 d_{ij}=\left ( \sum_{k=1}^{m}\left | x_ {ki}-x_{kj} \right | ^{2} \right )^{\frac{1}{2} }欧氏距离
Euclidean distance
dイジ=(k = 1∑メートル∣ xに−バツkj∣2 )21
このときp=∞
、( )闵氏距离
とも呼ばれます: dij = max ∣ xki − xkj ∣ d_{ij}=max\left | x_{ki}-x_{kj} \right |切比雪夫距离
Chebyshev distance
dイジ=マ×∣ xに−バツkj∣
(2)马氏距离
正式名称马哈拉诺比斯距离
(Mahalanobis distance
) は、さまざまな特徴間の相関を測定するクラスタリング測定手法です。サンプル セットが与えられX=(xij)mxn
、サンプルの共分散行列が であると仮定するとS
、サンプル xi とサンプル xj の間のマハラノビス距離は次のように定義できます。
dij = [ ( xi − xj ) TS − 1 ( xi − xj ) ] 1 2 d_ {ij}=\left [\left(x_{i}-x_{j}\right)^{T} S^{-1}\left(x_{i}-x_{j}\right)\right] ^{\frac{1}{2}}dイジ=[ ( x私は−バツj)TS− 1( ×私は−バツj) ]21
単位行列の場合S
、つまりサンプルの特徴が互いに独立で分散が 1 の場合、マハラノビス距離はユークリッド距離になります。
(3) 相関係数は、サンプルの類似性を測定するために最も一般的に使用される方法です。相関係数を定義するにはさまざまな方法がありますが、より一般的に使用されるのはピアソン相関です。相関係数が 1 に近づくほど、2 つのサンプルはより類似します。サンプル xi とサンプル xj の間の相関係数は次のように定義できます。
rij = ∑ k = 1 m ( xki − x ˉ i ) ( xkj − x ˉ j ) [ ∑ k = 1 m ( xki − x ˉ i ) 2 ∑ k = 1 m ( xkj − x ˉ j ) 2 ] 1 2 r_{ij}=\frac{\sum_{k=1}^{m }\left ( x_ {ki}-\bar{x}_{i}\right )\left ( x_{kj}-\bar{x}_{j}\right )}{\left [ \sum_{k =1}^{ m} \left ( x_{ki}-\bar{x}_{i}\right )^{2} \sum_{k=1}^{m} \left ( x_{kj}- \bar{x} _{j}\right )^{2} \right ] ^{\frac{1}{2} } }rイジ=[ ∑k = 1メートル( ×に−バツˉ私は)2∑k = 1メートル( ×kj−バツˉj)2 ]21∑k = 1メートル( ×に−バツˉ私は)( ×kj−バツˉj)
上の式は少し複雑に見えますが、実際は次のとおりです。
r ( X , Y ) = C ov ( X , Y ) V ar [ X ] V ar [ Y ] r\left ( X,Y \right ) =\frac { Cov\left ( X,Y \right ) }{\sqrt{Var\left [ X \right ] Var\left [ Y \right ] } }r( X ,や)=だった[ X ]だった[ Y ]Cov_ _ _( X ,や)
(4) 余弦夹角
( angle cosine
) も 2 つのサンプルの類似性を測定する方法です。夾角のコサインが 1 に近づくほど、2 つのサンプルは類似します。
類似度 = cos ( θ ) = A ⋅ B ∥ A ∥ ∥ B ∥ 類似度=cos\left ( \theta \right ) =\frac {A\cdot B} {\left\|A\right\|\left\|B\right\|}似たようなこと_ _ _=コス(私)=∥ ∥ _∥ B ∥あ⋅B
サンプル xi とサンプル xj の間の夾角の余弦は、次のように定義できます。
AC ij = ∑ k = 1 mxkixkj [ ∑ k = 1 mxki 2 ∑ k = 1 mxkj 2 ] 1 2 AC_{ij}=\frac{\ sum_{ k=1}^{m}x_{ki}x_{kj}}{\left [ \sum_{k=1}^{m}x_{ki}^{2} \sum_{k=1}^ {m }x_{kj}^{2}\right ] ^{\frac{1}{2}}}AC_イジ=[ ∑k = 1メートルバツに2∑k = 1メートルバツkj2]21∑k = 1メートルバツにバツkj
2 クラスタリングアルゴリズム一覧
クラスタリング アルゴリズムは、類似したサンプルを同じクラスター (クラスター) に分類します。これにより、同じクラスター内のサンプル オブジェクトの類似性が可能な限り大きくなり、異なるクラスター内のサンプル オブジェクトの差も可能な限り大きくなります。一般的に使用されるクラスタリング アルゴリズムは次のとおりです。
基于距离的聚类
: このタイプのアルゴリズムの目的は、クラスター内の距離を小さくし、クラスター間の距離を大きくすることであり、最も典型的なアルゴリズムですk均值聚类
。基于密度的聚类
: このタイプのアルゴリズムは、サンプルの隣接領域の密度に応じて分割されており、最も一般的な密度クラスタリング アルゴリズムは間違いなく ですDBSCAN算法
。层次聚类算法
: 階層クラスタリングのマージや階層クラスタリングの分割などを含みます。- グラフ理論に基づいています
谱聚类
。
さまざまなデータセットに対する sklearn の 10 クラスのクラスタリング アルゴリズムの効果の比較。
3 K 平均法アルゴリズムの原理
4 K 平均法アルゴリズムの numpy 実装
import numpy as np
# 定义欧氏距离
def euclidean_distance(x, y):
distance = 0
for i in range(len(x)):
distance += np.power((x[i] - y[i]), 2)
return np.sqrt(distance)
# 质心初始化
def centroids_init(X, k): # 训练样本,质心个数(聚类簇数)
m, n = X.shape # 样本数和特征数
centroids = np.zeros((k, n)) # 初始化质心矩阵,大小为质心个数*特征数
for i in range(k):
centroid = X[np.random.choice(range(m))]
centroids[i] = centroid
return centroids # centroids:质心矩阵,k个长度为n的从m个样本中选取的样本
# 求单个样本所属最近质心的索引
def closest_centroid(x, centroids): # 单个样本实例,质心矩阵
closest_i, closest_dist = 0, float('inf')
for i, centroid in enumerate(centroids):
distance = euclidean_distance(x, centroid)
if distance < closest_dist:
closest_i = i
closest_dist = distance
return closest_i # closest_i:最近质心
# 构建簇与分配样本
def build_clusters(centroids, k, X): # 质心矩阵,质心个数, 训练样本
clusters = [[] for _ in range(k)] # 初始化簇列表
for x_i, x in enumerate(X):
centroid_i = closest_centroid(x, centroids) # 样本最近质心的下标
clusters[centroid_i].append(x_i) # 样本下标加入簇矩阵中
return clusters # 聚类簇
# 计算新的质心
def calculate_centroids(clusters, k, X):
n = X.shape[1] # 特征数
centroids = np.zeros((k, n)) # 初始化质心矩阵
for i, cluster in enumerate(clusters):
centroid = np.mean(X[cluster], axis=0) # 计算每个簇的均值作为新的质心
centroids[i] = centroid # 更新质心矩阵
return centroids # 返回新的质心矩阵
# 获取每个样本所属聚类类别
def get_cluster_labels(clusters, X):
y_pred = np.zeros(X.shape[0]) # 样本数
for cluster_i, cluster in enumerate(clusters):
for sample_i in cluster:
y_pred[sample_i] = cluster_i
return y_pred # 预测结果
# 封装k-means算法
def kmeans(X, k, max_iterations):
centroids = centroids_init(X, k) # 训练样本,质心个数(聚类簇数)
# 迭代至收敛
for _ in range(max_iterations):
clusters = build_clusters(centroids, k, X) # 分配样本与构建簇
new_centroids = calculate_centroids(clusters, k, X) # 计算新的质心
print(f'迭代进行到第{
_}轮')
diff = centroids - new_centroids
centroids = new_centroids
if not diff.any():
break
return get_cluster_labels(clusters, X) # 获取每个样本所属聚类类别
from sklearn import datasets
# 测试算法
data = datasets.load_iris()
iris, y = data.data, data.target
label_pred = kmeans(iris, 3, 100)
# 取2个或者3个维度来看一下聚类的效果
X = iris[:,2:]
x0 = X[label_pred == 0]
x1 = X[label_pred == 1]
plt.scatter(x0[:, 0], x0[:, 1], c = "red", marker='o', label='label0')
plt.scatter(x1[:, 0], x1[:, 1], c = "green", marker='*', label='label1')
plt.xlabel('petal length')
plt.ylabel('petal width')
plt.legend(loc=2)
plt.show()
5 sklearn に基づく K 平均法アルゴリズム
from sklearn.cluster import KMeans
kmeans_sk = KMeans(n_clusters=3, random_state=2023).fit(iris)
label_pred = kmeans_sk.labels_ # 打印拟合标签
X = iris[:,2:]
x0 = X[label_pred == 0]
x1 = X[label_pred == 1]
plt.scatter(x0[:, 0], x0[:, 1], c = "red", marker='o', label='label0')
plt.scatter(x1[:, 0], x1[:, 1], c = "green", marker='*', label='label1')
plt.xlabel('petal length')
plt.ylabel('petal width')
plt.legend(loc=2)
plt.show()