下面我会介绍 在sklearn 的knn-api函数 ,然后 k近邻的算法步骤 ,使用 k近邻的思想过程 ,然后举几个使用k近邻算法的例子
- API 使用
class
sklearn.neighbors.
KNeighborsClassifier
(n_neighbors=5, weights=’uniform’, algorithm=’auto’, leaf_size=30, p=2, metric=’minkowski’, metric_params=None, n_jobs=None, **kwargs)在以上算法的API中,基本上只有一个n_neighbors,weights,algorithm, p需要我们去传参;我们如果要修改这个方法,大概也是修改weights,和 algorithm;学过acm的基本上也知道kd-tree,我们这里的alg可以选择kd-tree,换句话说如果你有更好的划分方法也就可以提高kNN的效率了。
例子:
X = [[0], [1], [2], [3]] # 准备数据(数据一般有两个属性X,Y;分别代表一个物体的属性) y = [0, 0, 1, 1] # 和一个物体的分类结果(对于监督算法来说是必要的) from sklearn.neighbors import KNeighborsClassifier neigh = KNeighborsClassifier(n_neighbors=3) # 创建一个KNN的模型 neigh.fit(X, y) # 把数据传到模型中 print(neigh.predict([[1.1]])) # 预测[1.1]这个数据属于哪 print(neigh.predict_proba([[0.9]])) # 分类到类别的可能性,比如对于二分类问题 A类可能性0.66,B类0.33
- API解释
从上面的例子基本可以看出KNN的sklearn使用包括四个步骤,准备数据,准备模型,将数据传入模型,分析结果;其实大部分的sklearn - API 都是这样使用,使用api的好处是我们不用关注其内部实现,难点就在于数据的完美表示(matplotlib)但是如果我们需要大体了解哪些模型可以干啥,他们大体的算法流程是啥。
算法描述:
- 假设有一个带有标签的样本数据集(训练样本集),其中包含每条数据与所属分类的对应关系。
- 输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较。
- 计算新数据与样本数据集中每条数据的距离。
- 对求得的所有距离进行排序(从小到大,越小表示越相似)。
- 取前 k (k 一般小于等于 20 )个样本数据对应的分类标签。
- 求 k 个数据中出现次数最多的分类标签作为新数据的分类。
使用该模型的考虑过程:
收集数据:任何方法
准备数据:距离计算所需要的数值,最好是结构化的数据格式
分析数据:任何方法
训练算法:此步骤不适用于 k-近邻算法
扫描二维码关注公众号,回复: 4366773 查看本文章测试算法:计算错误率
使用算法:输入样本数据和结构化的输出结果,然后运行 k-近邻算法判断输入数据分类属于哪个分类,最后对计算出的分类执行后续处理
优点:精度高、对异常值不敏感、无数据输入假定
缺点:计算复杂度高、空间复杂度高 适用数据范围:数值型和标称型
KNN的python实现 和一个手写例子-- 有兴趣的可以看看,看看能不能在此基础上进行修改
from numpy import *
import operator
from os import listdirdef classify0(inX, dataSet, labels, k): #用于分类 [ 分类的向量,训练集,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 #选择距离最小的k个点
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]def createDataSet():
group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels = ['A','A','B','B']
return group, labelsdef file2matrix(filename): #用于将txt文件内的数据转换成矩阵
fr = open(filename)
numberOfLines = len(fr.readlines()) #获得文件的行数
returnMat = zeros((numberOfLines,3)) #准备要返回的numpy矩阵
classLabelVector = [] #准备labels
fr = open(filename)
index = 0
for line in fr.readlines():
line = line.strip()
listFromLine = line.split('\t')
returnMat[index,:] = listFromLine[0:3]
classLabelVector.append(int(listFromLine[-1]))
index += 1
return returnMat,classLabelVector
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
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
def img2vector(filename):
returnVect = zeros((1,1024))
fr = open(filename)
for i in range(32):
lineStr = fr.readline()
for j in range(32):
returnVect[0,32*i+j] = int(lineStr[j])
return returnVectdef handwritingClassTest():
hwLabels = []
trainingFileList = listdir('trainingDigits') #load the training set
m = len(trainingFileList)
trainingMat = zeros((m,1024))
for i in range(m):
fileNameStr = trainingFileList[i]
fileStr = fileNameStr.split('.')[0] #take off .txt
classNumStr = int(fileStr.split('_')[0])
hwLabels.append(classNumStr)
trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr)
testFileList = listdir('testDigits') #iterate through the test set
errorCount = 0.0
mTest = len(testFileList)
for i in range(mTest):
fileNameStr = testFileList[i]
fileStr = fileNameStr.split('.')[0] #take off .txt
classNumStr = int(fileStr.split('_')[0])
vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)
classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)
print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr)
if (classifierResult != classNumStr): errorCount += 1.0
print "\nthe total number of errors is: %d" % errorCount
print "\nthe total error rate is: %f" % (errorCount/float(mTest))
课后练习:
将上述的手写例子实现用sklearn写出来
SOME MORE
其实在sklearn的最近邻这样一个模块除了介绍了
KNeighborsRegressor还介绍了RadiusNeighborsRegressor,而且这两种也有对应的回归方法;如果数据不是均匀采样的我们采用RadiusNeighborsRegressor方法,什么叫不均匀采样呢,我举个例子,就是统计全国男士的平均身高来判断你是哪个省的,但是呢你在江苏只采样了500个人,在上海采集了5000个人(我个人理解哈....)