KNN算法

KNN算法,是比较常见而且也易于实现的机械学习分类算法。其从字面上简单的可以理解为,周围离预测点最近的K各点中大多数点的属性就为预测点的属性。此处,可以看出这样三个关键点。第一,少数服从多数;第二,知道周围点的属性,因此需要储存属性,这点便导致了KNN算法需要比较大的空间复杂度;第三,最近的K各点。如何判断最近?便以此,引入距离的概念。距离在解析几何中定义(空间两点或者两向量之间的距离)  d = \sqrt{\sum_{i}((xi-yi))^{^{2}})}, 线性代数中的矩阵的距离; 其次还有曼哈顿距离(棋盘距离)d(i,j)=|X1-X2|+|Y1-Y2|等等。

那么问题来了,KNN算法中距离的定义是否会对计算结果有影响了?

自然是有影响的,一般地连续性数据的时候采用欧式距离;非连续性的时候采用曼哈顿或者汉明距离。所以有时候需要对距离度量进行优化从而提高预测的精度,如大边缘最近邻法或者近邻成分分析法。但是本人认为距离的选取,对KNN算法的精度影响不太大,而更为重要的是K值的选取。显然K值的选择并不是一拍脑门就直接想出的。K值的选择过程中需要采用交叉验证来降低误差。

另外,由于采用的是少数服从多数的方法,显然样本的不均衡性会对预测结果产生一定的影响。此处,我们便引入权重的概念,权重的概念体现在两个方面,第一,数据量(如A类本身数据量极大,因此可以考虑按照比例降低);第二,距离。(显然距离预测点越近的点,其在预测中权重就应该越大,选1/dis)。

接下来,我们用一个示例代码来说明。

调用sklearn来实现

from sklearn import neighbors
from sklearn import datasets

knn = neighbors.KNeighborsClassifier()

iris = datasets.load_iris()

print (iris)

knn.fit(iris.data, iris.target)
predictedLabel = knn.predict([[0.1,0.2, 0.3, 0.4]])

print(predictedLabel)

基本编程来实现

import csv
##自行下载iris.data.txt 或者csv 二者可以直接转化
import random
import math
import operator #操作文件

#首先载入数据
def loadDataset(filename, split, trainingSet = [], testSet = []):
    with open(filename, 'r')as csvfile:
        lines =csv.reader(csvfile)
        dataset = list(lines)
        for x in range(len(dataset) - 1):
            for y in range(4):
                dataset[x][y] = float(dataset[x][y])
                if random.random() < split:
                    trainingSet.append(dataset[x])
                else:
                    testSet.append(dataset[x])
#计算距离
def euclideanDistance(instance1, instance2, length):
    distance = 0
    for x in range(length):
        distance += pow((instance1[x] - instance2[x]), 2)
    return math.sqrt(distance)
# 选择k个最近的值
def getNeighbors(trainingSet, testInstance, k):
    distance = []
    length = len(testInstance) -1
    for x in range(len(trainingSet)):
        dist = euclideanDistance(testInstance, trainingSet[x], length)##计算每个训练集到实数集的距离
        distance.append((trainingSet[x], dist))
    distance.sort(key = operator.itemgetter(1))
    neighbors = []
    for x in range(k):
        neighbors.append(distance[x][0])
    return neighbors

#投票排序
def getResponse(neighbors):
    classVotes = {}
    for x in range(len(neighbors)):
        response = neighbors[x][-1]
        if response in classVotes:
            classVotes[response] += 1
        else:
            classVotes[response] = 1
    sortedVotes = sorted(classVotes.items(), key = operator.itemgetter(1), reverse= True)
    return sortedVotes[0][0]
###准确性预测
def getAccuracy(testSet, predictions):
    correct = 0
    for x in range(len(testSet)):
        if testSet[x][-1] == predictions[x]:
            correct += 1
    return (correct / float(len(testSet))) * 100

def main():
    trainingSet = []
    testSet = []
    split = 0.67
    loadDataset(r'D:\knn\iris.data.csv', split, trainingSet, testSet)
    print('Train set' + repr(len(trainingSet)))
    print('Test Set' + repr(len(testSet)))

    predictions = []
    k = 3

    for x in range(len(testSet)):
        neighbors = getNeighbors(trainingSet, testSet[x], k)
        result = getResponse(neighbors)
        predictions.append(result)
        print('prediction = ' + repr(result) + ', actual=' + repr(testSet[x][-1]))
    accuracy = getAccuracy(testSet, predictions)
    print('accuracy:' + repr(accuracy) + '%')

if __name__ == '__main__':
    main()












还有三个问题需要测试;一个是K值的选取,一个是距离的定义问题,另外一个是分割值split.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

米汤馒头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值