[机器学习笔记]kNN进邻算法
K-近邻算法
一、算法概述
(1)采用测量不同特征值之间的距离方法进行分类
- 优点: 精度高、对异常值不敏感、无数据输入假定。
- 缺点: 计算复杂度高、空间复杂度高。
(2)KNN模型的三个要素
kNN算法模型实际上就是对特征空间的的划分。模型有三个基本要素:距离度量、K值的选择和分类决策规则的决定。
距离度量
距离定义为:
\[L_p(x_i,x_j)=\left( \sum^n_{l=1} |x_i^{(l)} - x_j^{(l)}|^p \right) ^{\frac{1}{p}}
\]一般使用欧式距离:p = 2的个情况
\[L_p(x_i,x_j)=\left( \sum^n_{l=1} |x_i^{(l)} - x_j^{(l)}|^2 \right) ^{\frac{1}{2}}
\]K值的选择
一般根据经验选择,需要多次选择对比才可以选择一个比较合适的K值。
如果K值太小,会导致模型太复杂,容易产生过拟合现象,并且对噪声点非常敏感。
如果K值太大,模型太过简单,忽略的大部分有用信息,也是不可取的。
分类决策规则
一般采用多数表决规则,通俗点说就是在这K个类别中,哪种类别最后就判别为哪种类型
二、实施kNN算法
2.1 伪代码
- 计算法已经类别数据集中的点与当前点之间的距离
- 按照距离递增次序排序
- 选取与但前点距离最小的k个点
- 确定前k个点所在类别的出现频率
- 返回前k个点出现频率最高的类别作为当前点的预测分类
#### 2.2 实际代码
def classify0(inX, dataSet, 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
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
三、实际案例:使用kNN算法改进约会网站的配对效果
我的朋友阿J一直使用在线约会软件寻找约会对象,他曾经交往过三种类型的人:
- 不喜欢的人
- 感觉一般的人
- 非常喜欢的人
步骤:
- 收集数据
- 准备数据:也就是读取数据的过程
- 分析数据:使用Matplotlib画出二维散点图
- 训练算法
- 测试算法
- 使用算法
3.1 准备数据
样本数据共有1000个,3个特征值,共有4列数据,最后一列表示标签分类(0:不喜欢的人;1:感觉一般的人;2:非常喜欢的人)
特征
- 每年获得的飞行常客里程数
- 玩视频游戏所好的时间百分比
- 每周消费的冰淇淋公斤数
部分数据如下:
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
读取数据(读取txt文件)
def file2matrix(filename):
fr = open(filename)
numberOfLines = len(fr.readlines()) #get the number of lines in the file
returnMat = zeros((numberOfLines,3)) #prepare matrix to return
classLabelVector = [] #prepare labels return
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
3.2 分析数据:使用Matplotlib创建散点图
初步分析
import matplotlib
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1], datingDataMat[:,2])
ax.set_xlabel("玩视频游戏所耗时间百分比")
ax.set_ylabel("每周消费的冰淇淋公斤数")
plt.show()

因为有三种类型的分类,这样看的不直观,我们添加以下颜色
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1], datingDataMat[:,2])
ax.scatter(datingDataMat[:,1], datingDataMat[:,2], 15.0*array(datingLabels), 15.0*array(datingLabels))
ax.set_xlabel("玩视频游戏所耗时间百分比")
ax.set_ylabel("每周消费的冰淇淋公斤数")
plt.show()

通过都多次的尝试后发现,玩游戏时间和冰淇淋这个两个特征关系比较明显
具体的步骤:
- 分别将标签为1,2,3的三种类型的数据分开
- 使用matplotlib绘制,并使用不同的颜色加以区分
datingDataType1 = array([[x[0][0],x[0][1],x[0][2]] for x in zip(datingDataMat,datingLabels) if x[1]==1])
datingDataType2 = array([[x[0][0],x[0][1],x[0][2]] for x in zip(datingDataMat,datingLabels) if x[1]==2])
datingDataType3 = array([[x[0][0],x[0][1],x[0][2]] for x in zip(datingDataMat,datingLabels) if x[1]==3])
fig, axs = plt.subplots(2, 2, figsize = (15,10))
axs[0,0].scatter(datingDataType1[:,0], datingDataType1[:,1], s = 20, c = 'red')
axs[0,1].scatter(datingDataType2[:,0], datingDataType2[:,1], s = 30, c = 'green')
axs[1,0].scatter(datingDataType3[:,0], datingDataType3[:,1], s = 40, c = 'blue')
type1 = axs[1,1].scatter(datingDataType1[:,0], datingDataType1[:,1], s = 20, c = 'red')
type2 = axs[1,1].scatter(datingDataType2[:,0], datingDataType2[:,1], s = 30, c = 'green')
type3 = axs[1,1].scatter(datingDataType3[:,0], datingDataType3[:,1], s = 40, c = 'blue')
axs[1,1].legend([type1, type2, type3], ["Did Not Like", "Liked in Small Doses", "Liked in Large Doses"], loc=2)
axs[1,1].set_xlabel("玩视频游戏所耗时间百分比")
axs[1,1].set_ylabel("每周消费的冰淇淋公斤数")
plt.show()

3.3 准备数据:数据归一化
通过上面的图形绘制,发现三个特征值的范围不一样,在使用KNN进行计算距离的时候,数值大的特征值就会对结果产生更大的影响。
数据归一化:就是将几组不同范围的数据,转换到同一个范围内。
公式: newValue = (oldValue - min)/(max - min)
def autoNorm(dataSet):
minVals = dataSet.min(0) # array([[1,20,3], [4,5,60], [7,8,9]]) min(0) = [1, 5, 3]
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normData = zeros(shape(dataSet))
m = dataSet.shape[0]
normData = (dataSet - tile(minVals, (m,1)))/tile(ranges,(m,1))
return normData
3.4 测试算法
我们将原始样本保留20%作为测试集,剩余80%作为训练集
def datingClassTest():
hoRatio = 0.20
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #load data setfrom file
normMat = autoNorm(datingDataMat)
m = normMat.shape[0]
numTestVecs = int(m*hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:,:],datingLabels[numTestVecs:],3)
if (classifierResult != datingLabels[i]):
errorCount += 1.0
print ("the total error rate is: %f" % (errorCount/float(numTestVecs)))
print (errorCount)
运行结果
the total error rate is: 0.080000
16.0
四、源代码
from numpy import *
import operator
from os import listdir
import matplotlib
import matplotlib.pyplot as plt
## KNN function
def classify0(inX, dataSet, 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
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
# read txt data
def file2matrix(filename):
fr = open(filename)
numberOfLines = len(fr.readlines()) #get the number of lines in the file
returnMat = zeros((numberOfLines,3)) #prepare matrix to return
classLabelVector = [] #prepare labels return
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) # array([[1,20,3], [4,5,60], [7,8,9]]) min(0) = [1, 5, 3]
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normData = zeros(shape(dataSet))
m = dataSet.shape[0]
normData = (dataSet - tile(minVals, (m,1)))/tile(ranges,(m,1))
return normData
def drawScatter1(datingDataMat, datingLabels):
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1], datingDataMat[:,2])
ax.set_xlabel("玩视频游戏所耗时间百分比")
ax.set_ylabel("每周消费的冰淇淋公斤数")
plt.show()
def drawScatter2(datingDataMat, datingLabels):
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1], datingDataMat[:,2])
ax.scatter(datingDataMat[:,1], datingDataMat[:,2], 15.0*array(datingLabels), 15.0*array(datingLabels))
ax.set_xlabel("玩视频游戏所耗时间百分比")
ax.set_ylabel("每周消费的冰淇淋公斤数")
plt.show()
def drawScatter3(datingDataMat, datingLabels):
datingDataType1 = array([[x[0][0],x[0][1],x[0][2]] for x in zip(datingDataMat,datingLabels) if x[1]==1])
datingDataType2 = array([[x[0][0],x[0][1],x[0][2]] for x in zip(datingDataMat,datingLabels) if x[1]==2])
datingDataType3 = array([[x[0][0],x[0][1],x[0][2]] for x in zip(datingDataMat,datingLabels) if x[1]==3])
fig, axs = plt.subplots(2, 2, figsize = (15,10))
axs[0,0].scatter(datingDataType1[:,0], datingDataType1[:,1], s = 20, c = 'red')
axs[0,1].scatter(datingDataType2[:,0], datingDataType2[:,1], s = 30, c = 'green')
axs[1,0].scatter(datingDataType3[:,0], datingDataType3[:,1], s = 40, c = 'blue')
type1 = axs[1,1].scatter(datingDataType1[:,0], datingDataType1[:,1], s = 20, c = 'red')
type2 = axs[1,1].scatter(datingDataType2[:,0], datingDataType2[:,1], s = 30, c = 'green')
type3 = axs[1,1].scatter(datingDataType3[:,0], datingDataType3[:,1], s = 40, c = 'blue')
axs[1,1].legend([type1, type2, type3], ["Did Not Like", "Liked in Small Doses", "Liked in Large Doses"], loc=2)
axs[1,1].set_xlabel("玩视频游戏所耗时间百分比")
axs[1,1].set_ylabel("每周消费的冰淇淋公斤数")
plt.show()
def datingClassTest():
hoRatio = 0.20
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #load data setfrom file
normMat = autoNorm(datingDataMat)
m = normMat.shape[0]
numTestVecs = int(m*hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:,:],datingLabels[numTestVecs:],3)
if (classifierResult != datingLabels[i]):
errorCount += 1.0
print ("the total error rate is: %f" % (errorCount/float(numTestVecs)))
print (errorCount)
datingDataMat, datingLabels = file2matrix("datingTestSet2.txt")
drawScatter1(datingDataMat, datingLabels)
drawScatter2(datingDataMat, datingLabels)
drawScatter3(datingDataMat, datingLabels)
datingClassTest()
[机器学习笔记]kNN进邻算法的更多相关文章
- 机器学习笔记(五) K-近邻算法
K-近邻算法 (一)定义:如果一个样本在特征空间中的k个最相似的样本中的大多数属于某一个类别,则该样本也属于这个类别. (二)相似的样本,特征之间的值应该是相近的,使用k-近邻算法需要做标准化处理.否 ...
- kNN进邻算法
一.算法概述 (1)采用测量不同特征值之间的距离方法进行分类 优点: 精度高.对异常值不敏感.无数据输入假定. 缺点: 计算复杂度高.空间复杂度高. (2)KNN模型的三个要素 kNN算法模型实际上就 ...
- 《机器学习实战》——k-近邻算法Python实现问题记录(转载)
py2.7 : <机器学习实战> k-近邻算法 11.19 更新完毕 原文链接 <机器学习实战>第二章k-近邻算法,自己实现时遇到的问题,以及解决方法.做个记录. 1.写一个k ...
- Python机器学习笔记:异常点检测算法——LOF(Local Outiler Factor)
完整代码及其数据,请移步小编的GitHub 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/MachineLearningNote 在数据挖掘方面,经常需 ...
- 机器学习实战读书笔记(二)k-近邻算法
knn算法: 1.优点:精度高.对异常值不敏感.无数据输入假定 2.缺点:计算复杂度高.空间复杂度高. 3.适用数据范围:数值型和标称型. 一般流程: 1.收集数据 2.准备数据 3.分析数据 4.训 ...
- 机器学习实践之K-近邻算法实践学习
关于本文说明,本人原博客地址位于http://blog.csdn.net/qq_37608890,本文来自笔者于2017年12月04日 22:54:26所撰写内容(http://blog.csdn.n ...
- 机器学习实战(一)k-近邻算法
转载请注明源出处:http://www.cnblogs.com/lighten/p/7593656.html 1.原理 本章介绍机器学习实战的第一个算法——k近邻算法(k Nearest Neighb ...
- 吴裕雄--天生自然python机器学习:使用K-近邻算法改进约会网站的配对效果
在约会网站使用K-近邻算法 准备数据:从文本文件中解析数据 海伦收集约会数据巳经有了一段时间,她把这些数据存放在文本文件(1如1^及抓 比加 中,每 个样本数据占据一行,总共有1000行.海伦的样本主 ...
- 机器学习实战笔记(1)——k-近邻算法
机器学习实战笔记(1) 1. 写在前面 近来感觉机器学习,深度学习神马的是越来越火了,从AlphaGo到Master,所谓的人工智能越来越NB,而我又是一个热爱新潮事物的人,于是也来凑个热闹学习学习. ...
随机推荐
- GDAL集成对KML文件的支持
目录 1. 正文 1.1. 编译LibKML 1.1.1. 第三方库支持 1.1.2. 编译错误 1.2. 配置GDAL 1.3. 链接问题 2. 参考 1. 正文 GDAL可以支持将KML作为矢量文 ...
- Java系列之注解
Java系列之注解 Java 注解(Annotation)又称之为 Java 标注.元数据,是 Java 1.5 之后加入的一种特殊语法,通过注解可以标注 Java 中的类.方法.属性.参数.包等,可 ...
- css的简单使用
css语法 id选择器: id 选择器可以为标有特定 id 的 HTML 元素指定特定的样式. HTML元素以id属性来设置id选择器,CSS 中 id 选择器以 "#" 来定义. ...
- ride.py打不开RF,而是打开pycharm
标题中问题的解决方式: 进入到E:\soft\Python\Python36\Scripts,选中ride.py右键-打开方式选择python即可
- Spring Boot提供RESTful接口时的错误处理实践
使用Spring Boot开发微服务的过程中,我们会使用别人提供的接口,也会设计接口给别人使用,这时候微服务应用之间的协作就需要有一定的规范. 基于rpc协议,我们一般有两种思路:(1)提供服务的应用 ...
- IDE安装完成无法打开,报错Fail load JVM DLL 问题与解决方案
安装完成pycharm 在打开pycharm的时候出现报错 Fail load JVM DLL xxxx xxx. 解决方案 安装Microsoft Visual C++ 2010 Redistrib ...
- ESP8266开发之旅 网络篇⑮ DNSServer——真正的域名服务
1. 前言 Arduino for esp8266中有两个DNS服务相关的库: ESP8266mDNS库 这个库是mDNS库,使用这个库的时候ESP8266可以在AP模式或是以STA模式接入局 ...
- 百万年薪python之路 -- 网络通信原理
1. C/S B/S架构 C: Client 客户端 B: Browse 浏览器 S: Server 服务端 C/S架构: 基于客户端与服务端之间的通信 eg: QQ,微信,LOL,DNF等需要安装A ...
- 一次PHP代码上线遇到的问题
exception ‘CDbException’ with message ‘The table “pms_goods” for active record class “PmsGoods” cann ...
- 数据库系统(六)---MySQL语句及存储过程
一.DDL.DML.DCL常用语句 1.DDL(Data Definition Language)数据库定义语言 (1)数据库模式定义 #创建数据库 create database if exsite ...