diff --git a/docs/10.k-means聚类.md b/docs/10.k-means聚类.md index 2cd50d0b..100b2fa6 100644 --- a/docs/10.k-means聚类.md +++ b/docs/10.k-means聚类.md @@ -20,7 +20,7 @@ K-Means 是发现给定数据集的 K 个簇的聚类算法, 之所以称之为 ### K-Means 术语 -* 簇: 簇中的对象是相似的. +* 簇: 所有数据点点集合,簇中的对象是相似的。 * 质心: 簇中所有点的中心(计算所有点的均值而来). * SSE: Sum of Sqared Error(平方误差和), SSE 值越小,表示越接近它们的质心. 由于对误差取了平方,因此更加注重那么远离中心的点. @@ -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. 然后将数据集中的每个点分配到一个簇中, 具体来讲, 就是为每个点找到距其最近的质心, 并将其分配该质心所对应的簇. 这一步完成之后, 每个簇的质心更新为该簇说有点的平均值. 上述过程的 `伪代码` 如下: @@ -96,7 +96,7 @@ def randCent(dataSet, k): ```python # k-means 聚类算法 # 该算法会创建k个质心,然后将每个点分配到最近的质心,再重新计算质心。 -# 这个过程重复数次,知道数据点的簇分配结果不再改变位置。 +# 这个过程重复数次,直到数据点的簇分配结果不再改变位置。 # 运行结果(多次运行结果可能会不一样,可以试试,原因为随机质心的影响,但总的结果是对的, 因为数据足够相似,也可能会陷入局部最小值) def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent): m = shape(dataSet)[0] # 行数 @@ -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 的划分过程不断重复,直到得到用户指定的簇数目为止。 @@ -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()