1. 程式人生 > >機器學習實戰精讀--------K-近鄰算法

機器學習實戰精讀--------K-近鄰算法

機器學習 knn算法 k-近鄰算法

對機器學習實戰的課本和代碼進行精讀,幫助自己進步。

#coding:utf-8
from numpy import *
import operator		#運算符模塊
from os import listdir  #os.listdir() 方法用於返回指定的文件夾包含的文件或文件夾的名字的列表。這個列表以字母順序。 它不包括 ‘.‘ 和‘..‘ 即使它在文件夾中。


#創建數據集和標簽
def createDataSet():
    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])  #數據集
    #python中的list是python的內置數據類型,list中的數據類不必相同的,而array的中的類型必須全部相同。在list中的數據類型保存的是數據的存放的地址,簡單的說就是指針,並非數據,這樣保存一個list就太麻煩了,例如list1=[1,2,3,‘a‘]需要4個指針和四個數據,增加了存儲和消耗cpu。
    labels = [‘A‘,‘B‘,‘C‘,‘D‘]    #標簽
    return group,labels

#實施KNN算法    
#歐氏距離公式:歐幾裏得度量(euclidean metric)(也稱歐氏距離)是一個通常采用的距離定義,指在m維空間中兩個點之間的真實距離,或者向量的自然長度(即該點到原點的距離)。在二維和三維空間中的歐氏距離就是兩點之間的實際距離
def classify0(inX, dataSet, labels, k):
	#inX:用於分類的輸入向量; dataSet:輸入的訓練樣本集; labels:標簽向量; k:選擇最近鄰居的數目
    dataSetSize = dataSet.shape[0]   
	#shape函數它的功能是讀取矩陣的長度,比如shape[0]就是讀取矩陣第一維度的長度。它的輸入參數可以使一個整數表示維度,也可以是一個矩陣。
    diffMat = tile(inX, (dataSetSize,1)) - dataSet 
	#他的功能是重復某個數組。比如tile(A,n),功能是將數組A重復n次,構成一個新的數組
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
	 #平時用的sum應該是默認的axis=0 就是普通的相加 ,而當加入axis=1以後就是將一個矩陣的每一行向量相加
    distances = sqDistances**0.5
    sortedDistIndicies = distances.argsort()   
    #sort函數只定義在list中,sorted函數對於所有的可叠代序列都可以定義.
	#argsort()函數,是numpy庫中的函數,返回的是數組值從小到大的索引值.
    classCount={}          
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)                              
	#key:用列表元素的某個屬性和函數進行作為關鍵字,有默認值,叠代集合中的一項
	#reverse:排序規則. reverse = True 或者 reverse = False,有默認值。返回值:是一個經過排序的可叠代類型
    #operator模塊提供的itemgetter函數用於獲取對象的哪些維的數據,參數為一些序號(即需要獲取的數據在對象中的序號)
    return sortedClassCount[0][0]




#step01 :因為直接用的人家的文件,所以我們這一步沒有收集數據,我們可以用python爬蟲進行海裏數據收集


#step02 : 準備數據:從文本文件中解析數據,得到距離計算所需要的數值
def file2matrix(filename):
    fr = open(filename)
	#打開文件,賦值給fr
    numberOfLines = len(fr.readlines())  
    #get the number of lines in the file
    returnMat = zeros((numberOfLines,3))       
	#創建給定類型的矩陣,並初始化為0,另一維度設置為固定數值3
    classLabelVector = []   
    fr.close()   
	#有打開就要有關閉                   
    fr = open(filename)
    index = 0
    for line in fr.readlines():                
	#.readline() 和 .readlines() 之間的差異是後者一次讀取整個文件,象 .read() 一樣。.readlines() 自動將文件內容分析成一個行的列表,該列表可以由 Python 的 for ... in ... 結構進行處理。另一方面,.readline() 每次只讀取一行,通常比 .readlines() 慢得多。僅當沒有足夠內存可以一次讀取整個文件時,才應該使用 .readline()
        line = line.strip()                     
		#截取掉所有的回車字符。
        listFromLine = line.split(‘\t‘)    
		#使用tab字符\t將上一步得到的整行數據分割成一個列表
        returnMat[index,:] = listFromLine[0:3]
		#選取前三個元素,將它們存儲到特征矩陣中
        classLabelVector.append(int(listFromLine[-1]))
		#將列表中最後一列存儲到向量classLabelVector中
        index += 1
	fr.close()
    return returnMat,classLabelVector




#step02:   準備數據:歸一化數值
#在處理這種不同取值範圍的特征值時,我們通常采用的方法是將數值歸一化 
#newvalue = (oldValue-min)/(max-min)  將任意取值範圍的特征值轉化為0到1區間的值
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))   #element wise divide
    return normDataSet, ranges, minVals


#step03 :分析數據:使用Matplotlib創建散點圖



#step04: 測試算法:作為完整程序驗證分類器
def datingClassTest():
    hoRatio = 0.50      #hold out 10%
    datingDataMat,datingLabels = file2matrix(‘./datingTestSet2.txt‘)       #load data setfrom file
    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)
        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))
    print errorCount

#step05  使用算法:構建完整可用系統
def classifyPerson():
	resultList = [‘not at all‘,‘in small doses‘,‘in large doses‘]
	percentTats = float(raw_input("percentage of time spent palying video games?"))
	ffMiles = float(raw_input("freguent filer miles earned per year?"))
	iceCream = float(raw_input("liters of ice cream consumed per year?"))
	datingDataMat,datingLabels = file2matrix(‘./datingTestSet2.txt‘)
	normMat,ranges,minVales = autoNorm(datingDataMat)
	inArr = array([ffMiles,percentTats,iceCream])
	classifierResult = classify0((inArr - minVales)/ranges,normMat,datingLabels,3)
	print "you will probably like this person:",resultList[classifierResult -1]

重點:

01:K-近鄰算法底層算法是歐式距離公式,計算m維空間中兩點之間的真實距離,或者向量的自然長度。

02:歸一化數值:

newvalue = (oldValue-min)/(max-min)  將任意取值範圍的特征值轉化為0到1區間的值

這個思想很重要。


體會:在我看來,整個機器學習從數據采集到最終的程序,整個流程特別重要,算法是核心,處理幹擾項的時候,我們用到了歸一化。

本文出自 “付煒超” 博客,謝絕轉載!

機器學習實戰精讀--------K-近鄰算法