1. 程式人生 > >py2.7 : 《機器學習實戰》 k-近鄰演算法 11.19 更新完畢

py2.7 : 《機器學習實戰》 k-近鄰演算法 11.19 更新完畢

主要有幾個總結的:
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-近鄰演算法改進約會網站配對效果結束