1. 程式人生 > >機器學習作業KNN(下)——字元分類

機器學習作業KNN(下)——字元分類

  1. 作業背景: 今天機器學習實驗課,老師給了個很小的資料集,是劃分英文字母B和M,讓我們用KNN做,看看分類效果嗎,正好我上個實驗也用的KNN,所以把上次的程式稍微修改一下即可(偷懶狂魔)。

  2. 資料預處理: 大致看了下資料集,是這個樣子的: 在這裡插入圖片描述 2.1 特徵選取: 所以,老規矩,先看看哪些特徵是沒有用的,很明顯id對分類不產生影響,將其剔除。剩下的特徵都有用,將其留下。 2.2 歸一化的問題:發現有些特徵都是過百的,而有些特徵在0~1之間徘徊,很明顯,過大的資料產生的影響會蓋過小值對分類的效用,所以要進行資料集的歸一化。 2.3 選取訓練集,資料集: 首先先打亂資料集,選取亂序後的資料集的前10行作為測試集,剩下的作為訓練集,訓練模型

  3. 資料視覺化: 由於是不是二維的,所以沒直接在座標上視覺化,所以我選區了幾個特徵進行了視覺化,如下圖所示: 在這裡插入圖片描述 資料質量還是客觀的,可以用於訓練,下面是程式碼塊>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  4. 程式碼塊(程式碼改的的有點醜,不要介意)

import numpy as np
import matplotlib.pyplot as plt
import
operator import pandas as pd #################讀取檔案(資料預處理)######################### def filematrix(filename): array0Lines = np.matrix(pd.read_csv(filename)) ##讀取檔案,選取前20行資料作為訓練集,最後三行資料作為測試集。 returnMat = array0Lines[:, 2:33] ##訓練集 number0Lines = array0Lines.shape[0] ##讀取檔案行數
classLabelVector = [] ##訓練集分類標籤向量 for line in array0Lines: #遍歷資料集,獲取分類標籤資訊 if line[:,1]=='B': classLabelVector.append('B') elif line[:,1]=='M': classLabelVector.append('M') return returnMat,np.matrix(classLabelVector).T ##返回訓練集和標籤向量 def showdatas(datingDataMat,datingLabels): """ 函式說明:視覺化資料 Parameters: datingDataMat - 特徵矩陣 datingLabels - 分類Label Returns: 無 """ #不同型別資料的顏色 LabelsColors = [] ##存放資料顏色的陣列 for i in datingLabels: if i == 'B': LabelsColors.append('blue') elif i == 'M': LabelsColors.append('red') fig,axs = plt.subplots(nrows=2,ncols=2,figsize=(10,6)) #畫圖時要注意把matrix格式換成list格式,否則不能畫圖 ###由於特徵有點多,所以畫圖時,我只選擇了其中幾個特徵看看分佈 axs[0][0].scatter(datingDataMat[:,2].tolist(),datingDataMat[:,3].tolist(),color=LabelsColors,s=15,alpha=.5) axs[0][1].scatter(datingDataMat[:,4].tolist(), datingDataMat[:, 5].tolist(), color=LabelsColors, s=15, alpha=.5) axs[1][0].scatter(datingDataMat[:, 6].tolist(), datingDataMat[:, 7].tolist(), color=LabelsColors, s=15, alpha=.5) axs[1][1].scatter(datingDataMat[:, 8].tolist(), datingDataMat[:, 9].tolist(), color=LabelsColors, s=15, alpha=.5) """ ###設定圖列legend '0' = mlines.Line2D([], [], color='black', marker='.',markersize=6, label='0') '1' = mlines.Line2D([], [], color='orange', marker='.',markersize=6, label='1') '2' = mlines.Line2D([], [], color='red', marker='.',markersize=6, label='2') plt.legend(handles=[0,1,2]) """ plt.show() def autoNorm(dataSet): """ 函式說明:對資料進行歸一化 Parameters: dataSet - 特徵矩陣 Returns: normDataSet - 歸一化後的特徵矩陣 ranges - 資料範圍 minVals - 資料最小值 """ #meanVals = dataSet.mean(0) #資料平均值 #stdVals = dataSet.std(0) minVals = dataSet.min(0) #資料最小值 maxVals = dataSet.max(0) #資料最大值 ranges = maxVals - minVals #最大值和最小值的差距 normDataSet = np.zeros(np.shape(dataSet)) #用於存放歸一化後的資料集 m= dataSet.shape[0] #返回資料集的行數 ###歸一化過程 #normDataSet = dataSet-meanVals #normDataSet = normDataSet/stdVals normDataSet = dataSet - np.tile(minVals,(m,1)) #原始資料減去最小資料 normDataSet = normDataSet/np.tile(ranges,(m,1)) #所得之差除以最大值最小值得差,得到歸一化資料 return normDataSet,ranges,minVals #返回歸一化資料結果,資料範圍,最小值 def classify(inX,dataSet,labels,k): dataSetSize = dataSet.shape[0] #返回dataSet的行數 diffMat = np.tile(inX,(dataSetSize,1)) - dataSet #測試矩陣-資料集 sqDiffMat = np.multiply(diffMat,diffMat) sqDistances = sqDiffMat.sum(axis=1).tolist() #沿著列的方向相加 #sqDistances = sqDistances.tolist() #這一步是為了把matrix格式,轉化成ndarray格式,否則下一行的操作會報錯 distances = np.sqrt(np.ravel(sqDistances)) #先展開成一維,再開平方歐式距離 sortedDisIndices = distances.argsort() #返回distances中元素從小到大排序後的索引值 classCount = {} #空字典,用來記錄類別次數 for i in range(k): #遍歷 voteIlabel = labels[sortedDisIndices[i]] #取出最近的K個點 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #存放出現的類別次數 #根據字典的值進行降序排序 sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) return sortedClassCount[0][0] #返回次數最多的類別 def datingClassTest(): filename = "G:/shiyan2/Ex2.1_KNN.csv" datingDataMat, datingLabels = filematrix(filename) normMat, ranges, minVals = autoNorm(datingDataMat) ###打亂資料集,並取前20個作為訓練集 index = np.arange(50) np.random.shuffle(index) dataSet = normMat[index] test = normMat[0:11, :] # 測試集 numTestVecs = len(test) #測試集個數 m = np.shape(normMat)[0] #獲得normMat的行數 errorCount = 0.0 #分類錯誤計數 for i in range (numTestVecs-1): classifierResult = classify(test[i,:],normMat[numTestVecs:m,:],np.ravel(datingLabels)[numTestVecs:m],5) ##前numTestVecs 作為測試集,後m-numTestVecs作為訓練集,這邊注意要是list格式,否則不能迭代的 print("分類結果:%s\t真實類別:%s"%(classifierResult,datingLabels[i])) if classifierResult!=datingLabels[i]: errorCount+=1.0 print("錯誤率:%f%%"%(errorCount/float(numTestVecs)*100)) showdatas(datingDataMat,datingLabels) if __name__ =='__main__': datingClassTest()
分類結果:B	真實類別:[['B']]
分類結果:B	真實類別:[['B']]
分類結果:B	真實類別:[['B']]
分類結果:B	真實類別:[['B']]
分類結果:B	真實類別:[['B']]
分類結果:B	真實類別:[['B']]
分類結果:M	真實類別:[['B']]
分類結果:M	真實類別:[['M']]
分類結果:B	真實類別:[['B']]
分類結果:B	真實類別:[['B']]
錯誤率:9.090909%



<Figure size 1000x600 with 4 Axes>