K平均クラスタリング - 単純なコードの実装、EMアルゴリズムに関連付けられました

アルゴリズムの実装手順

思考K-手段:

(1)ランダムにk個のクラスタのクラスタ中心を選択する
(2)試料のクラスクラスタとして最小距離を選択することにより、全てのクラスタに各サンプル点の距離を算出する
(3)までは、中心がすべてのクラスクラスタの座標を再計算します特定の停止条件(反復/クラスタ中心の数/最小二乗誤差を収束)


EMアルゴリズムのアイデア:

(1)私たちは不明である両方の初期状態では、推定2つのパラメータAとBを知りたいと仮定し、
(2)情報が、あなたが知っていればAさんは、今度はBを知っている情報Bを、取得することができます得た;
(3)B、次いで、Bの値の推定値を得るために、いくつかの初期値を与える最初に、電流値の再推定値から開始し、このプロセスは収束するまで継続します。


どちらの団体:

ステップ2は、EMが実際に繰り返し、2つのパラメータは開始のために知られていない、反射された後、初期の確率変数を選択し、オブジェクトの後に得られた結果は、その後全体のターンを計算され、kは、意味、上方から見ることができますこれらの2つのステップは、あなたが最良の結果を得るまで。

一般的な考え方は、目的関数があり、反復最適化プロセスであるが、可変パラメータは、隠れ変数は暗黙的変数を推定し、その後、目的関数が最適化されるまで、他のパラメータを推定するために暗黙変数を決定するために、他のパラメータを決定するだけよりもkは、意味します。


コードの実装:

計算ステップ:
2すべてのサンプル点を通過した後、サンプル点に割り当てられたクラスタ番号の重心最小距離、見つける、私重心各サンプル点までの距離を算出し、各サンプルポイントを通過する:1.以下の反復を行います。各クラスタの重心を再計算。すべての割り当てられたクラスタのサンプル点までもはや変更反復は停止されない。
3.最後に、クラスタの分布マトリックスとサンプル点の重心に戻ります。

import numpy as np
import math
import matplotlib.pyplot as plt

#1.加载数据
def loadDataSet(fileName, splitChar='\t'):
    dataSet = []
    with open(fileName) as fr:
        for line in fr.readlines():
            curline = line.strip().split(splitChar)
            fltline = list(map(float, curline))
            dataSet.append(fltline)
    return np.array(dataSet)


#2.计算欧氏距离:两个向量每个元素差的平方,求和后再开方
def dist_eclud(vecA, vecB):
    vec_square = []
    for element in vecA - vecB:   #元素想减
        element = element ** 2    #求平方
        vec_square.append(element)   #放入list
    return sum(vec_square) ** 0.5    #list求和后,再开方


# 3.构建k个随机质心
def rand_cent(data_set, k):
    n = data_set.shape[1]    
    centroids = np.zeros((k, n))   #构造质心的shape
    #限定质心在数据集范围之内
    for j in range(n):
        min_j = float(min(data_set[:,j]))    #数据集中的最小值
        range_j = float(max(data_set[:,j])) - min_j     #
        centroids[:,j] = (min_j + range_j * np.random.rand(k, 1))[:,0]
    return centroids


#4.算法的主函数
def Kmeans(data_set, k):    
    m = data_set.shape[0]
    cluster_assment = np.zeros((m, 2))     
    centroids = rand_cent(data_set, k)     #获取k个随机质心
    cluster_changed = True

    while cluster_changed:       
        cluster_changed = False
         #遍历m个原始数据
        for i in range(m):        
            min_dist = np.inf; min_index = -1
            #遍历k个质心  
            for j in range(k):
                #计算m个原始数据与每一个质心的距离
                dist_ji = dist_eclud(centroids[j,:], data_set[i,:])
                #找到最小距离,将该质心所在簇编号分配给该样本点
                if dist_ji < min_dist:              
                    min_dist = dist_ji
                    min_index = j   

            #重新计算每个簇的质心。直到所有样本点的簇分配都不再发生变化时迭代停止。
            if cluster_assment[i,0] != min_index:    
                cluster_changed = True      
            cluster_assment[i,:] = min_index, min_dist**2
            
        #返回质心和样本点的簇分配矩阵
        for cent in range(k):   
            pts_inclust = data_set[np.nonzero(list(map(lambda x:x==cent, cluster_assment[:,0])))]
            centroids[cent,:] = np.mean(pts_inclust, axis=0)

    return centroids, cluster_assment            


#加载数据
data_set = loadDataSet('img/1.txt', splitChar=',')
#计算出最终的质心
my_centroids, my_cluster_assment = Kmeans(data_set, 4)
print("最终4个质心为:")
print(my_centroids)

#原始数据的坐标点
point_x = data_set[:,0]
point_y = data_set[:,1]
#最终质心的坐标点 
cent_x = my_centroids[:,0]
cent_y = my_centroids[:,1]
#画图
fig, ax = plt.subplots(figsize=(10,5))
#画原始数据点,形状为圆圈
ax.scatter(point_x, point_y, s=30, c="r", marker="o", label="sample point")
#画最终数据点,形状为倒三角
ax.scatter(cent_x, cent_y, s=100, c="black", marker="v", label="centroids")
#在右上角显示小图标
ax.legend()
ax.set_xlabel("factor1")   #横轴名称
ax.set_ylabel("factor2")   #纵轴名称
plt.show()


結果は以下の通りである:
あなたが新しい4つの重心を取得します
ここに画像を挿入説明


生データとマップ上に描かれ、最終的な重心:
ここに画像を挿入説明

クラスタを達成するために、実質的にデータ点の分布の中央で、各グループの重心の位置を見ることができます。

参考リンク:https://blog.csdn.net/weixin_41090915/article/details/79389636

おすすめ

転載: blog.csdn.net/gm_Ergou/article/details/92074152