k-means、DBSCAN聚类算法代码

k-means聚类算法

优点

容易实现。
适用于高维。

缺点

对离群点敏感,对噪声点和孤立点很敏感。
不适用于非凸的簇或大小差别很大的簇。
需要自定义k,不同的初始点可能得到的结果完全不同。
可能收敛到局部最小值,在大规模数据集上收敛较慢。

适用数据类型

数值型数据。

伪代码

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

k-means代码

from numpy import *

def loadDataSet(fileName):  # 将文本文件导入到列表
    dataMat = []
    fr = open(fileName)
    for line in fr.readlines():
        curLine = line.strip().split('\t')
        fltLine = list(map(float, curLine))  # 需要在此处将map结果转化为列表
        dataMat.append(fltLine)
    return dataMat

def distEclud(vecA, vecB):  # 计算两个向量的欧式距离
    return sqrt(sum(power(vecA - vecB, 2)))

def randCent(dataSet, k):  # 为给定的数据集构建一个包含k个质心的集合
    n = shape(dataSet)[1]
    centroids = mat(zeros((k, n)))
    for j in range(n):  # 随机质心必须要在整个数据集的边界之内
        minJ = min(dataSet[:, j])  # 可以通过找到数据集每一维德最小和最大值来完成
        rangeJ = float(max(dataSet[:, j]) - minJ)
        centroids[:, j] = minJ + rangeJ * random.rand(k, 1)
    return centroids

def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
    m = shape(dataSet)[0]  # 样本数
    clusterAssment = mat(zeros((m, 2)))  # 创建一个矩阵,存储每个点的簇分配结果(一列记录簇索引值,另一列存储误差)
    centroids = createCent(dataSet, k)  # 初始化k个质心
    clusterChanged = True
    while clusterChanged:
        clusterChanged = False
        for i in range(m):  # 遍历每一个样本
            minDist = inf
            minIndex = -1
            for j in range(k):  # 对当前样本找到离其最近的质心
                distJI = distMeas(centroids[j, :], dataSet[i, :])
                if distJI < minDist:
                    minDist = distJI
                    minIndex = j
            if clusterAssment[i, 0] != minIndex:  # 簇分配仍在进行
                clusterChanged = True
            clusterAssment[i, :] = minIndex, minDist ** 2
        print(centroids)
        for cent in range(k):  # 更新质心的位置
            ptsInClust = dataSet[nonzero(clusterAssment[:, 0].A==cent)[0]]  # 每个簇中样本的值
            centroids[cent, :] = mean(ptsInClust, axis=0)  # 求每个簇的均值
    return centroids, clusterAssment

dataMat = mat(loadDataSet('testSet.txt'))  # 将文本文件导入到列表,再将列表转换为矩阵
myCentroids, clusterAssing = kMeans(dataMat, 4)
结果:经过3次迭代,算法就已经收敛。

k-means、DBSCAN聚类算法代码_第1张图片
最终分簇结果如图所示:
k-means、DBSCAN聚类算法代码_第2张图片

聚类度量指标SSE

SSE(Sum of Squared Error,误差平方和)。SSE越小表示数据点越接近它们的质心,聚类效果也就越好。因为对误差取了平方,因此更加重视那些远离中心的点。

k-均值很容易会收敛到局部最小值,而二分k-均值算法能在相似的思想上达到更好的聚类效果。

二分k-均值算法

为克服K-均值算法收敛于局部最小值的问题,有人提出了二分k-均值的算法。该算法首先将所有点作为一个簇,然后将该簇一分为二。之后选择其中一个簇继续进行划分,选择哪一个簇取决于对其划分是否可以最大程度降低SSE的值。上述基于SSE的划分过程不断重复,知道得到用户指定的簇数目为止。

二分k-均值算法伪代码

将所有点看成一个簇
当簇数目小于k时
	对于每一个簇
		计算总误差
		在给定的簇上面进行k-均值聚类(k=2)
		计算将该簇一分为二之后的总误差
	选择是的误差最小的那个簇进行划分操作

代码参考链接:https://www.cnblogs.com/multhree/p/11279140.html

k-means与DBSCAN效果对比

k-means

k-means、DBSCAN聚类算法代码_第3张图片

k-means、DBSCAN聚类算法代码_第4张图片

DBSCAN

k-means、DBSCAN聚类算法代码_第5张图片

k-means

k-means、DBSCAN聚类算法代码_第6张图片
k-means、DBSCAN聚类算法代码_第7张图片

DBSCAN

k-means、DBSCAN聚类算法代码_第8张图片

K-Means++、Mini Bacth K-Means

因为K-Means算法对初次选取的类别中心敏感,不同的随机种子点得到的聚类结果会有不同。K-Means++算法便是在K-Means的基础上解决了这个问题,并不是一开始就把所有初始点找到,而是一个个地找初始点。这样达到的效果就是:初始的聚类中心之间的相互距离会比较远

Mini Bacth K-Means算法:使用分批处理(Mini Bacth)的方法对数据点之间的距离进行计算。当样本点较多时,直接使用K-Means算法进行聚类的话,效率会比较慢,每一轮都有遍历计算所有的样本点到各个聚类中心的距离。

Mini Bacth K-Means的好处在于:不必使用所有的样本点进行距离计算、而是每次使用一个batch的样本点来进行K-means算法,进行计算到各个聚类中心的距离,从而得到新的聚类中心。batch_size的大小需自定义。
由于计算样本量的减少,相应的运行时间也会减少,但会带来准确度的降低

算法比较

from sklearn.cluster import KMeans, MiniBatchKMeans

centers = [[1, 0], [-1, 0], [0, -1], [0, 1], [0, 0], [-0.7, -0.7], [-0.7, 0.7], [0.7, -0.7], [0.7, 0.7]]
X, y_true = make_blobs(n_samples=100000, centers=centers, cluster_std=0.18, random_state=0)
fig, axes = plt.subplots(2, 2)
axes[0, 0].scatter(X[:, 0], X[:, 1], c=y_true)
axes[0, 0].set_xlabel('y_true')

t0 = time.time()
y_pred1 = KMeans(init='random', n_clusters=9, random_state=666, n_init=1).fit_predict(X)
t_k_means = time.time() - t0
axes[0, 1].scatter(X[:, 0], X[:, 1], c=y_pred1)
axes[0, 1].set_xlabel('k-means time:%f'%t_k_means)

y_pred2 = KMeans(init='k-means++', n_clusters=9, random_state=666, n_init=1).fit_predict(X)
axes[1, 0].scatter(X[:, 0], X[:, 1], c=y_pred2)
axes[1, 0].set_xlabel('k-means++')

t0 = time.time()
y_pred3 = MiniBatchKMeans(init='random', n_clusters=9, batch_size=900, n_init=1, max_no_improvement=10).fit_predict(X)
t_batch_means = time.time() - t0
axes[1, 1].scatter(X[:, 0], X[:, 1], c=y_pred3)
axes[1, 1].set_xlabel('batch-k-means time:%f'%t_batch_means)

plt.subplots_adjust(left=0.2, bottom=0.2, right=0.8, top=0.8, hspace=0.9, wspace=0.9)
plt.show()

结果如图所示:
k-means、DBSCAN聚类算法代码_第9张图片

层次聚类与DBSCAN

代码参考:https://blog.csdn.net/sinat_18665801/article/details/90637272

你可能感兴趣的:(机器学习,聚类,k-means算法,DBSCAN算法)