机器学习之K-Means

本文介绍了K-Means算法,包括相似度/距离的计算方法,如闽可夫斯基距离、杰卡德相似系数和余弦相似度。接着详细解释了K-Means的基本思想和伪代码,并提供了Python实现。文章总结了在Python3环境下遇到的问题,如计算欧式距离和使用random.rand()的差异,以及数据类型和matplotlib画图的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

K-Means

先来看看相似度/距离的计算方法

闽可夫斯基距离(Minkowski)/欧式距离(p=2) :

dist(X,Y)=(i=1nxiyip)1p d i s t ( X , Y ) = ( ∑ i = 1 n | x i − y i | p ) 1 p

杰卡德相似系数(Jaccard):

J(a,b)=ABAB J ( a , b ) = A ∩ B A ∪ B

余弦相似度(cosine similarity )

cos(θ)=aTb|a||b| cos ⁡ ( θ ) = a T b | a | | b |

Pearson相似系数

ρXY=cov(X,Y))σxσY=E[(XμX)(YμY)]σxσY=ni=1(XμX)(XμY)ni=1(XμX)2ni=1(XμX)2 ρ X Y = c o v ( X , Y ) ) σ x σ Y = E [ ( X − μ X ) ( Y − μ Y ) ] σ x σ Y = ∑ i = 1 n ( X − μ X ) ( X − μ Y ) ∑ i = 1 n ( X − μ X ) 2 ∑ i = 1 n ( X − μ X ) 2

相对熵(K-L距离)

D(p||q)=xp(x)logp(x)q(x)=Ep(x)logp(x)q(x) D ( p | | q ) = ∑ x p ( x ) l o g p ( x ) q ( x ) = E p ( x ) l o g p ( x ) q ( x )


K-Means算法详解

K-Means算法,即k-均值算法,是一种广泛使用的聚类算法。


基本思想


对一个给定的含有N个对象的数据集,构造数据的k个簇, kN k ≤ N

首先给定k,给出初始划分,通过迭代改变样本和簇的隶属关系,使得每一次改进之后的划分方案都比前一次好。

伪代码

创建k个点作为起始质心(经常是随机选择)
当任意一个点的簇分配结果发生改变时
    对数据集中的每个数据点
        对每个质心
            计算质心与数据点之间的距离
        将数据点分配到距离最近的簇
    对每一个簇,计算簇中所有点的均值作为质心

python代码实现
数据与代码来源于:《机器学习实战》

from numpy import *
import random
from matplotlib import pyplot as plt

def loadData(fileName):
    data = []
    with open(fileName) as fr:
        for line in fr.readlines():
            lines = line.strip().split('\t')
            L = list(map(float, lines)) #注意与书中的不同
            data.append(L)

    return mat(data)


# 欧式距离计算
def distEclud(vecA,vecB):
    return sqrt(sum(square(vecA-vecB)))

# 构建随机质心
def randCent(data,k):
    m,n = shape(data)
    centroids = mat(zeros((k,n)))
    for i in range(k):
        for j in range(n):
            minJ = min(data[:, j])  # 找出每列中最小的值
            rangeJ = float(max(data[:, j]) - minJ)  # 找出每一列的范围值
            centroids[(i,j)] = mat(minJ + rangeJ * random.random())
    return centroids

def k_Means(data,k):
    m,n = shape(data) # 每一行为一个simple,共有n个样本
    # 初始化一个矩阵来存储每个点的簇分配结果 #
    # 一列记录簇索引值,第二列存储误差(误差是指当前点到簇质心的距离,后面会使用该误差来评价聚类的效果)
    clusterAssemt = mat(zeros((m,2)))
    centroids = randCent(data,k)
    clusterChanged = True
    while clusterChanged:
        clusterChanged = False
        for i in range(m):
            minDist = inf
            minIndex = 0

            for j in range(k):
                distJI = distEclud(centroids[j,:],data[i,:]) #采用欧式距离
                if distJI < minDist:
                    minDist = distJI
                    minIndex = j
                    # 找到每个样本最近距离的质点

            if clusterAssemt[i,0] != minIndex:
                clusterChanged = True

            clusterAssemt[i,:] = minIndex, minDist **2
        for cent in range(k):
            ptsInClust = data[nonzero(clusterAssemt[:,0].A == cent)[0]]
            centroids[cent,:] = mean(ptsInClust,axis=0)
    return centroids,clusterAssemt


if __name__ == '__main__':
    # data = loadData('testSet.txt')
    data = loadData('testSet2.txt')
    fig = plt.figure()
    p1 = plt.scatter(data[:, 0].flatten().A[0], data[:, 1].flatten().A[0], marker='o')

    myCentroids, clustAssing = k_Means(data,3)

    print(myCentroids)
    print(clustAssing)
    p2 = plt.scatter(myCentroids[:,0].flatten().A[0],myCentroids[:,1].flatten().A[0], marker='x', edgecolors='r')
    plt.show()

上述代码运行后,得到的图如下:

错误聚类的figure

正确聚类的figure

K-Means算法实现总结:

1、python版本的差异
我使用的是python3.x,书中的代码是python2

2、计算欧式距离时,无法使用pow(x,2)函数,报错为数据维数不符合。而改用直接用是sqart()
具体原因:未知。欢迎拍砖!

3、random.rand(k,1)这个也是无法使用。报错为:
random中无rand模块。我dir了一下,python3中确实没有。不知道是不是2和3的差异。要想在3中使用,只能用numpy模块中的rand模块了。
因此我相应的把代码改了。

4、使用数据预测时,出现了数据类型不符合的情况~
什么list、matrix等混乱~这个得我一条条代码调试,更改相应的数据类型~ 吐血!希望以后加强这个方面的训练,能尽量少报这方面的错误!

5、使用matplotlib画图时,总算明白了flatten()的奥妙之处~散点画图能力加强了~

二分K-Means 算法后面在总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值