Andrew Ng课程作业第七周(python版)
作业目的:学习无监督K-均值算法
作业内容:将多个平面散点划分为3个簇
提供的数据:ex7data2.txt(mooc可下载),X的第一、二列为横纵坐标
处理过程:
- step1:读取数据
data=loadmat('d:/jupyter/ipython-notebooks-master/data/ex7data2.mat') X=data['X'] X.shape
- step2:在平面上随机取3个点作为簇的中心
def init_centroids(X,k): m,n=X.shape #300,2 centroids=np.zeros((k,n)) #k=3 idx=np.random.randit(0,m,k) #从0到300随机选择3个数值 for i in range(k): centroids[i,:]=X[idx[i],:] return centroids init_centroids(X,3)
- step3:根据初始中心找对应的所有簇中的点
def find_cluster(X,centroids): m=X.shape[0] k=centroids.shape[0] idx=np.zeros(m) for i in range(m): min_dist=100000 for j in range(k): dist = np.sum((X[i,:] - centroids[j,:]) ** 2) if dist < min_dist: min_dist = dist idx[i] = j return idx #idx为np数组,存储X每一个点所对应的簇中心(0,1,2)
- step4:根据形成的三个簇重新计算中心节点
def compute_center(X,idx,k): m,n=X.shape centroids=np.zeros((k,n)) #初始化 for i in range(k): indices = np.where(idx==i) #每个簇对应的点在X中的位置 #np.where在只有condition的情况下返回tuple of ndarrays,后面调用indices[0] sum_X=np.sum(X[indices,:],axis=1) #求点每列的和 centroids[i,:]=(sum_X/len(indices[0])).ravel() #取平均值,作为新的簇中心 return centroids
compute_centroids(X,idx,3)
- step5:综合上述步骤,将找簇和根据簇找新的中心的操作迭代进行
def run_k_means(X,initial_centroids,max_iters): m,n=X.shape k=initial_centroids.shape[0] idx=np.zeros(m) centroids = initial_centroids for i in range(max_iters): idx=find_cluster(X,centroids) centroids=compute_centroids(X,idx,k) return idx,centroids
- step6:画图,确认分类结果
idx, centroids = run_k_means(X, initial_centroids, 10) cluster1 = X[np.where(idx == 0)[0],:] cluster2 = X[np.where(idx == 1)[0],:] cluster3 = X[np.where(idx == 2)[0],:] fig, ax = plt.subplots(figsize=(12,8)) ax.scatter(cluster1[:,0], cluster1[:,1], s=30, color='r', label='Cluster 1') ax.scatter(cluster2[:,0], cluster2[:,1], s=30, color='g', label='Cluster 2') ax.scatter(cluster3[:,0], cluster3[:,1], s=30, color='b', label='Cluster 3') ax.legend()

p.s. 可能有人会问,为什么簇数量选择3,其实看X的分布图也能确定簇的数量为3,当然也可以用“肘部”观察法。
from sklearn.cluster import KMeans from scipy.spatial.distance import cdist K=range(1,5) meandistortions=[] for k in K: kmeans=KMeans(n_clusters=k) kmeans.fit(X) min_x=np.min(cdist(X,kmeans.cluster_centers_,'euclidean'),axis=1) meandistortions.append(sum(min_x)/X.shape[0]) plt.plot(K,meandistortions,'bx-') plt.xlabel('k') plt.ylabel('Average Dispersion') plt.show()

因此,簇数量选择3。
p.s. 用scikit-learn库也可以。
from sklearn.cluster import KMeans import matplotlib.pyplot as plt kmeans_model=KMeans(n_clusters=3).fit(X) print(kmeans_model.labels_) cluster1 = X[np.where(kmeans_model.labels_== 0)[0],:] cluster2 = X[np.where(kmeans_model.labels_ == 1)[0],:] cluster3 = X[np.where(kmeans_model.labels_ == 2)[0],:] fig, ax = plt.subplots(figsize=(12,8)) ax.scatter(cluster1[:,0], cluster1[:,1], s=30, color='r', label='Cluster 1') ax.scatter(cluster2[:,0], cluster2[:,1], s=30, color='g', label='Cluster 2') ax.scatter(cluster3[:,0], cluster3[:,1], s=30, color='b', label='Cluster 3') ax.legend()
浙公网安备 33010602011771号