【是什么】

KNN 即 k_近邻算法(k- nearest neighbor) ,就是寻找K个邻居作为该样本的特征,近朱者赤,近墨者黑,你的邻居是什么特征,那么就认为你也具备该特征;核心公式为:

数据来源:https://github.com/apachecn/AiLearning/blob/master/data/2.KNN/datingTestSet2.txt

读取数据转换成矩阵

# 提取文件中的数据 转换成矩阵
def file2matric(filename):
"""
disc:
param: filename: 导入数据文本
return: 数据矩阵
"""
f = open(filename,'r',encoding= 'utf-8')
# 获取文件的行数
lines_list = f.readlines()
num_of_lines = len(lines_list)
# 创建存放标签的列表
class_label_list = []
# 生成对应的空矩阵 zeros(2,3) 就是生成2行3列的0矩阵
returnMat = np.zeros((num_of_lines,3))
# 将文本中的数据放到矩阵中
for i in range(num_of_lines):
lines = lines_list[i].strip().split('\t')
# 将文本中的前3个数据放到矩阵中
returnMat[i,:] = lines[0:3]
# 将标签存到列表中
class_label_list.append(int(lines[-1])) # print(returnMat)
return returnMat, class_label_list

利用 matplotlib 绘制散点图

def DrawScatter(dataMat,label_list):
# 导入中文字体,及字体大小
zhfont = FontProperties(fname='C:/Windows/Fonts/simsun.ttc', size=14)
# 绘制绘图窗口 2行2列
fig,ax = plt.subplots(2,2,figsize=(13,8))
# 不同标签赋予不同颜色
label_color = []
for i in label_list:
if i == 1:
label_color.append('black')
elif i == 2:
label_color.append('orange')
elif i == 3:
label_color.append('red')
# 开始绘制散点图 设定散点尺寸与透明度
scatter_size = 12
scatter_alpha = 0.5
# ===================散点图========================
ax[0][0].scatter(dataMat[:,0], dataMat[:,1],color = label_color,s = scatter_size ,alpha = scatter_alpha)
ax[0][1].scatter(dataMat[:, 1], dataMat[:, 2], color=label_color, s=scatter_size , alpha=scatter_alpha)
ax[1][0].scatter(dataMat[:, 0], dataMat[:, 2], color=label_color, s=scatter_size , alpha=scatter_alpha) # 坐标轴标题
title_list = ['每年获得的飞行常客里程数和玩视频游戏所消耗时间占比',
'每年获得的飞行常客里程数和每周消费的冰激淋公升数',
'玩视频游戏所消耗时间占比和每周消费的冰激淋公升数']
x_name_list = ['每年获得的飞行常客里程数','玩视频游戏所消耗时间占比','每周消费的冰激淋公升数']
y_name_list = ['玩视频游戏所消耗时间占比','每周消费的冰激淋公升数','每年获得的飞行常客里程数']
#设置图例
didntLike = mlines.Line2D([], [], color='black', marker='.',
markersize=6, label='didntLike')
smallDoses = mlines.Line2D([], [], color='orange', marker='.',
markersize=6, label='smallDoses')
largeDoses = mlines.Line2D([], [], color='red', marker='.',
markersize=6, label='largeDoses') p = 0
for i in range(2):
for j in range(2):
if p > 2:
break
# 设置坐标轴名称和标题
plt.setp(ax[i][j].set_title(u'%s'%(title_list[p]),FontProperties = zhfont),size=9, weight='bold', color='red')
plt.setp(ax[i][j].set_xlabel(u'%s'%(x_name_list[p]),FontProperties = zhfont), size=7, weight='bold', color='black')
plt.setp(ax[i][j].set_ylabel(u'%s'%(y_name_list[p]),FontProperties = zhfont), size=7, weight='bold', color='black')
p+=1
# 添加图例
ax[0][0].legend(handles=[didntLike, smallDoses, largeDoses])
ax[0][1].legend(handles=[didntLike, smallDoses, largeDoses])
ax[1][0].legend(handles=[didntLike, smallDoses, largeDoses]) plt.show()

对数据进行归一化处理

由于不同数据的范围波动不同,在权重一样的情况下,需要进行归一化,即将数据转换成0-1之间

# 对矩阵进行归一化处理
def dataNorm(dataMat):
"""
:param dataMat:
:return: 归一化后的数据集
归一化公式: Y = (X - Xmin)/(Xmax - Xmin)
"""
# max(0) min(0) 求出每列的最大值和最小值
d_min = dataMat.min(0)
d_max = dataMat.max(0)
# 计算极差
d_ranges = d_max - d_min
# 创建输出矩阵
normDataSet = np.zeros(np.shape(dataMat))
print(normDataSet)
# 获得矩阵行数 .shape 获取矩阵的大小 3x3
m = dataMat.shape[0]
# 计算 (X - Xmin) 这部分 首先要创建Xmin矩阵 将d_min扩展到m行
# 需要使用np.tile 函数进行扩展 将d_min扩展成m行1列 变成m x 3 矩阵
normDataSet = dataMat - np.tile(d_min,(m,1))
print(normDataSet)
# 计算Y
normDataSet = normDataSet / np.tile(d_ranges,(m,1)) print(normDataSet)
return normDataSet

创建分类函数与分类器(kNN算法的实现)

(ps:每次都需要将测试数据与所有训练数据进行对比,感觉比较繁琐)

def classfy_fun(test_data, train_data, labels, k):
""" :param test_data: 测试集
:param train_data: 训练集
:param labels: 训练集标签
:param k: KNN 算法参数 选择距离最小的个数
:return: 分类结果
"""
# 计算训练集的矩阵行数
train_size = train_data.shape[0]
# 接下来按照欧氏距离进行元素距离计算 公式
# 将测试集扩充成与训练集相同行数 求差
diffMat = np.tile(test_data,(train_size,1)) - train_data
# 将差值矩阵的每个元素平方
sq_diffMat = diffMat**2
# 差值平方矩阵每行元素相加 axis = 1 是按行相加
sum_diffMat = sq_diffMat.sum(axis = 1)
# 对新的求和矩阵进行开方 得到距离值
distances = sum_diffMat ** 0.5
# 获得距离值中从小到大值的索引
sorted_distant = distances.argsort()
# 定义一个字典 存放标签 与 出现的数量
class_count = {}
for i in range(k):
# 找出前k个距离值最小的对应标签
temp_label = labels[sorted_distant[i]]
# 将标签作为 key 存放到字典中 出现次数作为 value
class_count[temp_label] = class_count.get(temp_label,0) + 1
# 将字典按照value 大小进行排序
sort_class_count = sorted(class_count.items(),key = operator.itemgetter(1))
return sort_class_count[0][0]
pass
# 创建分类器函数
def dating_class_test(): # 首先获取文件,将文件分成测试集和训练集
dating_Mat, dating_label = file2matric('datingdata.txt')
# 设置测试集的比例
test_ratio = 0.1
# 数据归一化
normMat = dataNorm(dating_Mat)
#获得矩阵的行数
m = normMat.shape[0]
# 计算测试集的数量
numTestData = int(m * test_ratio)
# 错误分类的数量
error_count = 0.0 for i in range(numTestData):
class_result = classfy_fun(dating_Mat[i,:], dating_Mat[numTestData:m,:],
dating_label[numTestData:m],4 )
print("分类结果:%s,实际分类:%s"%(class_result,dating_label[i]))
if class_result != dating_label[i]:
error_count += 1
# print("错误识别的数量:%f" %error_count)
print("正确率:%f%% \n" %((1 - error_count / numTestData)*100))

从结果看 识别率还是很低的,目前k值为4 ,可以改变k值看看正确率的变化

完整代码

 #!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
【KNN 实战】 """
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.lines as mlines
from matplotlib.font_manager import FontProperties
import operator # 提取文件中的数据 转换成矩阵
def file2matric(filename):
"""
disc:
param: filename: 导入数据文本
return: 数据矩阵
"""
f = open(filename,'r',encoding= 'utf-8')
# 获取文件的行数
lines_list = f.readlines()
num_of_lines = len(lines_list)
# 创建存放标签的列表
class_label_list = []
# 生成对应的空矩阵 zeros(2,3) 就是生成2行3列的0矩阵
returnMat = np.zeros((num_of_lines,3))
# 将文本中的数据放到矩阵中
for i in range(num_of_lines):
lines = lines_list[i].strip().split('\t')
# 将文本中的前3个数据放到矩阵中
returnMat[i,:] = lines[0:3]
# 将标签存到列表中
class_label_list.append(int(lines[-1])) # print(returnMat)
return returnMat, class_label_list def DrawScatter(dataMat,label_list):
# 导入中文字体,及字体大小
zhfont = FontProperties(fname='C:/Windows/Fonts/simsun.ttc', size=14)
# 绘制绘图窗口 2行2列
fig,ax = plt.subplots(2,2,figsize=(13,8))
# 不同标签赋予不同颜色
label_color = []
for i in label_list:
if i == 1:
label_color.append('black')
elif i == 2:
label_color.append('orange')
elif i == 3:
label_color.append('red')
# 开始绘制散点图 设定散点尺寸与透明度
scatter_size = 12
scatter_alpha = 0.5
# ===================散点图========================
ax[0][0].scatter(dataMat[:,0], dataMat[:,1],color = label_color,s = scatter_size ,alpha = scatter_alpha)
ax[0][1].scatter(dataMat[:, 1], dataMat[:, 2], color=label_color, s=scatter_size , alpha=scatter_alpha)
ax[1][0].scatter(dataMat[:, 0], dataMat[:, 2], color=label_color, s=scatter_size , alpha=scatter_alpha) # 坐标轴标题
title_list = ['每年获得的飞行常客里程数和玩视频游戏所消耗时间占比',
'每年获得的飞行常客里程数和每周消费的冰激淋公升数',
'玩视频游戏所消耗时间占比和每周消费的冰激淋公升数']
x_name_list = ['每年获得的飞行常客里程数','玩视频游戏所消耗时间占比','每周消费的冰激淋公升数']
y_name_list = ['玩视频游戏所消耗时间占比','每周消费的冰激淋公升数','每年获得的飞行常客里程数']
#设置图例
didntLike = mlines.Line2D([], [], color='black', marker='.',
markersize=6, label='didntLike')
smallDoses = mlines.Line2D([], [], color='orange', marker='.',
markersize=6, label='smallDoses')
largeDoses = mlines.Line2D([], [], color='red', marker='.',
markersize=6, label='largeDoses') p = 0
for i in range(2):
for j in range(2):
if p > 2:
break
# 设置坐标轴名称和标题
plt.setp(ax[i][j].set_title(u'%s'%(title_list[p]),FontProperties = zhfont),size=9, weight='bold', color='red')
plt.setp(ax[i][j].set_xlabel(u'%s'%(x_name_list[p]),FontProperties = zhfont), size=7, weight='bold', color='black')
plt.setp(ax[i][j].set_ylabel(u'%s'%(y_name_list[p]),FontProperties = zhfont), size=7, weight='bold', color='black')
p+=1
# 添加图例
ax[0][0].legend(handles=[didntLike, smallDoses, largeDoses])
ax[0][1].legend(handles=[didntLike, smallDoses, largeDoses])
ax[1][0].legend(handles=[didntLike, smallDoses, largeDoses])
plt.savefig('.\\123.png', bbox_inches='tight')
plt.show() # 对矩阵进行归一化处理
def dataNorm(dataMat):
"""
:param dataMat:
:return: 归一化后的数据集
归一化公式: Y = (X - Xmin)/(Xmax - Xmin)
"""
# max(0) min(0) 求出每列的最大值和最小值
d_min = dataMat.min(0)
d_max = dataMat.max(0)
# 计算极差
d_ranges = d_max - d_min
# 创建输出矩阵
normDataSet = np.zeros(np.shape(dataMat))
print(normDataSet)
# 获得矩阵行数 .shape 获取矩阵的大小 3x3
m = dataMat.shape[0]
# 计算 (X - Xmin) 这部分 首先要创建Xmin矩阵 将d_min扩展到m行
# 需要使用np.tile 函数进行扩展 将d_min扩展成m行1列 变成m x 3 矩阵
normDataSet = dataMat - np.tile(d_min,(m,1))
print(normDataSet)
# 计算Y
normDataSet = normDataSet / np.tile(d_ranges,(m,1)) print(normDataSet)
return normDataSet def classfy_fun(test_data, train_data, labels, k):
""" :param test_data: 测试集
:param train_data: 训练集
:param labels: 训练集标签
:param k: KNN 算法参数 选择距离最小的个数
:return: 分类结果
"""
# 计算训练集的矩阵行数
train_size = train_data.shape[0]
# 接下来按照欧氏距离进行元素距离计算 公式
# 将测试集扩充成与训练集相同行数 求差
diffMat = np.tile(test_data,(train_size,1)) - train_data
# 将差值矩阵的每个元素平方
sq_diffMat = diffMat**2
# 差值平方矩阵每行元素相加 axis = 1 是按行相加
sum_diffMat = sq_diffMat.sum(axis = 1)
# 对新的求和矩阵进行开方 得到距离值
distances = sum_diffMat ** 0.5
# 获得距离值中从小到大值的索引
sorted_distant = distances.argsort()
# 定义一个字典 存放标签 与 出现的数量
class_count = {}
for i in range(k):
# 找出前k个距离值最小的对应标签
temp_label = labels[sorted_distant[i]]
# 将标签作为 key 存放到字典中 出现次数作为 value
class_count[temp_label] = class_count.get(temp_label,0) + 1
# 将字典按照value 大小进行排序
sort_class_count = sorted(class_count.items(),key = operator.itemgetter(1))
return sort_class_count[0][0]
pass
# 创建分类器函数
def dating_class_test(): # 首先获取文件,将文件分成测试集和训练集
dating_Mat, dating_label = file2matric('datingdata.txt')
# 设置测试集的比例
test_ratio = 0.1
# 数据归一化
normMat = dataNorm(dating_Mat)
#获得矩阵的行数
m = normMat.shape[0]
# 计算测试集的数量
numTestData = int(m * test_ratio)
# 错误分类的数量
error_count = 0.0 for i in range(numTestData):
class_result = classfy_fun(dating_Mat[i,:], dating_Mat[numTestData:m,:],
dating_label[numTestData:m],4 )
print("分类结果:%s,实际分类:%s"%(class_result,dating_label[i]))
if class_result != dating_label[i]:
error_count += 1
# print("错误识别的数量:%f" %error_count)
print("正确率:%f%% \n" %((1 - error_count / numTestData)*100)) def main():
# reMat, label = file2matric('datingdata.txt')
# DrawScatter(reMat,label )
# dataNorm(reMat)
# 测试分类情况
dating_class_test()
pass if __name__ =='__main__':
main()

机器学习实战_KNN(一)的更多相关文章

  1. 机器学习实战笔记(Python实现)-08-线性回归

    --------------------------------------------------------------------------------------- 本系列文章为<机器 ...

  2. 机器学习实战笔记(Python实现)-06-AdaBoost

    --------------------------------------------------------------------------------------- 本系列文章为<机器 ...

  3. 机器学习实战笔记(Python实现)-05-支持向量机(SVM)

    --------------------------------------------------------------------------------------- 本系列文章为<机器 ...

  4. 机器学习实战笔记(Python实现)-04-Logistic回归

    --------------------------------------------------------------------------------------- 本系列文章为<机器 ...

  5. 机器学习实战笔记(Python实现)-03-朴素贝叶斯

    --------------------------------------------------------------------------------------- 本系列文章为<机器 ...

  6. 机器学习实战笔记(Python实现)-01-K近邻算法(KNN)

    --------------------------------------------------------------------------------------- 本系列文章为<机器 ...

  7. 机器学习实战笔记(Python实现)-02-决策树

    --------------------------------------------------------------------------------------- 本系列文章为<机器 ...

  8. 机器学习实战笔记(Python实现)-00-readme

    近期学习机器学习,找到一本不错的教材<机器学习实战>.特此做这份学习笔记,以供日后翻阅. 机器学习算法分为有监督学习和无监督学习.这本书前两部分介绍的是有监督学习,第三部分介绍的是无监督学 ...

  9. 《机器学习实战》 code debug

    摘要:最近在看<机器学习实战>,在code的过程中总是会报一些小错误,所以发下debug过的地方:由于是跳着看的,所以只是其中一部分,希望之后能把这本书我遇见的全部错误都在此更正下. 内容 ...

随机推荐

  1. JS 转换日期UTC类型

    前台取到的日期类型为UTC,"yyyy-MM-dd'T'HH:mm:ss.SSS",后台接收报错如下: org.springframework.http.converter.Htt ...

  2. Ganglia环境搭建并监控Hadoop分布式集群

    简介 Ganglia可以监控分布式集群中硬件资源的使用情况,例如CPU,内存,网络等资源.通过Ganglia可以监控Hadoop集群在运行过程中对集群资源的调度,作为简单地运维参考. 环境搭建流程 1 ...

  3. 记一次神奇的sql查询经历,group by慢查询优化

    一.问题背景 现网出现慢查询,在500万数量级的情况下,单表查询速度在30多秒,需要对sql进行优化,sql如下: 我在测试环境构造了500万条数据,模拟了这个慢查询. 简单来说,就是查询一定条件下, ...

  4. Linux 笔记 - 第二十章 配置 Nginx 反向代理和负载均衡

    一.简介 由于 Nginx 的反向代理和负载均衡功能经常被提及,所以将这两个功能单独提出来进行讲解. Nginx 其实仅仅是作为 Nginx Proxy 反向代理使用的,因为这个反向代理功能表现的效果 ...

  5. DirectX12 3D 游戏开发与实战第四章内容(下)

    Direct3D的初始化(下) 学习目标 了解Direct3D在3D编程中相对于硬件所扮演的角色 理解组件对象模型COM在Direct3D中的作用 掌握基础的图像学概念,例如2D图像的存储方式,页面翻 ...

  6. Failed to access IIS metabase.

    framework4.0 可这样 C:\Inetpub\AdminScripts>cd C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\ C:\WIN ...

  7. Mongodb关于查询返回指定字段的方法记录

    //通常指定字段由前端传入后台,例如params 前端以逗号分隔 //后端获取字段后操作如下: Query query = new Query(); if (params != null) { Str ...

  8. centos7 supervisor管理redis

    centos7 supervisor管理redis 标签(空格分隔): linux,redis 概念 Supervisor 相当强大,提供了很丰富的功能,不过我们可能只需要用到其中一小部分 super ...

  9. Netty源码分析 (十二)----- 心跳服务之 IdleStateHandler 源码分析

    什么是心跳机制? 心跳说的是在客户端和服务端在互相建立ESTABLISH状态的时候,如何通过发送一个最简单的包来保持连接的存活,还有监控另一边服务的可用性等. 心跳包的作用 保活Q:为什么说心跳机制能 ...

  10. at org.apache.jsp.WEB_002dINF.pages.login_jsp._jspInit( login_jsp.java:22)

    SEVERE: Servlet.service() for servlet jsp threw exception java.lang.NullPointerException at org.apac ...