【簡介】

#coding:utf-8 import sys from numpy import * import operator import matplotlib.pyplot as plt def classify(input,dataSet,label): dataSize = dataSet.shape[0] ####計算歐式距離 tarry=tile(input,(dataSize,1));#生成dataSet一樣的矩陣,進行剪發運算 diff = tarry - dataSet sqdiff = diff ** 2 #各參數平方(X²,Y²),得到距離 squareDist = sum(sqdiff,axis = 1)#行向量分別相加,從而得到新的一個行向量 X²,Y²相加, dist = list(squareDist ** 0.5) #開放,得到歐式距離 return label[dist.index(min(dist))] #返回最近鄰 //找到距離最小值,並得與之對應的類型 dataSet = array([[0.1,2.8],[1.9,0.6],[1.0,2.0], [3.0,2.5],[2.0,2.5],[1.8,3.0], [0.1,0.1],[0.5,0.5],[1.5,0.5], [1.5,1.5],[1.7,0.1],[2.5,0.2], ]) labels = ['A','A','A','B','B','B','C','C','C','D','D','D'] input = array([1.9,0.5]) print("input = ",input) output = classify(input,dataSet,labels) print("class = ",output) plt.figure(figsize=(5,5)) for i,j in enumerate(dataSet): if labels[i] == 'A': plt.scatter(j[0],j[1],marker ="^",c="blue",s=80) elif labels[i] == 'B': plt.scatter(j[0],j[1],marker ="D",c ="green",s=80) elif labels[i] == 'C': plt.scatter(j[0],j[1],marker ="o",c ="darkorange",s=80) elif labels[i] == 'D': plt.scatter(j[0],j[1],marker ="s",c ="purple",s=80) plt.scatter(input[0],input[1],marker ="*",c ="red",s=200) plt.axis('tight') plt.show()
結果:
【K近鄰算法】
最近鄰算法的最大缺陷是對干擾數據過於敏感,為了解決這個問題,我們可以把未知樣本周邊的多個鄰近樣本計算在內,擴大參與決策的樣本量,以避免個別數據直接決定決策結果。由此,我們引進K-最近鄰算法(KNN)。K近鄰算法是最近鄰算法的一個延伸。思路是:如果一個樣本在特征空間中的k個最相似(即特征空間中最鄰近)的樣本中的大多數屬於某一個類別,則該樣本也屬於這個類別。一般情況下,在分類時較大的K值能夠減小干擾數據的影響。

#coding:utf-8 import sys from numpy import * import operator import matplotlib.pyplot as plt ###通過KNN進行分類 def classify(input,dataSet,label,k): dataSize = dataSet.shape[0] ####計算歐式距離 diff = tile(input,(dataSize,1)) - dataSet sqdiff = diff ** 2 squareDist = sum(sqdiff,axis = 1)###行向量分別相加,從而得到新的一個行向量 dist = squareDist ** 0.5 ##對距離進行排序 sortedDistIndex = argsort(dist)##argsort()根據元素的值從大到小對元素進行排序,返回下標 classCount={} for i in range(k): voteLabel = label[sortedDistIndex[i]] ###對選取的K個樣本所屬的類別個數進行統計 classCount[voteLabel] = classCount.get(voteLabel,0) + 1 ###選取出現的類別次數最多的類別 maxCount = 0 for key,value in classCount.items(): if value > maxCount: maxCount = value classes = key return classes dataSet = array([[0.1,2.8],[1.9,0.6],[1.0,2.0], [3.0,2.5],[2.0,2.5],[1.8,3.0], [0.1,0.1],[0.5,0.5],[1.5,0.5], [1.5,1.5],[1.7,0.1],[2.5,0.2], ]) labels = ['A','A','A','B','B','B','C','C','C','D','D','D'] input = array([1.9,0.5]) print("input = ",input) for K in range(1,13): output = classify(input,dataSet,labels,K) print("K = ",K,"class = ",output) plt.figure(figsize=(5,5)) for i,j in enumerate(dataSet): if labels[i] == 'A': plt.scatter(j[0],j[1],marker ="^",c="blue",s=80) elif labels[i] == 'B': plt.scatter(j[0],j[1],marker ="D",c ="green",s=80) elif labels[i] == 'C': plt.scatter(j[0],j[1],marker ="o",c ="darkorange",s=80) elif labels[i] == 'D': plt.scatter(j[0],j[1],marker ="s",c ="purple",s=80) plt.scatter(input[0],input[1],marker ="*",c ="red",s=200) plt.axis('tight') plt.show()
結果:
【K-Means++算法
K-Means++算法在聚類中心的初始化過程中的基本原則是使得初始的聚類中心之間的相互距離盡可能遠,這樣可以避免出現上述的問題。K-Means++算法的初始化過程如下所示:
在數據集中隨機選擇一個樣本點作為第一個初始化的聚類中心
選擇出其余的聚類中心:
計算樣本中的每一個樣本點與已經初始化的聚類中心之間的距離,並選擇其中最短的距離,記為d_i 以概率選擇距離最大的樣本作為新的聚類中心,
重復上述過程,直到k個聚類中心都被確定 對k個初始化的聚類中心,利用K-Means算法計算最終的聚類中心。
#隨機生成數據 def CreateDataset(number): #生成數組 dataArry=np.zeros((number,2)); #轉為矩陣 dataSet=np.mat(dataArry); #數據分類聚類 offset=[[-80,-80],[-80,80],[-20,-20],[0,0],[80,-80],[30,-80],[80,80]]; #生成隨機數據 for i in range(number): dataSet[i]=np.random.uniform(-20,20)+offset[i%7][0],np.random.uniform(-20,20)+offset[i%7][1]; #返回數據 return dataSet; #矩陣求歐式距離 def Distance(vectot1,vector2): #求樣本數據差 sub=vector2-vectot1; #求矩陣平方 pows=np.power(sub,2); _sum=np.sum(pows); #求距離 distance=np.sqrt(_sum); return distance; #求樣本數據在聚集點數據中的最近點 def nearest(point,cluster_centers): #線初始化一個比較大的最小值 min_dis=10000000; # 當前已經初始化的聚類中心的個數 m=np.shape(cluster_centers)[0]; #遍歷聚類中心 for i in range(m): #計算point與每個聚類中心的距離 d=Distance(point,cluster_centers[i,]); #判斷是否小是最短距離 if min_dis>d: min_dis=d; return min_dis; #生成聚類點 def clusterCenter(dataSet,k): #1、獲取樣本數據集的shape num,dim=dataSet.shape; #2、創建聚集點集 clusterPoints=np.zeros((k,dim)); cluster_centers=np.mat(clusterPoints); #3、隨機在樣本數據中選取一個點作為第一個聚集點 index=np.random.randint(0,num); cluster_centers[0,]=dataSet[index,]; #4、初始化一個距離序列 disList=[0.0 for _ in range(num)]; #5、從第二個點開始遍歷聚合點(第一個點已經賦值了) for i in range(1,k): sum_all=0; for j in range(num): #6、對每一個樣本點找到最近的聚類中心 point=dataSet[j,];#獲取第j個樣本 cluster_points=cluster_centers[0:i,];#獲取前i個樣本數據 disList[j]=nearest(point,cluster_points); #7、將所有最短距離相加 sum_all=sum_all+disList[j]; #8、獲取sum_all之間的隨機值 sum_all = np.random.uniform(0,int(sum_all)); # 9、獲得距離最遠的樣本點作為聚類中心點 for j, di in enumerate(disList): sum_all -= di if sum_all > 0: continue cluster_centers[i] = dataSet[j,]; break return cluster_centers; #K-Means聚類 def kmeans(data,k,centroids): #獲取樣本維度,m表示樣本個數,n表示樣本維度 m,n=np.shape(data); #初始化樣本所屬類別 subCenter=np.mat(np.zeros((m,n))); #初始化判斷變量 change=True; #訓練數據 while change==True: #重置變量 change=False; #遍歷樣本數據 for i in range(m): minDis=10000000;#初始化最小數據 minIndex=0;#初始化最小距離的 #遍歷聚集點 for j in range(k): #計算兩點距離 dist=Distance(data[i,],centroids[j,]); #判斷距離是否為最小 if dist <minDis: minDis=dist; minIndex=j; #判斷是否需要改變 subCenter[i,0]不等於minindex if subCenter[i,0] != minIndex: change=True; subCenter[i,]=np.mat([minIndex, minDis]) #重新計算聚類中心 for j in range(k): #創建數據維度的總和矩形 sum_all=np.mat(np.zeros((1,n))); count=0;#沒類的樣本個數 #循環所屬類別數據 for i in range(m): if subCenter[i,0]==j: sum_all+=data[i,]; count+=1; #遍歷數據維度 for z in range(n): try: centroids[j,z]=sum_all[0,z]/count; except: print("count為零"); return subCenter; #保存聚類數據 def save_result(file_name, source): m, n = np.shape(source) f = open(file_name, "w") for i in range(m): tmp = [] for j in range(n): tmp.append(str(source[i, j])) f.write("\t".join(tmp) + "\n") f.close() print("保存完成"); #主函數 if __name__=="__main__": dataNum=300;#樣本數據集量 k=7;#分類數 # 1、創建數據 dataSet=CreateDataset(dataNum); print("數據初始化完成"); #生成聚合點 cluster_centers=clusterCenter(dataSet,k); print("生成聚合點"); #開始聚類 subcenter=kmeans(dataSet,k,cluster_centers); print("聚類完成"); #保存數據所屬類別數據 save_result("subcenter.txt",subcenter); #保存數據所屬類別數據 save_result("cluster_centers.txt",cluster_centers); #畫圖 #plt.figure(figsize=(-100,100)); #繪制數據 numSamples, dim = dataSet.shape mark = ['or', 'og', 'ob', 'oc', 'om', 'oy', 'ok', 'ow'] for i in range(numSamples): markIndex = int(subcenter[i, 0]); plt.plot(dataSet[i, 0], dataSet[i, 1], mark[markIndex-1]) #繪制聚合點 mark = ['*r', '*g', '*b', '*c', '*m', '*y', '*k', '*w'] for i in range(k): plt.plot(cluster_centers[i, 0], cluster_centers[i, 1], mark[i-1], markersize = 12) plt.axis('tight') plt.show() print("完成");
【參考文獻】
https://blog.csdn.net/sm9sun/article/details/78521927
https://www.cnblogs.com/charlesblc/p/6193979.html
http://blog.csdn.net/acdreamers/article/details/44672305
http://blog.csdn.net/u013414741/article/details/47108317
https://www.cnblogs.com/ybjourney/p/4702562.html
https://blog.csdn.net/google19890102/article/details/53284285