机器学习实战_KNN(一)
【是什么】
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(一)的更多相关文章
- 机器学习实战笔记(Python实现)-08-线性回归
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-06-AdaBoost
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-05-支持向量机(SVM)
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-04-Logistic回归
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-03-朴素贝叶斯
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-01-K近邻算法(KNN)
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-02-决策树
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-00-readme
近期学习机器学习,找到一本不错的教材<机器学习实战>.特此做这份学习笔记,以供日后翻阅. 机器学习算法分为有监督学习和无监督学习.这本书前两部分介绍的是有监督学习,第三部分介绍的是无监督学 ...
- 《机器学习实战》 code debug
摘要:最近在看<机器学习实战>,在code的过程中总是会报一些小错误,所以发下debug过的地方:由于是跳着看的,所以只是其中一部分,希望之后能把这本书我遇见的全部错误都在此更正下. 内容 ...
随机推荐
- guava multimap介绍
引用一篇别人的博客,理解理解 http://vipcowrie.iteye.com/blog/1517338
- airflow使用本地时区
在airflow中使用的时间是utc时间,而更多时候我们希望的是使用本地时间,于是在定义airflow定时任务的时候,涉及到了时间的转换. 1.python中本地时间和utc时间的转换 查看国内可 ...
- Linux、Windows 和 Mac 中的换行符对比
原文地址:Linux.Windows 和 Mac 中的换行符对比 博客地址:http://www.moonxy.com 一.前言 经常使用 Window.Linux 等不同操作系统的开发者,在处理文本 ...
- 19 (OC)* RunLoop
面试题 1:讲讲RunLoop,项目中有用到吗? 2:RunLoop内部实现逻辑? 3:Runloop和线程的关系? 4:timer 与 Runloop 的关系? 5:程序中添加每3秒响应一次的NST ...
- 云服务器 ECS Linux 系统 MySQL 备份的导入导出
MySQL 备份的导出 注意: 如果您使用的是帮助中心的一键环境配置,那么 MySQL 的安装目录是 /alidata/server/mysql. 如果您将 MySQL 安装到其他目录,您需要输入您 ...
- 自己制作一个简单的操作系统二[CherryOS]
自己制作一个简单的操作系统二[CherryOS] 我的上一篇博客 自己制作一个简单的操作系统一[环境搭建], 详细介绍了制作所需的前期准备工作 一. 一点说明 这个操作系统只是第一步, 仅仅是开机显示 ...
- vue-router之路由元信息
路由元信息?(黑人问号脸???)是不是这么官方的解释很多人都会一脸懵?那么我们说meta,是不是很多人恍然大悟,因为在项目中用到或者看到过呢? 是的,路由元信息就是我们定义路由时配置的meta字段:那 ...
- Spring MVC-从零开始-@RequestMapping结合@PathVariable (从URL路径中取值,作用于函数参数)
1.可以直接在RequestMapping中value元素中使用{key}描述属性键 2.也可以在{key}中使用正则限定key的取值范围,从而限定url的变化范围 package com.jt; i ...
- 配置Redis(远程访问及授权设置)
配置Redis(远程访问及授权设置) 1.将redis.conf里面的bind 127.0.0.1这一行注释掉,添加自己服务器的IP 2. 还有,找到protected-mode这行, 将改为yes. ...
- pikachu-数字型注入(post)#手工注入
1, 因为是post型,所以需要抓取数据包 2, 测试结果为数字型注入 提交恒等的语句可以查询到所有的数据信息 3, 使用UNION联合查询法 判断字段数,测试为2个字段时没有报错,所以可以判断字段数 ...