一步步教你轻松学KNN模型算法

article/2025/11/10 22:03:03
一步步教你轻松学KNN模型算法
( 白宁超 2018年7月24日08:52:16 )

导读:机器学习算法中KNN属于比较简单的典型算法,既可以做聚类又可以做分类使用。本文通过一个模拟的实际案例进行讲解。整个流程包括:采集数据、数据格式化处理、数据分析、数据归一化处理、构造算法模型、评估算法模型和算法模型的应用。(本文原创,转载必须注明出处: 一步步教你轻松学KNN模型算法)

目录

1 机器学习:一步步教你轻松学KNN模型算法

2 机器学习:一步步教你轻松学决策树算法

3 机器学习:一步步教你轻松学朴素贝叶斯模型算法理论篇1 

4 机器学习:一步步教你轻松学朴素贝叶斯模型实现篇2 

5 机器学习:一步步教你轻松学朴素贝叶斯模型算法Sklearn深度篇3

6 机器学习:一步步教你轻松学逻辑回归模型算法

7 机器学习:一步步教你轻松学K-means聚类算法

8 机器学习:一步步教你轻松学关联规则Apriori算法

9 机器学习: 一步步教你轻松学支持向量机SVM算法之理论篇1

10 机器学习: 一步步教你轻松学支持向量机SVM算法之案例篇2

11 机器学习: 一步步教你轻松学主成分分析PCA降维算法

12 机器学习: 一步步教你轻松学支持向量机SVM降维算法

更多文章请点击这里>>

1 理论介绍

什么是KNN?

       k-近邻(kNN,k-NearestNeighbor)算法是一种基本分类与回归方法,我们这里只讨论分类问题中的 k-近邻算法。k-近邻算法的输入为实例的特征向量,对应于特征空间的点;输出为实例的类别,可以取多类。k-邻算法假设给定一个训练数据集,其中的实例类别已定。分类时,对新的实例,根据其 k 个最近邻的训练实例的类别,通过多数表决等方式进行预测。因此,k近邻算法不具有显式的学习过程即属于有监督学习范畴。k近邻算法实际上利用训练数据集对特征向量空间进行划分,并作为其分类的“模型”。k值的选择、距离度量以及分类决策规则是k近邻算法的三个基本要素。

KNN算法思想

1 计算已知类别中数据集的点与当前点的距离。[即计算所有样本点跟待分类样本之间的距离]
2 按照距离递增次序排序。[计算完样本距离进行排序]
3 选取与当前点距离最小的k个点。[选取距离样本最近的k个点]
4 确定前k个点所在类别的出现频率。[针对这k个点,统计下各个类别分别有多少个]
5 返回前k个点出现频率最高的类别作为当前点的预测分类。[k个点中某个类别最多,就将样本划归改点]

KNN工作原理

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

KNN算法流程

1 搜集数据:数据采集过程,其分为非结构化数据,半结构化数据和数据化数据。诸如:网络爬取,数据库,文件等。
2 准备数据:格式化处理,对不同类别的数据进行统一的格式化处理。诸如:将pdf,word,excel,sql等等统一转化为txt文本。
3 分析数据:主要看看数据特点,有没有缺失值,数据连续性还是离散型,进而选择不同模型。诸如:可视化数据分析
4 训练数据:不适用于KNN,但是在其他一些监督学习中会经常遇到,诸如:朴素贝叶斯分类等。
5 测试算法:评价指标,如计算错误率,准确率,召回率,F度量值等。
6 应用算法:针对完善的模型进行封装重构,然后进行实际应用。

KNN优缺点

优点:精度高、对异常值不敏感、无数据输入假定
缺点:计算复杂度高、空间复杂度好
适用数据范围:数值型和标称型

2 KNN算法实现与分析

2.1 数据准备

创建模拟数据集

描述:现在你来了一个新的任务,任务其实非常简单,就是根据吃冰淇淋和喝水的数量判断成都天气冷热程度。你现在要做的就是去成都春熙路街头采访记录一些游客吃了多少冰淇淋,又喝了几瓶水,他觉得成都天气怎么样(这里只考虑二分类问题,假设只有‘非常热’和‘一般热’)。其中特征向量包括两个分别是冰激凌数t1和喝水数t2,标签类别分别是非常热A和一般热B。

现在我们开始行动,随机采访4个游客(暂时不考虑样本数量问题),询问每个游客吃多少冰淇淋和喝多少水(两个整型的特征向量,不考虑特征重要程度),并记录下他们口中的成都天气感受(非常热A与一般热B)。然后通过采访数据训练一个KNN分类器,新的游客只需要说出特征向量自动判别成都天气冷热程度。创建模拟数据集代码如下:

'''KNN创建数据源,返回数据集和标签'''
def create_dataset():group = array(random.randint(0,10,size=(4,2))) # 数据集labels = ['A','A','B','B'] # 标签return group,labels

运行查看数据集的特征向量和分类标签:

'''1 KNN模拟数据分类算法'''
dataset,labels = create_dataset()
print('特征集:\n'+str(dataset))
print('标签集:\n'+str(labels))

运行结果:

特征集:
[[8 4][7 1][1 4][3 0]]
标签集:
['A', 'A', 'B', 'B']

分析解读:

本段代码没有实际意义,只是帮助读者理解特征向量和分类标签。可以这么理解,A代表非常热,B代表一般热,属性1代表吃冰淇淋数量,属性2代表喝水的数量。那么样本数据可以解读为:

游客     冰淇淋    喝水    冷热程度        判断描述小王      8       4       A           小王吃了8个冰淇淋喝了4瓶水,成都天气非常热小张      7       1       A           小张吃了7个冰淇淋喝了1瓶水,成都天气非常热小李      1       4       B           小王吃了1个冰淇淋喝了4瓶水,成都天气一般热小赵      3       0       B           小王吃了3个冰淇淋喝了0瓶水,成都天气一般热

思考:

计算机是不能直接处理自然语言,往往需要将自然语言转化成特征向量,再通过计算机处理。比如这里不是吃喝看天气情况了,而是垃圾邮件自动识别,我们就需要对邮件转化成数值型特征向量再输入计算机进行处理。

规范文件数据集处理

如下是一个规范文件的数据集(已经经过数采集、数据格式化、数据预处理等),特征向量包括3个,样本属于一个多分类的情况。即我们通过周飞行里程数、玩游戏占比、吃冰激凌数量判断一个人的优秀程度。假设1代表普通,2代表比较优秀,3代表非常优秀。(ps:一个人一周都在飞机上度过忙碌的工作,又不太玩游戏,关键还注意饮食,说明优秀是有道理的。)

周飞行里程数(km)   周玩游戏占比(%)    周消耗冰激凌(公升)        样本分类
40920                8.326976            0.953952                3
14488                7.153469            1.673904                2
26052                1.441871            0.805124                1
...                  ...                 ...                    ...
75136                13.147394           0.428964                1
38344                1.669788            0.134296                1
72993                10.141740           1.032955                1

上面是处理好保存在txt文本的数据,计算机如何去识别并处理这些数据呢?这里我们分别提取特征向量和标签向量。数据集处理代码如下:

'''对文件进行格式处理,便于分类器可以理解'''
def file_matrix(filename):f = open(filename)arrayLines = f.readlines()returnMat = zeros((len(arrayLines),3))    # 数据集classLabelVactor = []                     # 标签集index = 0for line in arrayLines:listFromLine = line.strip().split('    ')    # 分析数据,空格处理returnMat[index,:] = listFromLine[0:3]classLabelVactor.append(int(listFromLine[-1]))index +=1return returnMat,classLabelVactor

代码说明:

1 zeros(Y,X):填充矩阵,需要导入NumPy包。Y向量代表样本行数,X向量代表样本特征数即列数。
2 returnMat[index,:]:遍历样本特征向量

运行查看数据集的特征向量和分类标签:

''' KNN针对文件的分类算法'''
filename = os.path.abspath(r'./datasource/datingTestSet2.txt')
dataset,labels = file_matrix(filename)
print('特征集:\n'+str(dataset))
print('标签集:\n'+str(labels))

运行结果:

特征集:
[[4.0920000e+04 8.3269760e+00 9.5395200e-01][1.4488000e+04 7.1534690e+00 1.6739040e+00][2.6052000e+04 1.4418710e+00 8.0512400e-01]...[2.6575000e+04 1.0650102e+01 8.6662700e-01][4.8111000e+04 9.1345280e+00 7.2804500e-01][4.3757000e+04 7.8826010e+00 1.3324460e+00]]
标签集:
[3, 2, 1, 1, 1, 1, 3, 3, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3, 2, 1, 2, 3, 2, 3, 2, 3, 2, 1, 3, 1, 3, 1, 2, 1, 1, 2, 3, 3, 1, 2, 3, 3, 3, ...    3, 3, 1, 2, 3, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1]

不规范数据集处理

这里我们只是提供一个思路。比如做文本分类算法,如何将一篇篇新闻转化为规范的数值型数据集呢。假设Z政治新闻100篇,T体育新闻100篇,Y娱乐新闻100篇,K科技新闻100篇。我们进行分类:

1 遍历所有文本转化统一的txt格式文件(2.2节会讲到)
2 对全部ZTYK文本进行分词和停用词处理。
3 统计全部样本词频尺寸(可以采用TF-IDF或者深度学习方法处理)。
4 每个样本进行词频统计

最终模拟效果如下:

样本      词1      词2      词3      词4      ...     词n      标签
p1       200       0       100      50       ...    20         Z
p2       100       0       80       40       ...    10         Z
p3       0         100     5        5        ...    200        T
p4       6         230     40       12       ...    670        T
p5       0         2       110      57       ...    234        Y
...      ...       ...     ...      ...      ...    ...        ...
pn       123       45      0        580      ...    24         K

2.2 数据格式化

数据文件转化

自然语言处理、数据挖掘、机器学习技术应用愈加广泛。针对大数据的预处理工作是一项庞杂、棘手的工作。首先数据采集和存储,尤其高质量数据采集往往不是那么简单。采集后的信息文件格式不一,诸如pdf,doc,docx,Excel,ppt等多种形式。然而最常见便是txt、pdf和word类型的文档。这里所谓格式转化主要对pdf和word文档进行文本格式转换成txt。格式一致化以后再进行后续预处理工作。具体详情请参照之前写的数据分析:基于Python的自定义文件格式转换系统一文。

文件格式化处理

这里可以采用多种方式,诸如上文提到的矩阵填充法,当然也可以采用现成的工具。比如百度的Echarts中表格数据转换工具。其支持纯数组的转换,数组+对象,地理坐标等方式,还支持json数据的转化,这对使用百度EChart可视化是非常友好的,也有助于可视化数据分析。文本数据格式效果如下图:

图2-1 文本数据表格转化

[['40920    8.326976    0.953952    3'],['14488    7.153469    1.673904    2'],['26052    1.441871    0.805124    1'],['75136    13.147394    0.428964    1'],['38344    1.669788    0.134296    1'],['72993    10.141740    1.032955    1'],...['35948    6.830792    1.213192    3'],['42666    13.276369    0.543880    3'],['67497    8.631577    0.749278    1'],['35483    12.273169    1.508053    3'],['50242    3.723498    0.831917    1'],['63275    8.385879    1.669485    1'],['5569    4.875435    0.728658    2'],['15669    0.000000    1.250185    2'],['28488    10.528555    1.304844    3'],['6487    3.540265    0.822483    2'],['37708    2.991551    0.833920    1']
]

2.3 数据归一化

数据归一化

机器学习、数据挖掘、自然语言处理等数据科学工作中,数据前期准备、数据预处理过程、特征提取等几个步骤比较花费时间。同时,数据预处理的效果也直接影响了后续模型能否有效的工作。然而,目前的很多研究主要集中在模型的构建、优化等方面,对数据预处理的理论研究甚少,很多数据预处理工作仍然是靠工程师的经验进行的。也不是所有数据都需要归一化,诸如

1.  数据类型一致且分布均匀。
2.  概率模型可以不做归一化,如决策树。

数据归一化优点

1. 归一化后加快了梯度下降求最优解的速度;
2. 归一化有可能提高精度;

归一化方法

1 sklearn线性归一化

# 线性函数将原始数据线性化的方法转换到[0, 1]的范围   
min_max_scaler = preprocessing.MinMaxScaler()
X_train_minmax = min_max_scaler.fit_transform(X_train)
X_test_minmax = min_max_scaler.transform(X_test)

2 标准差标准化

# 经过处理的数据符合标准正态分布,即均值为0,标准差为1,其转化函数为:
scaler = preprocessing.StandardScaler().fit(X_train)
scaler.transform(X_test)

3 非线性归一化

经常用在数据分化比较大的场景,有些数值很大,有些很小。通过一些数学函数,将原始值进行映射。该方法包括 log、指数,正切等。需要根据数据分布的情况,决定非线性函数的曲线,比如log(V, 2)还是log(V, 10)等。

线性归一化方法代码实现

'''数值归一化:特征值转化为0-1之间:newValue = (oldValue-min)/(max-min)'''
def norm_dataset(dataset):minVals = dataset.min(0)  # 参数0是取得列表中的最小值,而不是行中最小值maxVals = dataset.max(0)ranges = maxVals - minValsnormdataset = zeros(shape(dataset)) # 生成原矩阵一样大小的0矩阵m = dataset.shape[0]# tile:复制同样大小的矩阵molecular = dataset - tile(minVals,(m,1))  # 分子: (oldValue-min)Denominator = tile(ranges,(m,1))           # 分母:(max-min)normdataset = molecular/Denominator     # 归一化结果。return normdataset,ranges,minVals

数据归一化前:

归一化的数据结果:
[[4.0920000e+04 8.3269760e+00 9.5395200e-01][1.4488000e+04 7.1534690e+00 1.6739040e+00][2.6052000e+04 1.4418710e+00 8.0512400e-01]...[2.6575000e+04 1.0650102e+01 8.6662700e-01][4.8111000e+04 9.1345280e+00 7.2804500e-01][4.3757000e+04 7.8826010e+00 1.3324460e+00]]

展开第一条信息“40920 8.326976 0.953952 3”,其中里程40000多,而公升数才0.9.两者根本不在同一个数量级上面,也就是说,如果特征属性相同的情况下,公升数即使变动100倍对里程数的影响也微乎其微。而里程数轻微变化就直接影响公升数的结果。所以我们将其放在同一尺度下进行处理,也就是本文采用的线性缩放方,数据归一化后结果如下:

归一化的数据结果:
[[0.44832535 0.39805139 0.56233353][0.15873259 0.34195467 0.98724416][0.28542943 0.06892523 0.47449629]...[0.29115949 0.50910294 0.51079493][0.52711097 0.43665451 0.4290048 ][0.47940793 0.3768091  0.78571804]]

分析:

经过上述归一化处理后,各个特征指标都是0-1这样一个范畴中进行比较。当然实际工作中不同特征的权重不同,这个可以通过增加权重方法处理即可,本文不在进行深入讨论。

2.4 数据分析

基于matplotlib的可视化分析

我们对数据处理后,很不容易进行数据分析。毕竟密密麻麻的数字略显冰冷无趣。我们可以将其可视化展示出来,进而查看数据稀疏程度,离散程度等等。我们查看'玩游戏所耗时间百分比','每周消耗在冰淇淋的公升数'两个属性的散点图,实现代码如下:

'''
散列表分析数据:
dataset:数据集
datingLabels:标签集
Title:列表,标题、横坐标标题、纵坐标标题。
'''
def analyze_data_plot(dataset,datingLabels,Title):fig = plt.figure()# 将画布划分为1行1列1块ax = fig.add_subplot(111)ax.scatter(dataset[:,1],dataset[:,2],15.0*array(datingLabels),15.0*array(datingLabels))# 设置散点图标题和横纵坐标标题plt.title(Title[0],fontsize=25,fontname='宋体',fontproperties=myfont)plt.xlabel(Title[1],fontsize=15,fontname='宋体',fontproperties=myfont)plt.ylabel(Title[2],fontsize=15,fontname='宋体',fontproperties=myfont)# 设置刻度标记大小,axis='both'参数影响横纵坐标,labelsize刻度大小plt.tick_params(axis='both',which='major',labelsize=10)# 设置每个坐标轴取值范围# plt.axis([-1,25,-1,2.0])# 截图保存图片# plt.savefig('datasets_plot.png',bbox_inches='tight')# 显示图形plt.show()

这里注意一个问题,横纵坐标是乱码显示,解决这个问题,添加如下代码:

#加入中文显示
import  matplotlib.font_manager as fm
# 解决中文乱码,本案例使用宋体字
myfont=fm.FontProperties(fname=r"C:\\Windows\\Fonts\\simsun.ttc")

调用可视化数据分析方法如下:

''' 文件数据图形化分析数据 '''
dataset,labels = file_matrix(filename)
noredataset = norm_dataset(dataset)[0] # 数据归一化
title = ['约会数据游戏和饮食散列点','玩游戏所耗时间百分比','每周消耗在冰淇淋的公升数']
visualplot.analyze_data_plot(noredataset,labels,title)

游戏占比与冰淇淋公升数关系散点图可视化:

图2-2 游戏占比与冰淇淋公升数关系散点图

折线图代码实现如下:

'''折线图'''
def line_chart(xvalues,yvalues):# 绘制折线图,c颜色设置,alpha透明度plt.plot(xvalues,yvalues,linewidth=0.5,alpha=0.5,c='red') # num_squares数据值,linewidth设置线条粗细# 设置折线图标题和横纵坐标标题plt.title("Python绘制折线图",fontsize=30,fontname='宋体',fontproperties=myfont)plt.xlabel('横坐标',fontsize=20,fontname='宋体',fontproperties=myfont)plt.ylabel('纵坐标',fontsize=20,fontname='宋体',fontproperties=myfont)# 设置刻度标记大小,axis='both'参数影响横纵坐标,labelsize刻度大小plt.tick_params(axis='both',labelsize=14)# 显示图形plt.show()

游戏占比与冰淇淋公升数关系折线图可视化:(此处折线图明显不合适,只是突出另一种分析方式。)

图2-3 游戏占比与冰淇淋公升数关系折线图

扩展:

更多matplotlib可视化实现效果图参考文章 70个注意的Python小Notes:完整的matplotlib可视化

基于Echart的可视化分析

我们上面采用的matplotlib可视化效果,采用该方式主要是结合python数据分析绑定比较方便。有些时候我们为了取得更加漂亮的可视化效果,可以选择百度echart进行分析,百度Echart使用简单且文档规范容易上手。我们对原数据进行分析并转化为json代码:

'''array数据转化json'''
def norm_Json(dataset):noredataset = norm_dataset(dataset)[0] # 数据归一化number1 = np.around(noredataset[:,1], decimals=4) # 获取数据集第二列number2 = np.around(noredataset[:,2], decimals=4) # 获取数据集第三列returnMat=zeros((dataset.shape[0],2))             # 二维矩阵returnMat[:,0] = number1returnMat[:,1] = number2file_path = os.path.abspath(r"./datasource/test.json")json.dump(returnMat.tolist(), codecs.open(file_path, 'w', encoding='utf-8'), separators=(',', ':'), sort_keys=True, indent=4)

生成json数据保存在指定文件中,打开文件查看数据如下:

[[0.3981,0.5623],[0.342,0.9872],[0.0689,0.4745],[0.6285,0.2525]...[0.4367,0.429],[0.3768,0.7857]
]

从百度Echart实例中选择一种散点图并绑定json文件,其html代码如下:

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>图案例</title><script src="https://cdn.bootcss.com/jquery/2.2.0/jquery.min.js"></script><script type="text/javascript" src="./js/echarts.js"></script>
</head>
<body><div id="chartmain" style="width:800px; height: 400px; margin:auto; "></div><script type="text/javascript">//初始化echarts实例var myChart = echarts.init(document.getElementById('chartmain'));$.getJSON('game-food.json', function (data) {var option = {title: {text: '玩游戏时间占比和饮食数据描述',left: 'center',top: 0},visualMap: {min: 15202,max: 159980,dimension: 1,orient: 'vertical',right: 10,top: 'center',text: ['优秀', '一般'],calculable: true,inRange: {color: ['#f2c31a', '#24b7f2']}},tooltip: {trigger: 'item',axisPointer: {type: 'cross'}},xAxis: [{type: 'value'}],yAxis: [{type: 'value'}],series: [{name: 'price-area',type: 'scatter',symbolSize: 5,data: data}]};myChart.setOption(option);
});</script>
</body>
</html>

json文件读取需要在web运行环境中,单纯的运行效果如下图所示:

 

图2-4 游戏占比与冰淇淋公升数Echarts关系散点图

数据转化工具

本文采用自己构建的方式进行json文件生成,此外我们也可以采用现有的数据转化工具进行处理。比如百度的表格数据转化工具(2.2节已经介绍了)。

另一个便是在线json验证格式工具:http://www.bejson.com/

2.5 KNN分类器实现

通过数据分析,我们查看数据样本是否偏态分别,数据规模情况等等。针对性进行数据预处理后,编写具体算法模型。本文主要是KNN分类器,其代码如下:

''' 构造KNN分类器vecX:输入向量,待测数据filename: 特征集文件路径isnorm:是否进行归一化处理k:k值的选择,默认选择3
'''
def knn_classifier(vecX,dataset,labels,isnorm='Y',k=3):# 距离计算(方法1)if isnorm == 'Y':normMat,ranges,minVals = norm_dataset(dataset)     # 对数据进行归一化处理normvecX = norm_dataset(vecX)else:normMat = datasetnormvecX = vecXm = normMat.shape[0]# tile方法是在列向量vecX,datasetSize次,行向量vecX1次叠加diffMat = tile(normvecX,(m,1)) - normMatsqDiffMat = diffMat ** 2sqDistances = sqDiffMat.sum(axis=1)   # axis=0 是列相加,axis=1是行相加distances = sqDistances**0.5# print('vecX向量到数据集各点距离:\n'+str(distances))sortedDistIndexs = distances.argsort(axis=0)  # 距离排序,升序# print(sortedDistIndicies)classCount = {}   # 统计前k个类别出现频率for i in range(k):votelabel = labels[sortedDistIndexs[i]]classCount[votelabel] = classCount.get(votelabel,0) + 1 #统计键值# 类别频率出现最高的点,itemgetter(0)按照key排序,itemgetter(1)按照value排序sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)print(str(vecX)+'KNN的投票决策结果:\n'+str(sortedClassCount[0][0]))return sortedClassCount[0][0]

3 KNN算法模型评估

3.1 评价指标介绍

基本知识

混淆矩阵:正元组和负元组的合计

图3-1 混淆矩阵表

评估度量:(其中P:正样本数 N:负样本数 TP:真正例 TN:真负例 FP:假正例 FN:假负例)

图3-2 评估信息度量表

注意:学习器的准确率最好在检验集上估计,检验集的由训练集模型时未使用的含有标记的元组组成数据。

各参数描述如下:

TP(真正例/真阳性):是指被学习器正确学习的正元组,令TP为真正例的个数。

TN(真负例/真阴性):是指被学习器正确学习的负元组,令TN为真负例的个数。

FP(假正例/假阳性):是被错误的标记为正元组的负元组。令FP为假正例的个数。

FN(假负例/假阴性):是被错误的标记为负元组的正元组。令FN为假负例的个数。

准确率:正确识别的元组所占的比例。

评价指标优点

一般采用精确率和召回率作为度量的方法具有以下几个优点:

(1) 准确率数值对于小数据不是特别敏感,而精确率和召回率对于这样数据比较敏感。 (2) 在相同实验环境下,F度量这种倾向和我们直观感觉是一致的,我们对目标事件很敏感,甚至返回一些垃圾数据也在所不惜。 (3) 通过精确率和找回来衡量目标事件和垃圾事件的差异。

模型评估拓展

参见《自然语言处理理论与实战》一书第13章模型评估。

3.2 评估算法模型实现

本文只是对错误率进行评估,其也是knn分类器核心指标,实现代码如下:

'''测试评估算法模型'''
def test_knn_perfor(filename):hoRatio = 0.1dataset,label = file_matrix(filename)              # 获取训练数据和标签normMat,ranges,minVals = norm_dataset(dataset)     # 对数据进行归一化处理m = normMat.shape[0]numTestVecs = int(m*hoRatio)                       # 10%的测试数据条数errorCount = 0.0                                   # 统计错误分类数for i in range(numTestVecs):classifierResult = knn_classifier(normMat[i,:],normMat[numTestVecs:m,:],label[numTestVecs:m],3)          # 此处分类器可以替换不同分类模型print('分类结果:'+str(classifierResult)+'\t\t准确结果:'+str(label[i]))if classifierResult != label[i]:errorCount += 1.0Global.all_FileNum += 1print('总的错误率为:'+str(errorCount/float(numTestVecs))+"\n总测试数据量: "+str(Global.all_FileNum))

运行效果如下:

[0.44832535 0.39805139 0.56233353]KNN的投票决策结果:
分类结果:3      准确结果:3
[0.15873259 0.34195467 0.98724416]KNN的投票决策结果:
分类结果:2      准确结果:2
...
分类结果:3      准确结果:3
[0.19385799 0.30474213 0.01919426]KNN的投票决策结果:
分类结果:2      准确结果:2
[0.24463971 0.10813023 0.60259472]KNN的投票决策结果:
分类结果:1      准确结果:1
[0.51022756 0.27138082 0.41804137]KNN的投票决策结果:
分类结果:3      准确结果:1总的错误率为:0.05
总测试数据量: 100
耗时:0.0300 s

评估结果分析:

本文采用封闭评估的方法,前100条数据作为测试集,后900条数据作为训练集。如上结果最后一条信息表明knn分类器的结果是3,而标准结果是1.knn分类存在错误。将所有错误占比分析出来即错误率。本文错误率5%,即准确率95%.

读者可以选取200:800、300:700等等数据进行测试查看错误率。

4 KNN算法模型的实际应用

knn分类器应用

经过如上的改进最终形成实际应用的算法模型API开发给外部程序使用,调用knn算法代码如下:

'''调用可用算法'''
def show_classifyPerson(filename):resultlist = ['不喜欢','还可以','特别喜欢']ffMiles = float(input('每年飞行的历程多少公里?\n'))percentTats = float(input('玩游戏时间占百分比多少?\n')) # [751,13,0.4][40920 ,8.326976,0.953952]iceCream = float(input('每周消费冰淇淋多少公升?\n'))dataset,labels = file_matrix(filename) # 数据格式化处理inArr = array([ffMiles,percentTats,iceCream])classifierResult = knn_classifier(inArr,dataset,labels,3) # 数据归一化并进行分类print('预测的约会结果是:'+resultlist[classifierResult-1])

运行结果如下:

每年飞行的历程多少公里?
10000
玩游戏时间占百分比多少?
10
每周消费冰淇淋多少公升?
0.5
KNN的投票决策结果:
2
预测的约会结果是:还可以

展望

我们还可以采用knn分类器进行实际应用,比如新闻分类系统。大致思路如下:

1 采集数据:选用复旦大学的文本分类新闻语料 2 准备数据:数据格式化、分词、停用词处理等 3 分析数据:看看数据特点,有没有缺失值,数据连续性还是离散型,进而选择不同模型。诸如:可视化数据分析 4 数据转化:采用IF-IDF或者神经网络的方法对词频进行处理,最终转化为机器可以处理的数值型矩阵。 5 构建模型:KNN新闻分类器模型构建。 6 测试算法:评价指标,如计算错误率,准确率,召回率,F度量值等。 7 应用算法:针对完善的模型进行封装重构,然后进行实际的新闻分类应用。

5 参考文献

  1. 归一化学习:https://blog.csdn.net/hyq3235356/article/details/78472307
  2. 归一化方法:https://blog.csdn.net/zxd1754771465/article/details/73558103
  3. 百度Echart转化工具:http://echarts.baidu.com/spreadsheet.html
  4. 在线json验证格式工具:http://www.bejson.com/
  5. 模型评估:http://www.cnblogs.com/baiboy/p/mxpg2.html

完整代码下载

机器学习和自然语言QQ群:436303759。 微信公众号:datathinks

自然语言处理和机器学习QQ交流群:436303759自然语言处理和机器学习微信公众号:datathinks

源码请进QQ群文件下载:

作者声明

本文版权归作者所有,旨在技术交流使用。未经作者同意禁止转载,转载后需在文章页面明显位置给出原文连接,否则相关责任自行承担。转载必须注明出处【伏草惟存】:一步步教你轻松学KNN模型算法

 

 

 

 

转载于:https://www.cnblogs.com/baiboy/p/pybnc2.html


http://chatgpt.dhexx.cn/article/V8JfQS4E.shtml

相关文章

Oracle实战详解

Oracle实战详解 1.oracle介绍 ORACLE数据库系统是美国ORACLE公司&#xff08;甲骨文&#xff09;提供的以分布式数据库为核心的一组软件产品&#xff0c;是目前最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的数据库之一。比如SilverStream就是基于数据库的一种中间件。ORA…

数据库|SQL / MySQL的基本理论用法

本文从数据库MySQL的数据类型、关系模型、增删改查语句、管理MySQL、实用SQL语句、事务等方面进行介绍。 数据类型 对于一个关系表&#xff0c;除了定义每一列的名称外&#xff0c;还需要定义每一列的数据类型。关系数据库支持的标准数据类型包括数值、字符串、时间等&#xf…

KNN模型算法研究与案例分析

KNN模型算法研究与案例分析( 白宁超 2018年8月29日15:39:13 ) 导读&#xff1a;机器学习算法中KNN属于比较简单的典型算法&#xff0c;既可以做聚类又可以做分类使用。本文通过一个模拟的实际案例进行讲解。整个流程包括&#xff1a;采集数据、数据格式化处理、数据分析、数据归…

SQL总结

目录 简介 在Android中存储数据有时会用到数据库&#xff0c;Android给我们提供了 一系列的API来操作数据库&#xff0c;非常简单&#xff0c;我们只需要输入对应的SQL语句&#xff0c;甚至不懂SQL语句&#xff0c;只传入对应的参数即可使用。还有一些第三方库&#xff0c;如G…

Windows开机启动项设置详解

一、开机启动原理 Windows系统都有一个“启动”文件夹&#xff0c;把需要打开的程序的快捷方式或脚本放到“启动”文件夹里&#xff0c;就可以实现开机自启动。 启动”文件夹分为两种&#xff1a;“系统启动文件夹”和“用户启动文件夹”。 系统启动文件夹 Win10系统“启动”…

「C#」设置开机启动

自己写了个监控键盘按键的小程序。 在界面上实时显示按下的键&#xff0c;但是想实现程序的开机自启如何实现呢。 开机自启动一种是在windows的“C:\Users\用户名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup”家快捷方式。但是这种方法自测有时候不成功。…

centos7 设置开机启动项

高端的废话就是没有引言这种废话。 1.这里我已我的centos7为例输入&#xff1a; systemctl list-unit-files #查看开机启动表如图下&#xff1a; 最左边就是服务 &#xff0c;最右边就是状态 。如当你想要服务器开机启动firewalld&#xff08;防火墙&#xff09;输入 system…

计算机怎么管理自启,电脑如何设置开机启动项

大家都知道将程序添加到开机启动项进入系统就可以自动打开了&#xff0c;但是有些流氓软件会强制进入开机启动项&#xff0c;这就导致电脑开机速度变慢&#xff0c;内存占用过多&#xff0c;运行卡顿的问题。下面&#xff0c;我就教大家如何设置开机启动 现在几乎家家户户都配备…

电脑设置开机

我们知道电脑可以通过修改系统任务计划来实现定时关机的功能&#xff0c;那么&#xff0c;能不能让电脑实现自动开机的功能呢?答案是可以的&#xff0c;我们可以通过BIOS设置&#xff0c;指定电脑在某个时间点自动开机&#xff0c;接下来&#xff0c;小编来介绍一下如何通过BI…

nginx 设置开机自启动

一、下载 在windows下实现开机自启动需要一个开源项目Windows Service Wrapper 来实现。 我用的是这个版本。 下载下来&#xff0c;放在Nginx根目录下 下载下来&#xff0c;放在Nginx根目录下&#xff0c;名字改为start-nginx.exe&#xff0c;再新建一个txt文件&#xff0c…

Win11开机启动项怎么调整,Win11开机启动项怎么设置

Win11开机启动项怎么调整&#xff1f;Win11开机启动项怎么设置&#xff1f;现在很多应用或软件下载安装之后默认都是开机自启的&#xff0c;如果开机自启的软件多了的话难免会导致系统开机速度变慢。最近有使用win11系统的小伙伴就遇到了这个问题&#xff0c;有网友想了解怎么设…

windows设置开机启动程序

1.新建文件,填写路径 echo off cd F:\程序路径\ //后面填写3D所在的路径 F: //程序的个盘符 run.bat把这个文件填写完成后,改个名字,后缀改为bat,并把这个文件放在机房的程序目录下 2.设置开机计划任务 windows 7 在【开始】菜单中&#xff0c;输入【任务计划】&#xf…

计算机软件自启动设置,设置开机启动项,详细教您电脑如何设置开机启动项

身边不少朋友买了电脑都在比拼电脑开机速度&#xff0c;一般新电脑开机启动时间保持在30s左右就已经很不错了&#xff0c;不过不少朋友电脑开机时间需要1分多钟&#xff0c;不少朋友的答案的设置开机启动项目&#xff0c;尽量减少程序开机启动&#xff0c;那么如何优化提升电脑…

Windows 三种开机自启动的设置方式(全面)

一、修改注册表的方式 进入注册表&#xff0c;点击任务栏开始&#xff0c;输入regedit.exe&#xff0c;进入[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run]位置后&#xff0c;新建一个二进制字符类型的项&#xff0c;数值数据位置填入所需开机自启动的应…

linux设置开机启动脚本的3种方法

Linux 下设置开机启动的三种简单但可行的开机启动设置方法。 方法一&#xff1a;修改 /etc/rc.d/rc.local 文件 /etc/rc.d/rc.local 文件会在 Linux 系统各项服务都启动完毕之后再被运行。所以你想要自己的脚本在开机后被运行的话&#xff0c;可以将自己脚本路径加到该文件里…

Win11怎么设置开机启动项?

我们在使用电脑的时候经常会打开非常多的软件&#xff0c;而每次开机都需要手动去点击&#xff0c;就会变得非常的麻烦&#xff0c;那么在Win11操作系统中我们应该怎么设置呢&#xff1f;其实方法非常简单&#xff0c;下面小编就带着大家一起看看吧&#xff01; 操作方法&#…

WebLogic RMI 反序列化漏洞

文章目录 WebLogic RMI 反序列化基础知识影响版本漏洞概述漏洞危害漏洞复现目标机搭建漏洞环境漏洞验证端口探测 漏洞检测脚本在kali上运行命令下载反序列化漏洞利用工具 ysoserial启动 JRMPListener server执行反弹shell命令 使用python脚本发送payload下载 exploit脚本脚本执…

常见的Web漏洞——反序列化漏洞

目录 漏洞简介 漏洞成因 漏洞可能出现的位置 漏洞原理 Python反序列化漏洞实验 PHP反序列化漏洞实验 serialize函数输出格式 PHP中常用魔术方法 Java反序列化漏洞实验 FastJson反序列化漏洞简单实验 ASP.NET反序列化实验 防御方法 常用工具 参考文章 漏洞简介 序…

shrio反序列漏洞修复_shiro反序列化漏洞

shrio反序列化漏洞 一、漏洞介绍 Shiro 是 Java 的一个安全框架。Apache Shiro默认使用了CookieRememberMeManager,其处理cookie的流程是:得到rememberMe的cookie值 > Base64解码–>AES解密–>反序列化。然而AES的密钥是硬编码的,就导致了攻击者可以构造恶意数据造…

如何挖掘反序列化漏洞

文章目录 代码审计payload 1payload 2 平时挖的或者看到的反序列例子都很曲折&#xff0c;或者很个例&#xff0c;无法作为一个科普文。偶然看到大佬KeePassX的Java反序列化漏洞从入门到关门&#xff0c;发现这是一个难得一见的反序列化挖掘的好例子&#xff0c;它很舒畅&#…