# k均值

这个算法比较简单，基本步骤为：

> 输入：聚类个数K，如K=3
>
> 输出：K个聚类簇中点
>
> 1）初始化3个聚类集合，里面随便放一个初始样本点作为C1、C2、C3簇的中心
>
> 2）循环 直到数据集中样本被标记、归类完
>
> > 迭代每个样本xi，xi与类集合C1、C2、C3各自的中心计算距离，然后被划分到距离最近的簇类Cj中
> >
> > 划分后，标记这个样本，同时更新这个Cj簇的中心（集合样本均值）
>
> 3）结束循环：此时所有样本被归类到C1、C2、C3中某个簇中
>
> 4）继续执行1-3步骤，不过，1步中随机的3个点作为中心，换成上一轮学到的簇集合均值作为中心

![img](https://img-blog.csdnimg.cn/20190226235425737.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppYW5nNDI1Nzc2MDI0,size_16,color_FFFFFF,t_70)

k均值仅在凸形簇结构上表现较好、结果受初始点影响

## elkan K-Means

> ​ 利用了两边之和大于等于第三边,以及两边之差小于第三边的三角形性质，来减少KMeans的距离的计算。

## K-Means++

> ​ 把原来初始时随机的选k个点作为初始簇中心做了优化。先随机取一个点作为簇中心，此时只有一个簇，然后计算所有点与簇中心点的距离，距离越大的概率越大，这个概率用来选择第二个簇的中心点，此时有两个簇；然后计算所有点与两个簇中心的距离，取2个距离中小的那个作为样本的计算距离，样本的计算距离越大的概率越大，用于选第3个簇中心，得到3个簇；然后计算所有样本点与3个簇中心的距离，取3个距离中小的那个作为样本的计算距离，......直到得到k个簇中心，作为原始kmeans的随机初始化的替换。

## Mini Batch K-Means

> ​ 在统的K-Means算法中，要计算所有的样本点到所有的质心的距离。如果样本量非常大，比如达到10万以上，特征有100以上，此时用传统的K-Means算法非常的耗时；Mini Batch，用样本集中的一部分的样本来做传统的K-Means，这样可以避免样本量太大时的计算难题，算法收敛速度大大加快。当然此时的代价就是我们的聚类的精确度也会有一些降低。一般来说这个降低的幅度在可以接受的范围之内。
>
> ​ Mini Batch K-Means中，我们会选择一个合适的批样本大小batch size，来做K-Means聚类。一般是通过无放回的随机采样得到的。

## scikit-learn中

包括两个K-Means的算法：**传统的KMeans、基于采样的MiniBatchKMeans**。

**KMeans**：

> KMeans类的主要参数有： 1) n\_clusters: 即我们的聚类数量k。 2）max\_iter： 最大的迭代次数。 3）n\_init：用不同的质心初始化算法的次数。由于K-Means是结果受初始值影响的局部最优的迭代算法，因此需要多跑几次，默认是10。如果k值较大，可适当增大。 4）init： 即初始值选择的方式，完全随机选择'random',优化过的'k-means++'或者自己指定初始化的k个质心。一般建议使用默认的'k-means++'。 5）algorithm：有“auto”, “full” or “elkan”三种选择。"full"是传统的K-Means算法， “elkan”是elkan K-Means算法。默认的"auto"会根据数据值是否是稀疏的，来决定如何选择"full"和“elkan”。一般数据是稠密的，那么就是 “elkan”，否则就是"full"。一般来说建议直接用默认的"auto"

```python
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets.samples_generator import make_blobs
from sklearn.cluster import KMeans
from sklearn import metrics

# X为样本特征，Y为样本簇类别， 共1000个样本，每个样本5个特征，共4个簇（类），
# 簇中心在[-1,-1], [0,0],[1,1], [2,2]， 簇方差分别为[0.4, 0.2, 0.2,0.2]
X, y = make_blobs(n_samples=1000, n_features=2, centers=[[-1, -1], [0, 0], [1, 1], [2, 2]],
                  cluster_std=[0.4, 0.2, 0.2, 0.2],
                  random_state=9)
plt.scatter(X[:, 0], X[:, 1], marker='o')

y_pred = KMeans(n_clusters=4, random_state=9).fit_predict(X)

print('silhouette_score轮廓系数:', metrics.silhouette_score(X, y_pred))
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

#silhouette_score轮廓系数: 0.6634549555891298
```

![](/files/-LqBk1bI4wWXAyT9PBke)

**基于采样的MiniBatchKMeans**

> MiniBatchKMeans类主要参数 MiniBatchKMeans类的主要参数比KMeans类稍多，主要有： 1) n\_clusters:一样。 2）max\_iter：一样。 3）n\_init：用不同的初始化质心运行算法的次数，和KMeans类意义稍有不同的是，MiniBatchKMeans每次用不同的采样数据集来跑不同的初始化质心运行算法。 4）batch\_size：算法采样集的大小，默认是100.如果数据集的类别较多或者噪音点较多，需要增加这个值。 5）init： 一样。 6）init\_size: 做质心初始值候选的样本个数，默认是batch\_size的3倍，一般用默认值就可以了。 7）reassignment\_ratio: 某个类别质心被重新赋值的最大次数比例，这个和max\_iter一样是为了控制算法运行时间的。这个比例是占样本总数的比例，乘以样本总数就得到了每个类别质心可以重新赋值的次数。如果取值较高的话算法收敛时间可能会增加，尤其是那些暂时拥有样本数较少的质心。默认是0.01。如果数据量不是超大的话，比如1w以下，建议使用默认值。如果数据量超过1w，类别又比较多，可能需要适当减少这个比例值。具体要根据训练集来决定。 8）max\_no\_improvement：即连续多少个Mini Batch没有改善聚类效果的话，就停止算法， 和reassignment\_ratio， max\_iter一样是为了控制算法运行时间的。默认是10.一般用默认值就足够了。

```python
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets.samples_generator import make_blobs
from sklearn.cluster import MiniBatchKMeans
from sklearn import metrics

# X为样本特征，Y为样本簇类别， 共1000个样本，每个样本5个特征，共4个簇（类），
# 簇中心在[-1,-1], [0,0],[1,1], [2,2]， 簇方差分别为[0.4, 0.2, 0.2,0.2]
X, y = make_blobs(n_samples=1000, n_features=2, centers=[[-1, -1], [0, 0], [1, 1], [2, 2]],
                  cluster_std=[0.4, 0.2, 0.2, 0.2],
                  random_state=9)
plt.scatter(X[:, 0], X[:, 1], marker='o')

y_pred = MiniBatchKMeans(n_clusters=4, batch_size=200, random_state=9).fit_predict(X)
print('Calinski-Harabasz分数:', metrics.calinski_harabaz_score(X, y_pred))
print('silhouette_score轮廓系数:', metrics.silhouette_score(X, y_pred))
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

#
Calinski-Harabasz分数: 2827.388413921534
silhouette_score轮廓系数: 0.5349102143157655
```

![img](/files/-LqBk1bKF5Zi3imeTWKQ)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://im-qianuxn.gitbook.io/pytorch/ji-suan-ji/ml/cluster/kmean.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
