引言

kmeans 是一个简单实用的机器学习算法,今天专门介绍一下。这篇文章主要关注以下几点:

kmeans 算法的具体流程是啥?做一个代码实战,并用可视化的方法来展示kmeans的聚类效果。训练过程中如何选取最好的聚类结果?训练好后如何评价训练的的结果。

k-means算法流程

k-means算法的步骤:

随机选取k个初始中心点。计算每个样本点和中心点的距离,各自划分为距离最近的中心点所对应的类别中。重新确定中心点: 每个类别中的点的均值作为新的中心点。重复步骤2,3 直到某个条件终止(一定的次数或者是每个簇中的点不在改变)

k-means算法存在的问题:

计算量和样本数量成正比初始值对聚类结果影响很大不同的初始值可能会有不同的聚类结果。对不规则的数据效果不好。分成的簇的数量需要人工确认。对初始值的稳定性非常差。

kmeans 算法实战

生成数据

我们可以先自己手工构造一个一个的簇,作为聚类的数据集。 这里讲一下生成数据的方法。 要点如下:

指定若干个二维的点作为质心。指定每个质心周围的点的个数以及离散程度,用标准差数值来表示。绘制散点图。 具体的代码如下:

import numpy as np

import os

%matplotlib inline

import matplotlib

import matplotlib.pyplot as plt

from sklearn.datasets import make_blobs

# 这是中心点

blob_centers = np.array(

[

[2.2,2.3],

[-1.5, 2.3],

[-2.8, 1.8],

[-2.8, 2.8],

[-2.8, 1.3]

]

)

# 这是离散程度, 越大则越离散。

blob_std = np.array([1, 0.3, 0.1, 0.1, 0.1])

X,y = make_blobs(n_samples=5000, centers = blob_centers, cluster_std = blob_std, random_state=7)

print(X, y)

这里有个小思考: 例子中基本都是使用的二维点来进行展示的, 如果是多维的数据,如果可以图形化展示聚类算法的效果呢?

聚类算法进行聚类

# kmeans算法

from sklearn.cluster import KMeans

# 需要人为指定簇的个数

k = 5

# random_stat 指定可以保证出来的结果都是一样的

kmeans = KMeans(n_clusters = k, random_state=42)

# 输入的X是一个二维的数组,每个元素都是一个点。

y_pred= kmeans.fit_predict(X)

# 得到的是每个点的簇的标签

print(y_pred)

print(kmeans.labels_)

# 可以得出簇的中心点

kmeans.cluster_centers_

可视化展示-画等高线

等高线可以看出每个簇所处的区域是啥,具体的函数代码如下:

def plot_data(X):

plt.plot(X[:, 0], X[:, 1], 'k.', markersize=2)

# 画中心点

def plot_centroids(centroids, weights=None, circle_color='w', cross_color='k'):

if weights is not None:

centroids = cnetroids[weights > weights.max() / 10]

plt.scatter(centroids[:, 0], centroids[:, 1], marker= 'o', s = 30, linewidths=8, color=circle_color, zorder=10, alpha=0.9)

plt.scatter(centroids[:, 0], centroids[:, 1],

marker='x', s=50, linewidths=1,

color=cross_color, zorder=11, alpha=1)

def plot_decision_boundaries(clusterer, X, resolution=1000, show_centroids=True, show_xlabels=True, show_ylabels=True):

# 这个是为了可以显示所有的点

mins = X.min(axis=0)

maxs = X.max(axis=0)

print(mins)

print(maxs)

# 下面画一个网格

xx, yy = np.meshgrid(np.linspace(mins[0], maxs[0], resolution),

np.linspace(mins[1], maxs[1], resolution)

)

# 这个ravel函数可以把二维数组拍平

Z = clusterer.predict(np.c_[xx.ravel(), yy.ravel()])

print(Z)

Z = Z.reshape(xx.shape)

plt.contourf(Z, extent=(mins[0], maxs[0], mins[1], maxs[1]), cmap="Pastel2")

plt.contour(Z, extent=(mins[0], maxs[0], mins[1], maxs[1]), linewidths=1, colors='k')

plot_data(X)

if show_centroids:

plot_centroids(clusterer.cluster_centers_)

if show_xlabels:

plt.xlabel("$x_1$", fontsize=14)

else:

plt.tick_params(labelbottom='off')

if show_ylabels:

plt.ylabel("$x_2$", fontsize=14, rotation=0)

else:

plt.tick_params(labelleft='off')

plt.figure(figsize=(8,4))

plot_decision_boundaries(kmeans, X)

也可以写一个画图函数,将不同簇的点用不同的颜色表示出来。代码如下:

def plot_color(clusterer, X):

# 预测一下聚类效果

y = clusterer.fit_predict(X)

# 这里的c 表示颜色序列

plt.scatter(X[:, 0], X[:, 1], c=y,s=2, cmap=plt.cm.Spectral)

plot_color(kmeans, X)

kmeans聚类算法使用技巧

我们知道, kmeans聚类算法的结果,会受到初始值中心点的影响,我们怎么保证最后聚类出来的结果是比较合适的呢? kmeans算法里有几个参数, 需要注意一下。

n_init, 例如这个值设定为10的话,会把模型跑10次,最后选取跑的最好的那一次,那么, 如何确定哪个值好呢,先留个疑问。max_iter: 迭代次数, 这里设置最大的迭代次数。

kmeans聚类算法的评估方法

机器学习库中, 有个inertia_属性, 这个就是每个样本与对应质心的距离的平方和的累加值。当设定n_init参数的时候, 会选取多次聚类, inertia_值最小的聚类结果。

如何寻找最合适的k值

首先,选择最小inertia值对应的k值不可靠,原因是,随着k的增加, 聚类的簇就会越来越多, 数据点到质心的距离也会很小, 最后的inertia的值也会变得非常小, 但是聚类效果并不是越来越好的。 推荐方案一:画一个图,表示出k值与对应的inertia值的对应关系曲线,在曲线的下降率发生剧烈变化的时候对应的k值,可以认为是比较合适的k值,不过, 这个点只能作为参考,有可能不是最优的选择。 推荐方案二:使用轮廓系数来选取k值。 定义两个概念:

a

i

a_i

ai​: 计算样本i到同簇其他样本的平均距离

a

i

a_i

ai​, 这个值越小, 说明越是应该被聚类到这个簇。

b

i

b_i

bi​: 计算样本i 到其他簇的所有样本的平均距离, 然后取一个最小值就是

b

i

b_i

bi​,

b

i

b_i

bi​越大越好。

s

(

i

)

=

b

(

i

)

a

(

i

)

m

a

x

(

a

(

i

)

,

b

(

i

)

)

s(i)=\frac{b(i)-a(i)}{max(a(i),b(i))}

s(i)=max(a(i),b(i))b(i)−a(i)​

我们可以计算所有

s

(

i

)

s(i)

s(i)的均值,作为评价指标。 sklearn机器学习库中有一个专门计算函数。具体使用如下:

# kmeans_per_k表示聚类实例的列表。

# 注意实例取值要从1开始, 否则会出错的。

silhouette_scores = [silhouette_score(X,model.labels_) for model in kmeans_per_k[1:]]

#绘制图表

plt.figure(figsize=(8,4))

plt.plot(range(2,10),silhouette_scores,'bo-')

plt.show()

这个指标也只能是作为一个参考,最合适的k值还是需要根据自己的需求来决定的。

总结

kmeans 是一个简单实用的算法, 不过缺点也是比较明显的, 对于形状不规则的点状图,kmeans 的聚类算法效果可能会不好,而且对于kmeans 的模型评估比较难, 不容易找到合适的k值。

好文推荐

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: