机器学习实战_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过的地方:由于是跳着看的,所以只是其中一部分,希望之后能把这本书我遇见的全部错误都在此更正下. 内容 ...
随机推荐
- SpringCloud学习笔记(4):Hystrix容错机制
简介 在微服务架构中,微服务之间的依赖关系错综复杂,难免的某些服务会出现故障,导致服务调用方出现远程调度的线程阻塞.在高负载的场景下,如果不做任何处理,可能会引起级联故障,导致服务调用方的资源耗尽甚至 ...
- Unity3D_03_代码及效率优化总结
1.在使用数组或ArrayList对象时应当注意: length = myArray.Length; ;i<length;i++) { } 避免 ;i<myArray.Length;i++ ...
- SqlServer2014怎样还原数据库
场景 在SqlServer2014企业版上怎样进行数据库的还原,首先你得有一个其他数据 的备份文件. 实现 打开cmd,输入sql,打开SqlServer 2014 Management Studio ...
- Winforn中设置ZedGraph曲线图的属性、坐标轴属性、刻度属性
场景 C#窗体应用中使用ZedGraph曲线插件绘制图表: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/99716066 在上面 ...
- jmeter性能分析
1.硬件要求:包括客户端和服务端的cpu,mem,network,disk等,这些硬件设备必须满足性能测试的前提下,才能进行性能测试,否则得到的各项指标不一定是正确的 2.场景分析: 测试前的准备工作 ...
- 54 (OC)* 网络七层架构
一:TCP/IP协议 二:七层协议 1:物理层 物理层为设备之间的数据通信提供传输媒体及互连设备,为数据传输提供可靠的环境. 1.1:传输媒体和互连设备 物理层的媒体包括架空明线.平衡 ...
- [Leetcode] 第357题 计算各个位数不同的数字个数
一.题目描述 给定一个非负整数 n,计算各位数字都不同的数字 x 的个数,其中 0 ≤ x < 10n . 示例: 输入: 2 输出: 91 解释: 答案应为除去 11,22,33,44,55, ...
- Linux下一键安装包的基础上安装SVN及实现nginx web同步更新
Linux下一键安装包的基础上安装SVN及实现nginx web同步更新 一.安装 1.查看是否安装cvs rpm -qa | grep subversion 2.安装 yum install sub ...
- 月光宝盒之时间魔法--java时间的前生今世
月光宝盒花絮 “曾经有一份真诚的爱情摆在我的面前,但是我没有珍惜,等到了失去的时候才后悔莫及,尘世间最痛苦的事莫过于此.如果可以给我一个机会再来一次的话,我会跟那个女孩子说我爱她,如果非要把这份爱加上 ...
- SpringBoot之简单入门
一,spring boot 是什么? spring boot的官网是这样说的: Spring Boot makes it easy to create stand-alone, production- ...