python 實現 kNN 算法

kNN算法

1.準備帶有標籤的數據(需要轉換成矩陣格式)
2.提供一個待分類的數據
3.求待分類數據與每一個帶標籤的數據的”距離“
4.選取“距離”最小的k個帶標籤數據
5.求k個數據中出現頻率最高的數據得出分類結果

python 代碼實現

from numpy import *
import operator

#inX爲待分類數據,dataSet爲數據,labels爲標籤
def classify0(inX,dataSet,labels,k):
    '''求距離'''
    #將inX整體複製成爲(dataSet.shape[0],1)的矩陣
    #dataSet.shape[0]表示dataSet行數目
    diffMat=dataSet-tile(inX,(dataSet.shape[0],1))
    #每個元素平方
    squMat=diffMat**2
    #對每一行求和,axis=1表示變化範圍是列,即對行求和
    sumMat=squMat.sum(axis=1)
    #每個元素開平方
    distances=sumMat**0.5
    '''排序'''
    #對distances排序,得出從小到大排序的索引號(方便求標籤號)
    sortedIndexs=distances.argsort()
    #構建一個類,用作字典
    classCount={}
    for i in range(k):
        #構造字典,get(鍵,默認值)表示取字典對應鍵的值
        #沒有則取默認值,整體效果爲對k個最小標籤進行頻率統計
        classCount[labels[sortedIndexs[i]]=...
            classCount.get(labels[sortedIndexs[i],0)+1
    #排序,items返回(鍵,值)二元組
    #itmgetter(1)表示按照值排序
    #reverse=True表示降序排列
    sortedclassCount=sorted(classCount.items(),...
        key=operator.itmgetter(1),reverse=True)
    return sortedclassCount[0][0]

#數據測試
group=array([[1,1],[1,1.1],[0,0],[0,0.1]])
labels=['a','a','b','b']
classify0([0.0.2],group,labels,3)

實例:約會網站配對

1.數據讀取(截取一部分數據,在本文末尾,名爲datingTestSet2.txt)

'''
將前三列數據導入數據矩陣,將最後一列數據導入標籤列表
將這個函數加入kNN模塊,即上面那個函數
'''
def file2matrix(filename):
    fr=open(filename)
    arrayofLines=fr.readlines()
    #初始化0矩陣
    returnMat=zeros((len(arrayofLines),3))
    #初始化列表
    classLabel=[]
    index=0
    for line in arrayOLines:
        #將line兩端的'\n','\t'等空白字符消去
        line=line.strip()
        #以tab爲分割,將line分爲一個列表
        listFromLine=line.split('\t')
        #將前三列數據導入數據矩陣
        returnMat[index,:]=listFromLine[0:3]
        #將最後一列數據導入標籤列表
        classLabel.append(int(listFromLine[-1]))
        index+=1
    return returnMat,classLabel 

2.歸一化數值
由於要計算差值,而第一列數值由於遠大於另外兩列,對結果影響很大,
爲了消除這種影響,需要進行歸一化數值,將結果映射爲0-1的數字

'''
歸一化算法newValue=(oldValue-min)/(max-min)
'''
def autoNorm(dataSet):
    minVals=dataSet.min(0)
    maxVals=dataSet.max(0)
    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

3.算法測試,錯誤率計算
每發現一個錯誤,計數器+1,錯誤率=錯誤數/總測試數

def datingClassTest():
    hoRatio=0.1#選取測試數據的比例
    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,:],\
                          datingLabel[numTestVecs:m],3)
        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 is : %f"\
        %(errorCount/float(numTestVecs)))

4.程序運用

def classifyPerson():
    resultList=['not at all','in small doses','in large doses']
    percentTats=float(input("percentageof time spent playing video games?"))
    ffMiles=float(input("frequent flier miles earned per year?"))
    iceCream=float(input("liters of ice cream consumed per year?"))
    datingDataMat,datingLabels=file2matrix("datingTestSet2.txt")
    normMat,ranges,minVals=autoNorm(datingDataMat)
    inArr=array([ffMiles,percentTats,iceCream])
    classifierResult=classify0((inArr-minVals)/ranges,normMat,datingLabels,3)
    print("you will probably like this person:",resultList[classifierResult-1])

數據(簡化版,複製到txt即可使用)
(僅複製數據即可,第一列代表每年飛行數
第二列代表玩遊戲所佔百分比,第三列代表冰淇淋每週消費量
第四列表示好感程度,3最大)
40920 8.326976 0.953952 3
14488 7.153469 1.673904 2
26052 1.441871 0.805124 1
75136 13.147394 0.428964 1
38344 1.669788 0.134296 1
72993 10.141740 1.032955 1
35948 6.830792 1.213192 3
42666 13.276369 0.543880 3
67497 8.631577 0.749278 1
35483 12.273169 1.508053 3
50242 3.723498 0.831917 1
63275 8.385879 1.669485 1
5569 4.875435 0.728658 2
51052 4.680098 0.625224 1
77372 15.299570 0.331351 1
43673 1.889461 0.191283 1
61364 7.516754 1.269164 1
69673 14.239195 0.261333 1
15669 0.000000 1.250185 2
28488 10.528555 1.304844 3
6487 3.540265 0.822483 2
37708 2.991551 0.833920 1
22620 5.297865 0.638306 2
28782 6.593803 0.187108 3
19739 2.816760 1.686209 2
36788 12.458258 0.649617 3
5741 0.000000 1.656418 2
28567 9.968648 0.731232 3
6808 1.364838 0.640103 2
41611 0.230453 1.151996 1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章