【Python】分类算法KNN

KNN算法原理

k最近邻(k-Nearest Neighbor)算法是比较简单的机器学习算法。它采用测量不同特征值之间的距离方法进行分类。它的思想很简单:如果一个样本在特征空间中的k个最近邻(最相似)的样本中的大多数都属于某一个类别,则该样本也属于这个类别。第一个字母k可以小写,表示外部定义的近邻数量。这句话不难理解,但有点拗口,下面通过一个实例来讲解一下。

首先我们准备一个数据集,这个数据集很简单,是由二维空间上的4个点构成的一个矩阵,如下表

分类XY
A1.01.1
A1.01.0
B00
B00.1

其中前两个点构成一个类别A,后两个点构成一个类别B。

我们用Python把这4个点在坐标系中绘制出来。
(1)产生数据集的函数代码如下。

# coding:utf-8

import sys
import os
import operator
import importlib
from numpy import *
import numpy as np
import matplotlib.pyplot as plt

importlib.reload(sys)
# sys.setdefaultencoding('utf-8')


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


dataSet, labels = createDataSet()
fig = plt.figure()
ax = fig.add_subplot(111)
indx = 0
for point in dataSet:
    if labels[indx] == 'A':
        ax.scatter(point[0], point[1], c='blue',
                   marker='o', linewidths=0, s=300)
        plt.annotate(
            "("+str(point[0])+","+str(point[1])+")", xy=(point[0], point[1]))
    else:
        ax.scatter(point[0], point[1], c='red',
                   marker='^', linewidths=0, s=300)
        plt.annotate(
            "("+str(point[0])+','+str(point[1])+')', xy=(point[0], point[1]))
    indx += 1
plt.show()

绘制的图形如图所示,从图形中可以清晰地看到由4个点构成的训练集。该训练集被分为两个类别:A类——蓝色圆圈,B类——红色三角形。因为红色区域内的点距比它们到蓝色区域内的点距要小得多,这种分类也很自然。
在这里插入图片描述
下面我们给出测试集,只有一个点,我们把它加入到刚才的矩阵中去,如表所示。

分类XY
A1.01.1
A1.01.0
B00
B00.1
0.20.2

我们想知道给出的这个测试集应该属于哪个分类。我认为最简单的方法还是画图,我们把新加入的点加入图中。

# coding:utf-8

import sys
import os
import operator
import importlib
from numpy import *
import numpy as np
import matplotlib.pyplot as plt

importlib.reload(sys)
# sys.setdefaultencoding('utf-8')


def createDataSet():
    group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1], [0.2, 0.2]])
    labels = ['A', 'A', 'B', 'B', 'C']
    return group, labels


dataSet, labels = createDataSet()
fig = plt.figure()
ax = fig.add_subplot(111)
indx = 0
for point in dataSet:
    if labels[indx] == 'A':
        ax.scatter(point[0], point[1], c='blue',
                   marker='o', linewidths=0, s=300)
        plt.annotate(
            "("+str(point[0])+","+str(point[1])+")", xy=(point[0], point[1]))
    else:
        ax.scatter(point[0], point[1], c='red',
                   marker='^', linewidths=0, s=300)
        plt.annotate(
            "("+str(point[0])+','+str(point[1])+')', xy=(point[0], point[1]))
    indx += 1
plt.show()

很清晰,从距离上看,它更接近红色三角形的范围,应该归入B类,如图2.10所示。这就是kNN算法的基本原理。
在这里插入图片描述
由此可见,kNN算法应由以下步骤构成。

第一阶段:确定k值(就是指最近邻居的个数)。一般是一个奇数,因为测试样本有限,故取k值为3。

第二阶段:确定距离度量公式。文本分类一般使用夹角余弦,得出待分类数据点和所有已知类别的样本点,从中选择距离最近的k个样本。

夹角余弦:
c o s θ = A B ∣ A ∣ ∣ B ∣ cos\theta=\frac{AB}{|A||B|} cosθ=ABAB
第三阶段:统计这k个样本点中各个类别的数量。如图2.10所示,如果我们选定k值为3,则B类样本(三角形)有2个,A类样本(圆形)有1个,那么我们就把这个方形数据点定为B类;即,根据k个样本中数量最多的样本是什么类别,我们就把这个数据点定为什么类别。

KNN算法的Python实现

导入依赖库,进行数据初始化

# coding:utf-8

import sys,os,operator,importlib
from numpy import *
import numpy as np
from Nbayes_lib import *

importlib.reload(sys)
# sys.setdefaultencoding('utf-8')
k=3

实现夹角余弦的距离公式

def cosdist(vector1,vector2):
    return dot(vector1,vector2)/(linalg.norm(vector1)*linalg.norm(vector2))

KNN实现分类机

def classify(testdata, trainSet, listClasses, k):
    dataSetSize = trainSet.shape[0]
    distances = array(zeros(dataSetSize))
    for indx in range(dataSetSize):
        distances[indx] = cosdist(testdata, trainSet[indx])
    sortedDistIndicies = argsort(-distances)
    classCount = {}
    for i in range(k):
        voteIlabel = listClasses[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel, 0)+1
        sortedClassCount = sorted(
            classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

评估分类结果

最后使用KNN算法实现文本分类

dataSet, listClasses = loadDataSet()
nb = NBayes()
nb.train_set(dataSet, listClasses)
print(classify(nb.tf[3], nb.tf, listClasses, k))

输出结果如下

1

准确率达100%

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值