機器學習小作業KNN分類(上)
阿新 • • 發佈:2018-12-20
-
資料預處理 1.1首先第4列資料並不影響分類結果,所以將其剔除 1.2資料集太過於奇葩,所以做了歸一化處理 1.3因為做的是分類,所以我想把值控制在0-1,所以採用的歸一化方法是:(dataSet - min)/(max-min) 1.4打亂資料集,因為本來的資料集是排序好的,而且有些資料太奇葩,所以事先將其打亂;一般會選取10%的資料作為測試集,但是顯然我的資料太少了,所以我選擇了打亂之後的前5行資料作為測試集,剩下的作為訓練集(真心覺得資料是老師自己編寫的)
-
演算法 2.1KNN演算法網上百度一大推,這裡我看的是李航老師的《統計學習方法》,推導寫的很不錯,推薦大家可以看一下,我就不寫了(反正也是截圖******滑稽******) 2.2資料之間的距離,歐式距離,很好做的。
-
除錯 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。