@@ -736,9 +736,136 @@ def predict(Theta1,Theta2,X):
736
736
737
737
## 五、K-Means聚类算法
738
738
- [ 全部代码] ( /K-Means/K-Menas.py )
739
- ### 1、
740
739
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
+ ----------------------
741
867
868
+ 六、主成分分析(降维)
742
869
743
870
744
871
@@ -776,4 +903,10 @@ def predict(Theta1,Theta2,X):
776
903
[ 30 ] : ./images/SVM_07.png " SVM_07.png "
777
904
[ 31 ] : ./images/SVM_08.png " SVM_08.png "
778
905
[ 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