Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions docs/10.k-means聚类.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ K-Means 是发现给定数据集的 K 个簇的聚类算法, 之所以称之为

### K-Means 术语

* 簇: 簇中的对象是相似的.
* 簇: 所有数据点点集合,簇中的对象是相似的
* 质心: 簇中所有点的中心(计算所有点的均值而来).
* SSE: Sum of Sqared Error(平方误差和), SSE 值越小,表示越接近它们的质心. 由于对误差取了平方,因此更加注重那么远离中心的点.

Expand All @@ -29,7 +29,7 @@ K-Means 是发现给定数据集的 K 个簇的聚类算法, 之所以称之为
![K-Means 术语图](../images/10.KMeans/apachecn-k-means-term-1.jpg)

### K-Means 工作流程
1. 首先, 随机确定 K 个初始点作为质心.
1. 首先, 随机确定 K 个初始点作为质心(不是数据中的点).
2. 然后将数据集中的每个点分配到一个簇中, 具体来讲, 就是为每个点找到距其最近的质心, 并将其分配该质心所对应的簇. 这一步完成之后, 每个簇的质心更新为该簇说有点的平均值.

上述过程的 `伪代码` 如下:
Expand Down Expand Up @@ -96,7 +96,7 @@ def randCent(dataSet, k):
```python
# k-means 聚类算法
# 该算法会创建k个质心,然后将每个点分配到最近的质心,再重新计算质心。
# 这个过程重复数次,知道数据点的簇分配结果不再改变位置
# 这个过程重复数次,直到数据点的簇分配结果不再改变位置
# 运行结果(多次运行结果可能会不一样,可以试试,原因为随机质心的影响,但总的结果是对的, 因为数据足够相似,也可能会陷入局部最小值)
def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
m = shape(dataSet)[0] # 行数
Expand Down Expand Up @@ -132,10 +132,10 @@ def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):

### K-Means 聚类算法的缺陷
在 kMeans 的函数测试中,可能偶尔会陷入局部最小值(局部最优的结果,但不是全局最优的结果).
所以为了客户 KMeans 算法收敛于局部最小值的问题,有更厉害的大佬提出了另一个称为二分K-均值(bisecting K-Means)的算法.
所以为了克服 KMeans 算法收敛于局部最小值的问题,有更厉害的大佬提出了另一个称为二分K-均值(bisecting K-Means)的算法.

### 二分 K-Means 聚类算法
该算法首先将说有点作为一个簇,然后将该簇一分为二。
该算法首先将所有点作为一个簇,然后将该簇一分为二。
之后选择其中一个簇继续进行划分,选择哪一个簇进行划分取决于对其划分时候可以最大程度降低 SSE(平方和误差)的值。
上述基于 SSE 的划分过程不断重复,直到得到用户指定的簇数目为止。

Expand Down Expand Up @@ -170,7 +170,7 @@ def biKMeans(dataSet, k, distMeas=distEclud):
sseSplit = sum(splitClustAss[:,1]) # 将二分 kMeans 结果中的平方和的距离进行求和
sseNotSplit = sum(clusterAssment[nonzero(clusterAssment[:,0].A!=i)[0],1]) # 将未参与二分 kMeans 分配结果中的平方和的距离进行求和
print "sseSplit, and notSplit: ",sseSplit,sseNotSplit
if (sseSplit + sseNotSplit) < lowestSSE:
if (sseSplit + sseNotSplit) < lowestSSE: # 总的(未拆分和已拆分)误差和越小,越相似,效果越优化,划分的结果更好(注意:这里的理解很重要,不明白的地方可以和我们一起讨论)
bestCentToSplit = i
bestNewCents = centroidMat
bestClustAss = splitClustAss.copy()
Expand Down