Skip to content

Commit 5167652

Browse files
committed
K-Means
1 parent 3705ccc commit 5167652

File tree

8 files changed

+135
-2
lines changed

8 files changed

+135
-2
lines changed

formula/K-Means.wmf

7.53 KB
Binary file not shown.

images/K-Means_01.png

21.3 KB
Loading

images/K-Means_02.png

23.3 KB
Loading

images/K-Means_03.png

27.1 KB
Loading

images/K-Means_04.png

15.8 KB
Loading

images/K-Means_05.png

29.9 KB
Loading

images/K-Means_06.png

157 KB
Loading

readme.md

Lines changed: 135 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -736,9 +736,136 @@ def predict(Theta1,Theta2,X):
736736

737737
## 五、K-Means聚类算法
738738
- [全部代码](/K-Means/K-Menas.py)
739-
### 1、
740739

740+
### 1、聚类过程
741+
- 聚类属于无监督学习,不知道y的标记分为K类
742+
- K-Means算法分为两个步骤
743+
- 第一步:簇分配,随机选`K`个点作为中心,计算到这`K`个点的距离,分为`K`个簇
744+
- 第二步:移动聚类中心:重新计算每个****的中心,移动中心,重复以上步骤。
745+
- 如下图所示:
746+
- 随机分配的聚类中心
747+
![enter description here][34]
748+
- 重新计算聚类中心,移动一次
749+
![enter description here][35]
750+
- 最后`10`步之后的聚类中心
751+
![enter description here][36]
752+
- 计算每条数据到哪个中心最近实现代码:
753+
```
754+
# 找到每条数据距离哪个类中心最近
755+
def findClosestCentroids(X,initial_centroids):
756+
m = X.shape[0] # 数据条数
757+
K = initial_centroids.shape[0] # 类的总数
758+
dis = np.zeros((m,K)) # 存储计算每个点分别到K个类的距离
759+
idx = np.zeros((m,1)) # 要返回的每条数据属于哪个类
760+
761+
'''计算每个点到每个类中心的距离'''
762+
for i in range(m):
763+
for j in range(K):
764+
dis[i,j] = np.dot((X[i,:]-initial_centroids[j,:]).reshape(1,-1),(X[i,:]-initial_centroids[j,:]).reshape(-1,1))
765+
766+
'''返回dis每一行的最小值对应的列号,即为对应的类别
767+
- np.min(dis, axis=1)返回每一行的最小值
768+
- np.where(dis == np.min(dis, axis=1).reshape(-1,1)) 返回对应最小值的坐标
769+
- 注意:可能最小值对应的坐标有多个,where都会找出来,所以返回时返回前m个需要的即可(因为对于多个最小值,属于哪个类别都可以)
770+
'''
771+
dummy,idx = np.where(dis == np.min(dis, axis=1).reshape(-1,1))
772+
return idx[0:dis.shape[0]] # 注意截取一下
773+
```
774+
- 计算类中心实现代码:
775+
```
776+
# 计算类中心
777+
def computerCentroids(X,idx,K):
778+
n = X.shape[1]
779+
centroids = np.zeros((K,n))
780+
for i in range(K):
781+
centroids[i,:] = np.mean(X[np.ravel(idx==i),:], axis=0).reshape(1,-1) # 索引要是一维的,axis=0为每一列,idx==i一次找出属于哪一类的,然后计算均值
782+
return centroids
783+
```
784+
785+
### 2、目标函数
786+
- 也叫做**失真代价函数**
787+
- ![J({c^{(1)}}, \cdots ,{c^{(m)}},{u_1}, \cdots ,{u_k}) = \frac{1}{m}\sum\limits_{i = 1}^m {||{x^{(i)}} - {u_{{c^{(i)}}}}|{|^2}} ](http://chart.apis.google.com/chart?cht=tx&chs=1x0&chf=bg,s,FFFFFF00&chco=000000&chl=J%28%7Bc%5E%7B%281%29%7D%7D%2C%20%5Ccdots%20%2C%7Bc%5E%7B%28m%29%7D%7D%2C%7Bu_1%7D%2C%20%5Ccdots%20%2C%7Bu_k%7D%29%20%3D%20%5Cfrac%7B1%7D%7Bm%7D%5Csum%5Climits_%7Bi%20%3D%201%7D%5Em%20%7B%7C%7C%7Bx%5E%7B%28i%29%7D%7D%20-%20%7Bu_%7B%7Bc%5E%7B%28i%29%7D%7D%7D%7D%7C%7B%7C%5E2%7D%7D%20)
788+
- 最后我们想得到:
789+
![\mathop {\min }\limits_\begin{subarray}{l}
790+
{c^{(1)}}, \cdots ,{c^{(m)}} \\
791+
{u_1}, \cdots ,{u_k}
792+
\end{subarray} J({c^{(1)}}, \cdots ,{c^{(m)}},{u_1}, \cdots ,{u_k})](http://chart.apis.google.com/chart?cht=tx&chs=1x0&chf=bg,s,FFFFFF00&chco=000000&chl=%5Cmathop%20%7B%5Cmin%20%7D%5Climits_%5Cbegin%7Bsubarray%7D%7Bl%7D%20%0A%20%20%7Bc%5E%7B%281%29%7D%7D%2C%20%5Ccdots%20%2C%7Bc%5E%7B%28m%29%7D%7D%20%5C%5C%20%0A%20%20%7Bu_1%7D%2C%20%5Ccdots%20%2C%7Bu_k%7D%20%0A%5Cend%7Bsubarray%7D%20%20J%28%7Bc%5E%7B%281%29%7D%7D%2C%20%5Ccdots%20%2C%7Bc%5E%7B%28m%29%7D%7D%2C%7Bu_1%7D%2C%20%5Ccdots%20%2C%7Bu_k%7D%29)
793+
- 其中![{c^{(i)}}](http://chart.apis.google.com/chart?cht=tx&chs=1x0&chf=bg,s,FFFFFF00&chco=000000&chl=%7Bc%5E%7B%28i%29%7D%7D)表示第`i`条数据距离哪个类中心最近,
794+
- 其中![{u_i}](http://chart.apis.google.com/chart?cht=tx&chs=1x0&chf=bg,s,FFFFFF00&chco=000000&chl=%7Bu_i%7D)即为聚类的中心
795+
796+
### 3、聚类中心的选择
797+
- 随机初始化,从给定的数据中随机抽取K个作为聚类中心
798+
- 随机一次的结果可能不好,可以随机多次,最后取使代价函数最小的作为中心
799+
- 实现代码:(这里随机一次)
800+
```
801+
# 初始化类中心--随机取K个点作为聚类中心
802+
def kMeansInitCentroids(X,K):
803+
m = X.shape[0]
804+
m_arr = np.arange(0,m) # 生成0-m-1
805+
centroids = np.zeros((K,X.shape[1]))
806+
np.random.shuffle(m_arr) # 打乱m_arr顺序
807+
rand_indices = m_arr[:K] # 取前K个
808+
centroids = X[rand_indices,:]
809+
return centroids
810+
```
811+
812+
### 4、聚类个数K的选择
813+
- 聚类是不知道y的label的,所以不知道真正的聚类个数
814+
- 肘部法则(Elbow method)
815+
- 作代价函数`J``K`的图,若是出现一个拐点,如下图所示,`K`就取拐点处的值,下图此时`K=3`
816+
![enter description here][37]
817+
- 若是很平滑就不明确,人为选择。
818+
- 第二种就是人为观察选择
819+
820+
### 5、应用——图片压缩
821+
- 将图片的像素分为若干类,然后用这个类代替原来的像素值
822+
- 执行聚类的算法代码:
823+
```
824+
# 聚类算法
825+
def runKMeans(X,initial_centroids,max_iters,plot_process):
826+
m,n = X.shape # 数据条数和维度
827+
K = initial_centroids.shape[0] # 类数
828+
centroids = initial_centroids # 记录当前类中心
829+
previous_centroids = centroids # 记录上一次类中心
830+
idx = np.zeros((m,1)) # 每条数据属于哪个类
831+
832+
for i in range(max_iters): # 迭代次数
833+
print u'迭代计算次数:%d'%(i+1)
834+
idx = findClosestCentroids(X, centroids)
835+
if plot_process: # 如果绘制图像
836+
plt = plotProcessKMeans(X,centroids,previous_centroids) # 画聚类中心的移动过程
837+
previous_centroids = centroids # 重置
838+
centroids = computerCentroids(X, idx, K) # 重新计算类中心
839+
if plot_process: # 显示最终的绘制结果
840+
plt.show()
841+
return centroids,idx # 返回聚类中心和数据属于哪个类
842+
```
843+
844+
### 6、[使用scikit-learn库中的线性模型实现聚类](/K-Means/K-Means_scikit-learn.py.py)
845+
846+
- 导入包
847+
```
848+
from sklearn.cluster import KMeans
849+
```
850+
- 使用模型拟合数据
851+
```
852+
model = KMeans(n_clusters=3).fit(X) # n_clusters指定3类,拟合数据
853+
```
854+
- 聚类中心
855+
```
856+
centroids = model.cluster_centers_ # 聚类中心
857+
```
858+
859+
### 7、运行结果
860+
- 二维数据类中心的移动
861+
![enter description here][38]
862+
- 图片压缩
863+
![enter description here][39]
864+
865+
866+
----------------------
741867

868+
六、主成分分析(降维)
742869

743870

744871

@@ -776,4 +903,10 @@ def predict(Theta1,Theta2,X):
776903
[30]: ./images/SVM_07.png "SVM_07.png"
777904
[31]: ./images/SVM_08.png "SVM_08.png"
778905
[32]: ./images/SVM_09.png "SVM_09.png"
779-
[33]: ./images/SVM_10.png "SVM_10.png"
906+
[33]: ./images/SVM_10.png "SVM_10.png"
907+
[34]: ./images/K-Means_01.png "K-Means_01.png"
908+
[35]: ./images/K-Means_02.png "K-Means_02.png"
909+
[36]: ./images/K-Means_03.png "K-Means_03.png"
910+
[37]: ./images/K-Means_04.png "K-Means_04.png"
911+
[38]: ./images/K-Means_05.png "K-Means_05.png"
912+
[39]: ./images/K-Means_06.png "K-Means_06.png"

0 commit comments

Comments
 (0)