【机器学习】KNN基本介绍+代码实现

1.基本概念

k近邻算法:通过测量待预测点和已知点的特征值之间的距离,选取前k个距离近的,根据多数表决的方法来分类。

训练过程:无训练过程。

测试过程:根据距离来分类。

k越小,模型越复杂,越容易过拟合。

需要对各个属性(特征)进行归一化,防止数值较大的属性对分类器的影响过大。

2. 优缺点

优点:精度高,异常值不敏感,对输入格式无要求。

缺点:时间空间复杂度高。无法给出数据的基础结构信息,无法分析数据特征。

适用数据范围:标量和数值型。

3. 常用距离

样本一:x = (x1, x2, ..., xn)

样本二:y = (y1, y2, ..., yn)

欧氏距离: L(x,y) = \sqrt{\sum (x_i - y_i)^2}

曼哈顿距离:L(x,y) = \sum |x_i - y_i|

距离最大值:L(x,y) =max |x_i - y_i|

4. 代码实现

参考:《机器学习实战》

源码地址以及数据:https://github.com/JieruZhang/MachineLearninginAction_src

手写python KNN:

from numpy import *
import operator
import matplotlib
import matplotlib.pyplot as plt

#处理文档
def file2mat(file):
    f = open(file)
    lines = f.readlines()
    nums = len(lines)
    mat = zeros((nums,3))
    classes = []
    index = 0
    for line in lines:
        line = line.strip()
        line = line.split('\t')
        mat[index,:] = line[0:3]
        classes.append(int(line[-1]))
        index += 1
    return mat, classes

#归一化:由于各个种类特征的数字差异大,例如属性1是百级的,属性2是小数级的,则属性1对距离的影响大。为了使各个特征之间重要性相同,需要归一化。
#归一化方法:new = (old - 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))
    return normDataSet, ranges, minVals

#分类,计算距离
def classifyKNN(test, dataSet, labels, k):
    size = dataSet.shape[0]
    #计算距离
    distance = (((tile(test, (size,1)) - dataSet)**2).sum(axis=1))**0.5
    #距离由短到长排序, 将对应的index存入列表
    sortIndices = distance.argsort()
    #找到前k个最近的样本对应的类别
    classCount = {}
    for i in range(k):
        label = labels[sortIndices[i]]
        #get() 函数返回指定键的值,如果值不在字典中返回默认值。
        classCount[label] = classCount.get(label,0) + 1
    #将前k个classCount按照value的大小排序
    sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1), reverse=True)
    #返回最大的标签数目对应的标签
    return sortedClassCount[0][0]

#测试
def test():
    ratio = 0.1
    mat, labels = file2mat('datingTestSet.txt')
    normMat, ranges, minVals = autoNorm(mat)
    m = normMat.shape[0]
    numTest = int(m*ratio)
    errorCount = 0.0
    for i in range(numTest):
        res = classifyKNN(normMat[i,:], normMat[numTest:m,:], labels[numTest:m],3)
        if res != labels[i]:
            errorCount += 1
    print('error rate: %f' % (errorCount/float(numTest)))

datingMat, datingLabels = file2mat('datingTestSet.txt')
normMat, ranges, minVals = autoNorm(datingMat)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingMat[:,1], datingMat[:,2], 15.0*array(datingLabels), 15.0*array(datingLabels))
plt.show()

test()

sklearn 实现:

from sklearn.neighbors import KNeighborsClassifier
import numpy as np
def sklearnKNN():
    ratio = 0.1
    mat, labels = file2mat('datingTestSet.txt')
    normMat, ranges, minVals = autoNorm(mat)
    m = normMat.shape[0]
    numTest = int(m*ratio)
    train_mat = normMat[numTest:m,:]
    test_mat = normMat[0:numTest,:]
    train_labels = labels[numTest:m]
    test_labels = labels[0:numTest]
    knn = KNeighborsClassifier(n_neighbors = 3)
    knn.fit(train_mat, train_labels)
    print('error rate is : ', 1 - knn.score(test_mat, test_labels))

sklearnKNN()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章