py2.7 : 《機器學習實戰》 k-近鄰演算法 11.19 更新完畢
阿新 • • 發佈:2019-01-25
主要有幾個總結的:
1.python支援檔案模組化,所以在同一個目錄下import就可以呼叫了;
2.中文註釋要加上 # -*- coding: utf-8 -*-
3.import numpy 和 from numpy import * 區別是, 對於前者,呼叫的時候需要加上名字:numpy.方法() ; 對於後者,直接 方法();
剩下的多多少少的放在程式碼的註釋裡了。
test.py:
輸出:
在test.py中執行
效果圖:
test.py:
輸出:
輸出結果:
至此2.2:使用k-近鄰演算法改進約會網站配對效果結束
1.python支援檔案模組化,所以在同一個目錄下import就可以呼叫了;
2.中文註釋要加上 # -*- coding: utf-8 -*-
3.import numpy 和 from numpy import * 區別是, 對於前者,呼叫的時候需要加上名字:numpy.方法() ; 對於後者,直接 方法();
剩下的多多少少的放在程式碼的註釋裡了。
2.1.2 實施kNN演算法
# -*- coding: utf-8 -*- from numpy import * import operator def createDataSet(): group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]) labels = ['A','A','B','B'] return group,labels def classify0(inX , dataSet , labels, k): #4個輸入引數分別為:用於分類的輸入向量inX,輸入的訓練樣本集dataSet,標籤向量labels,選擇最近鄰居的數目k dataSetSize = dataSet.shape[0]#把行數求出來 diffMat = tile(inX , (dataSetSize,1) ) - dataSet #tile是將inx陣列重複n次,把相對距離的x y 求出來 sqDiffMat = diffMat**2 #表示乘方,diffMar^2 sqDistance = sqDiffMat.sum(axis=1) #axis = 1代表行向量相加, 0就是普通的求和 distance = sqDistance**0.5#距離 sortedDisIndicies = distance.argsort() #np排序,代表的是返回從小到大排序的下標 classCount = {} for i in range(k): #取歐氏距離計算 voteIlabel = labels[sortedDisIndicies[i]] classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #get返回指定鍵的值,否則返回預設值 sortedClasscount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True) #排序 return sortedClasscount[0][0]
test.py:
import kNN
group , labels = kNN.createDataSet()
print kNN.classify0([0,0],group,labels,3
輸出:
B
2.2 示例:使用k-近鄰演算法改進約會網站的配對效果
2-2 將文字記錄轉換為Numpy的解析程式
資料集放在 2.2data 中, 可以下載使用(注意檔名字是:datingTestSet2 , 開啟檔案書上沒這個‘2’)
在kNN.py中加入如下程式碼
def file2matrix(filename):#講文字記錄解析為Numpy的解析程式 fr = open(filename) arrayOLines = fr.readlines() numberOfLines = len(arrayOLines) returnMat = zeros((numberOfLines,3)) #填充0,另一緯度設定為固定的3 classLabelVector = [] #把分類labels存為列表 index = 0 for line in arrayOLines: line = line.strip() #去除最右端回車 listFromLine = line.split('\t') #用空格把字串分成列表 returnMat[index,:] = listFromLine[0:3] #選取前三個特徵存到特徵矩陣裡,然後index自加 classLabelVector.append(int(listFromLine[-1])) #負索引把特徵值提取出來並且標為int變數 index+=1 return returnMat,classLabelVector
在test.py中執行
import kNN
datingDataMat,datingLabels = kNN.file2matrix('datingTestSet2.txt')
print(datingDataMat)
print(datingLabels[0:20])
輸出答案:
[[ 4.09200000e+04 8.32697600e+00 9.53952000e-01] [ 1.44880000e+04 7.15346900e+00 1.67390400e+00] [ 2.60520000e+04 1.44187100e+00 8.05124000e-01] ..., [ 2.65750000e+04 1.06501020e+01 8.66627000e-01] [ 4.81110000e+04 9.13452800e+00 7.28045000e-01] [ 4.37570000e+04 7.88260100e+00 1.33244600e+00]] [3, 2, 1, 1, 1, 1, 3, 3, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3]
2.2.2 : 分析資料:使用matplotlib建立散點圖
先分析 ‘玩遊戲視訊所耗時間半分比’ 和 ‘每週消費的冰淇淋公升數’
import kNN
import matplotlib
import matplotlib.pyplot as plt
from numpy import *
import operator
datingDataMat,datingLabels = kNN.file2matrix('datingTestSet2.txt')
fig = plt.figure()#建立圖形
ax = fig.add_subplot(111)#也可以寫為1,1,1 ; 代表建立1行1列為p1的子圖
# 對訓練樣本矩陣進行畫圖
#使用第二列和第三列資料,代表的是“玩視訊遊戲所耗時間”和“每週消費冰淇淋數”
ax.scatter(datingDataMat[:,1], datingDataMat[:,2],15*array(datingLabels),15*array(datingLabels), label=u'散點圖')
plt.xlabel(u'玩視訊遊戲所耗時間半分比')
plt.ylabel(u'每週消費的冰淇淋公升數')
plt.show()
效果圖:
本題目一共有三組特徵值:玩遊戲視訊所耗時間的百分比;每週消費的冰淇淋公升數;每年獲取的飛行常客里程數;
由於上述特徵描繪出來的屬性值不是特別的好,所以改進後選用了列1和列2;
2.2.3 準備資料:歸一化數值
理由:當資料的樣本特徵權重不一樣,就會導致某一個特徵權重的差距太大影響到整體的距離,因此要使用歸一化來將這種不同取值範圍的特徵值歸一化,將取值範圍處理為0到1,或者-1到1之間;使用如下公式可以講任意取值範圍的特徵值轉化為0到1區間內的值:
newValue = (oldValue - min ) / (max - min )
這裡的new和old都針對的是某一列裡的一個,而在這裡使用應該是列表整體的使用了公式,故得到的是一個列表型別的newValue;
def autoNorm(dataSet):#輸入為資料集資料
minVals = dataSet.min(0)#獲得資料每列的最小值,minval是個列表
maxVals = dataSet.max(0)#獲得資料每列的最大值,maxval是個列表
ranges = maxVals - minVals#獲得取值範圍
normDataSet = zeros(shape(dataSet)) #初始化歸一化資料集
m = dataSet.shape[0]#得到行
normDataSet = dataSet - tile(minVals,(m,1))
normDataSet = normDataSet/tile(ranges,(m,1)) #特徵值相除
return normDataSet,ranges , minVals#返回歸一化矩陣,取值範圍, 最小值
test測試:
# -*- coding: utf-8 -*-
import kNN
from numpy import *
import operator
datingDataMat,datingLabels = kNN.file2matrix('datingTestSet2.txt')
normMat , ranges , minval= kNN.autoNorm(datingDataMat)
print(normMat,'\n' ,ranges,'\n' , minval)
樣例輸出:
[[ 0.44832535 0.39805139 0.56233353]
[ 0.15873259 0.34195467 0.98724416]
[ 0.28542943 0.06892523 0.47449629]
...,
[ 0.29115949 0.50910294 0.51079493]
[ 0.52711097 0.43665451 0.4290048 ]
[ 0.47940793 0.3768091 0.78571804]] #歸一化矩陣
[ 9.12730000e+04 2.09193490e+01 1.69436100e+00] #取值範圍:max-min
[ 0. 0. 0.001156] #最小值
2-4:分類器針對約會網站的測試程式碼
先拿出10%的資料進行測試,我這個是5%
kNN,py
def datingClassTest():
hoRatio = 0.10 #測試資料佔總樣本的10%
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #樣本集,樣本標籤
normMat , ranges , minVals = autoNorm(datingDataMat) #歸一化處理樣本集,然後得到取值範圍和最小值
m = normMat.shape[0]#樣本集行數
numTestVecs = int(m*hoRatio) #測試樣本集的數量
errorCount = 0.0#初始化錯誤率
for i in range(numTestVecs):#對樣本集進行錯誤收集
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m], 3)#kNN
print("The classifier came back with : %d , the real answer is : %d" % (classifierResult,datingLabels[i]))
if(classifierResult!=datingLabels[i]):
errorCount+=1.0
print("the total error rate if :%f" % (errorCount/float(numTestVecs)))#計算錯誤率並輸出
test.py:
# -*- coding: utf-8 -*-
import kNN
from numpy import *
import operator
group , labels = kNN.createDataSet()
print kNN.datingClassTest()
輸出:
The classifier came back with : 1 , the real answer is : 1
The classifier came back with : 3 , the real answer is : 3
...
The classifier came back with : 1 , the real answer is : 1
The classifier came back with : 3 , the real answer is : 1
the total error rate if :0.050000
None
2-5 約會網站預測函式
最後一個主要是構建分類器,然後自己讀入資料給出結果。
def classfyPerson():
resultList = ['not at all' , 'in small doese ' , 'in large dose'] #分類器
precentTats = float(raw_input("precentage of time spent playint video games?")) #輸入資料
ffMiles = float(raw_input("frequent flier miles earned per year"))
iceCream = float(raw_input("liters of ice cream consumed per year?"))
datingDataMat , datingLabels = file2matrix('datingTestSet2.txt') #訓練集
normMat , ranges , minVals = autoNorm(datingDataMat) #進行訓練
inArr =array([ffMiles,precentTats,iceCream]) #把特徵加入矩陣
#4個輸入引數分別為:用於分類的輸入向量inX,輸入的訓練樣本集dataSet,標籤向量labels,選擇最近鄰居的數目k
classfierResult = classify0((inArr-minVals)/ranges,normMat,datingLabels,3) #歸一化處理矩陣,並且結果就是序列號-1就是對應
print "You will probably like this person : " , resultList[classfierResult - 1 ]
輸出結果:
You will probably like this person : in small doses
至此2.2:使用k-近鄰演算法改進約會網站配對效果結束