python 机器学习 sklearn - k近邻 算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36336522/article/details/84702847

下面我会介绍  在sklearn 的knn-api函数 ,然后  k近邻的算法步骤  ,使用  k近邻的思想过程  ,然后举几个使用k近邻算法的例子

  • API 使用

class sklearn.neighbors.KNeighborsClassifier(n_neighbors=5weights=’uniform’algorithm=’auto’leaf_size=30p=2metric=’minkowski’metric_params=Nonen_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)但是如果我们需要大体了解哪些模型可以干啥,他们大体的算法流程是啥。

算法描述:

  1. 假设有一个带有标签的样本数据集(训练样本集),其中包含每条数据与所属分类的对应关系。
  2. 输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较。
    1. 计算新数据与样本数据集中每条数据的距离。
    2. 对求得的所有距离进行排序(从小到大,越小表示越相似)。
    3. 取前 k (k 一般小于等于 20 )个样本数据对应的分类标签。
  3. 求 k 个数据中出现次数最多的分类标签作为新数据的分类。

使用该模型的考虑过程:

收集数据:任何方法

准备数据:距离计算所需要的数值,最好是结构化的数据格式

分析数据:任何方法

训练算法:此步骤不适用于 k-近邻算法

测试算法:计算错误率

使用算法:输入样本数据和结构化的输出结果,然后运行 k-近邻算法判断输入数据分类属于哪个分类,最后对计算出的分类执行后续处理

优点:精度高、对异常值不敏感、无数据输入假定

缺点:计算复杂度高、空间复杂度高 适用数据范围:数值型和标称型

KNN的python实现 和一个手写例子-- 有兴趣的可以看看,看看能不能在此基础上进行修改

from numpy import *
import operator
from os import listdir

def 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, labels

def 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 returnVect

def 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个人(我个人理解哈....)

猜你喜欢

转载自blog.csdn.net/qq_36336522/article/details/84702847