K-近邻算法简介
K-近邻算法是机器学习中比较简单易懂的一个算法,其原理是:存在一个训练样本数据集,并且样本中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系,这时如果我们输入一个没有标签的新数据后,将新数据的每个特征与样本集中的数据对应的特征进行比较计算,然后算法提取样本集中特征最相似的数据(最近邻)的分类标签。一般来说,我们只选择样本集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数,最后,选择k个最相似的数据中出现次数最多的分类,作为新数据的分类。
k近邻算法的一般流程:
(1)收集数据:可以采用公开的数据源
(2)准备数据:计算距离所需要的数值
(3)分析数据:剔除垃圾信息
(4)测试算法:计算错误率
(5)使用算法:运用在实际中,对实际情况进行预测
k-近邻算法应用
我们将使用一个乳腺癌数据集作为一个简单的示例来演示k-近邻算法,数据集里面包含breast-cancer-wisconsin.data 和 breast-cancer-wisconsin.names,breast-cancer-wisconsin.test三个文件,从breast-cancer-wisconsin.names里面我们可以了解到数据集的属性,这些属性包含乳腺癌的如下特征:
(id,clump_thickness,uniform_cell_size,uniform_cell_shape,marginal_adhesion,single_epi_cell_size,bare_nuclei,bland_chromation,normal_nucleoli,mitoses,Class),对应breast-cancer-wisconsin.data里的每一行数据,其中id是每例乳腺癌的唯一编号,class是分类,表示良性或恶性,第三个文件breast-cancer-wisconsin.test作为测试集,以验证k-近邻算法的有效性。
from numpy import *
import operator
from os import listdir
def run_main():
exampleMat,examplelabelVec = loadExampleDataSet()
exampleNormalMat = autoNormal(exampleMat)
testNormalMat =loadTestDataSet('breast-cancer-wisconsin.test')
testRow =shape(testNormalMat)[0]
for index in range(testRow)
knn(testNormalMat[index],exampleNormalMat ,examplelabelVec ,5)
def kNN(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]
diffMat = tile(inX, (dataSetSize,1)) - dataSet
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.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]
def loadExampleDataSet():
fr = open('breast-cancer-wisconsin.data')
lineObject = fr.readlines()
lineNum = len(lineObject)
returnMat =zeros((lineNum,9))
returnClassLabelVec = []
listFromLine = []
index =0
for line in lineObject:
line =line.strip()
line =line.replace('?','9999')
listFromLine =line.split(',')
returnMat[index,0:9] =listFromLine[1:10]
returnClassLabelVec.append(int(listFromLine[10]))
index +=1
#print returnMat
return returnMat,returnClassLabelVec
def loadTestDataSet():
fr = open('breast-cancer-wisconsin.test')
lineObject = fr.readlines()
lineNum = len(lineObject)
returnMat =zeros((lineNum,9))
returnClassLabelVec = []
listFromLine = []
index =0
for line in lineObject:
line =line.strip()
line =line.replace('?','9999')
listFromLine =line.split(',')
returnMat[index,0:9] =listFromLine[1:10]
index +=1
#print returnMat
return returnMat
def autoNormal(myDataSet):
minVec = myDataSet.min(0)
maxVec = myDataSet.max(0)
rcNum = shape(myDataSet)
normalMat =zeros(rcNum)
minMat =tile(minVec,(rcNum[0],1))
maxMat =tile(maxVec,(rcNum[0],1));
normalMat =myDataSet -minMat
normalMat =normalMat /(maxMat-minMat)
print normalMat
return normalMat
if __name__=='__main__':
run_main()