1. 程式人生 > >機器學習小作業KNN分類(上)

機器學習小作業KNN分類(上)

  1. 資料預處理 1.1首先第4列資料並不影響分類結果,所以將其剔除 1.2資料集太過於奇葩,所以做了歸一化處理 1.3因為做的是分類,所以我想把值控制在0-1,所以採用的歸一化方法是:(dataSet - min)/(max-min) 1.4打亂資料集,因為本來的資料集是排序好的,而且有些資料太奇葩,所以事先將其打亂;一般會選取10%的資料作為測試集,但是顯然我的資料太少了,所以我選擇了打亂之後的前5行資料作為測試集,剩下的作為訓練集(真心覺得資料是老師自己編寫的)

  2. 演算法 2.1KNN演算法網上百度一大推,這裡我看的是李航老師的《統計學習方法》,推導寫的很不錯,推薦大家可以看一下,我就不寫了(反正也是截圖******滑稽******) 2.2資料之間的距離,歐式距離,很好做的。

  3. 除錯 3.1hash 發現list不能hash,matrix也不能hash,除錯了我好久,我太菜了

import numpy as np
import matplotlib.pyplot as plt
import operator
import pandas as pd
from math import  sqrt
from matplotlib.font_manager import FontProperties
#################讀取檔案(資料預處理)#########################
def filematrix(filename):
    array0Lines =
np.matrix(pd.read_csv(filename)) ##讀取檔案,選取前20行資料作為訓練集,最後三行資料作為測試集。 returnMat = array0Lines[:, 1:3] ##訓練集 number0Lines = array0Lines.shape[0] ##讀取檔案行數 classLabelVector = [] ##訓練集分類標籤向量 for line in array0Lines: #遍歷資料集,獲取分類標籤資訊
if line[:,0]==0: classLabelVector.append(0) elif line[:,0]==1: classLabelVector.append(1) elif line[:,0]==2: classLabelVector.append(2) return returnMat,np.matrix(classLabelVector).T ##返回訓練集和標籤向量 ####################資料視覺化######################### def showdatas(datingDataMat,datingLabels): """ 函式說明:視覺化資料 Parameters: datingDataMat - 特徵矩陣 datingLabels - 分類Label Returns: 無 """ #不同型別資料的顏色 LabelsColors = [] ##存放資料顏色的陣列 for i in datingLabels: if i == 0: LabelsColors.append('black') elif i == 1: LabelsColors.append('orange') elif i == 2: LabelsColors.append('red') fig,ax = plt.subplots(figsize=(10,6)) #畫圖時要注意把matrix格式換成list格式,否則不能畫圖 ax.scatter(datingDataMat[:,0].tolist(),datingDataMat[:,1].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) #沿著列的方向相加 distances = np.ravel(np.sqrt(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:/shiyan1/shiyan1/Ex1.1_Challenger.csv" datingDataMat, datingLabels = filematrix(filename) #訓練集,標籤,測試集 normMat,ranges,minVals = autoNorm(datingDataMat) ###打亂資料集,並取前20個作為訓練集 index = np.arange(23) np.random.shuffle(index) dataSet = normMat[index] test = normMat[0:6,:] #測試集 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("分類結果:%d\t真實類別:%d"%(classifierResult,datingLabels[i])) if classifierResult!=datingLabels[i]: errorCount+=1.0 print("錯誤率:%f%%"%(errorCount/float(numTestVecs)*100)) if __name__=='__main__': datingClassTest()
分類結果:0	真實類別:0
分類結果:0	真實類別:1
分類結果:0	真實類別:0
分類結果:0	真實類別:0
分類結果:0	真實類別:0
錯誤率:16.666667%

有一個數據錯了,就是那個特別奇葩的資料。。。。。。。。。。。。。。。。。。。 果然資料處理才是煩的,還有python的一大堆格式問題。 希望有大佬能教教我,怎麼畫legend。