按照《機器學習實戰》這書的內容來,稍微總結一下。
數據格式:
數據中的格式應該是 特徵1 特徵2 特徵3 ...類別,中間是tab鍵分割
1.讀文件。
將文件中的數據,特徵讀到numpy array數組之中,類似於矩陣。特徵讀到list當中。先讀,然後每一行進行處理,處理包括用\t進行分割,然後加到特徵數組
特徵加到特徵的list當中。
#讀文件,將文件讀到array裏。返回一個屬性的array[m,n]和一個標籤的list
def file2matrix(filename):
fr=open(filename)
arrayOLines=fr.readlines()
numberOfLines=len(arrayOLines)
returnMat=zeros((numberOfLines,3))
classLabelVector=[]
index=0
for line in arrayOLines:
line=line.strip()
listFromLine=line.split('\t')
returnMat[index,:]=listFromLine[0:3]
classLabelVector.append(int(listFromLine[-1]))
index+=1
return returnMat,classLabelVector
2.數據歸一化。
先求得整個矩陣的數據每列的最小值和最大值,然後就可以將(每個元素-最小)/(最大元素-最小元素)得到一個0~1之間的數據。
#數據歸一化
def autoNorm(dataSet):
#0代表是按列計算
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.KNN的核心算法。
將要預測的元素(假設是1*n)進行列向複製,得到m*n的矩陣,跟特徵矩陣形狀一樣。然後減去特徵矩陣,這樣得到待預測項與每一個樣本的差,然後對整個殘差矩陣進行求和,得到一個m*1的一個矩陣,每個元素代表待預測數據向量與樣本的距離。然後求根,再取最小的K個。得到了跟待測數據向量最相似的K個數據。最後統計這K個裏面的標籤值,哪個最多,就爲預測值。
'''main coding of classify,select top k of similarity
intX代表要預測的輸入向量,dataset是特徵矩陣(array類型),labels是標籤列表(list),k代表取前幾個相似'''
def classify0(inX,dataSet,labels,k):
dataSetsize=dataSet.shape[0]
#比如tile(A,n),功能是將數組A重複n次,構成一個新的數組,在這裏是將向量intX列方向進行復制。
diffMat=tile(inX,(dataSetsize,1))-dataSet
sqDiffMat=diffMat**2
#求每一行的殘差和
sqDistances=sqDiffMat.sum(axis=1)
distances=sqDistances**0.5
#求的索引的排序值。a=array([1,2,3,5,4,6])使用函數輸出array([0, 1, 2, 4, 3, 5])
sortedDistIndicies=distances.argsort()
#字典的存儲結果爲 {類別:數量}
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)
return sortedClassCount[0][0]
4.測試
讀文件,進行歸一化操作後,選取前面的numTestVecs個樣本爲測試集。對測試集中的數據,分別與訓練集中的數據進行KNN算法的預測。
#算法的基本測試
def datingClassTest():
#測試集的比例
hoRatio=0.10
datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
normMat,ranges,minVals=autoNorm(datingDataMat)
m=normMat.shape[0]
errorCount=0.0
numTestVecs=int(m*hoRatio)
for i in range(numTestVecs):
classifierResult=classify0(normMat[i,:],normMat[numTestVecs:m,:],\
datingLabels[numTestVecs:m],10)
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 errorrate is %f" % (errorCount/float(numTestVecs))