Python机器学习之KNN近邻算法


Posted in Python onMay 14, 2021

一、KNN概述

简单来说,K-近邻算法采用测量不同特征值之间的距离方法进行分类

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

工作原理:存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一个数据与所属分类的对应关系(训练集)。输入没有标签的新数据之后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签(测试集)。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处。(通常k不大于20)

二、使用Python导入数据

我们先写入一段代码

from numpy import *		# 导入numpy模块
import operator		# 导入operator模块
def createDataSet():		# 创建数据集函数
	# 构建一个数组存放特征值
    group = array(
        [[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]]
    )
    # 构建一个数组存放目标值
    labels = ['A', 'A', 'B', 'B']
    return group, labels

此处稍微介绍一下numpy这个包吧

三、numpy.array()

NumPy的主要对象是同种元素的多维数组。这是一个所有的元素都是一种类型、通过一个正整数元组索引的元素表格(通常是元素是数字)。
在NumPy中维度(dimensions)叫做轴(axes),轴的个数叫做秩(rank,但是和线性代数中的秩不是一样的,在用python求线代中的秩中,我们用numpy包中的linalg.matrix_rank方法计算矩阵的秩
线性代数中秩的定义:设在矩阵A中有一个不等于0的r阶子式D,且所有r+1阶子式(如果存在的话)全等于0,那末D称为矩阵A的最高阶非零子式,数r称为矩阵A的秩,记作R(A)。

四、实施KNN分类算法

依照KNN算法,我们依次来

先准备好四个需要的数据

  • inX:用于分类的输入向量inX
  • dataSet:输入的训练样本集dataSet
  • labels:标签向量labels(元素数目和矩阵dataSet的行数相同)
  • k:选择最近邻居的数目

五、计算已知类别数据集中的点与当前点之间的距离

使用欧式距离:

Python机器学习之KNN近邻算法

六、完整代码

# 返回矩阵的行数
dataSetSize = dataSet.shape[0]	
# 列数不变,行数变成dataSetSize列
diffMat = tile(inX, (dataSetSize, 1)) - dataSet
sqDiffMat = diffMat ** 2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.5

第一行

# 返回矩阵的行数
dataSetSize = dataSet.shape[0]	
# 以第一步的数据为例
answer:4		# 4行

第二行

inX = [1. , 0.]
# 列数不变,行数变成dataSetSize列
diffMat = tile(inX, (dataSetSize, 1)) - dataSet

# tile(inX, (dataSetSize, 1))
inX = [
	[1. , 0.],
	[1. , 0.],
	[1. , 0.],
	[1. , 0.]
]
# inX - dataSet两个矩阵相减(行列相等相加相减才有意义)
dataSet = [
		[1. , 1.1],
        [1. , 1. ],
        [0. , 0. ],
        [0. , 0.1]
]
diffMat = [
	[0. , -1.1],
	[0. , -1.],
	[1. , 0.],
	[1. , -0.1]
]

第三行

# 求平方差
sqDiffMat = diffMat * 2

第四行

# 计算矩阵中每一行元素之和
# 此时会形成一个多行1列的矩阵
sqDistances = sqDiffMat.sum(axis=1)

第五行

# 开根号
distances = sqDistances**0.5

按照距离递增次序排序

# 对数组进行排序
sortedDistIndicies = distances.argsort()

选择与当前点距离最小的k个点

classCount = {}		# 新建一个字典
# 确定前k个距离最小元素所在的主要分类
for i in range(k):
	# voteIlabel的取值是labels中sortedDistIndicies[i]的位置
	voteIlabel = labels[sortedDistIndicies[i]]
	classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1

确定前k个点所在类别的出现概率

# 排序
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)

###11# 返回前k个点出现频率最高的类别作为当前点的预测分类

return sortedClassCount[0][0]

刚刚试一试C++的版本…小心,救命

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
int sum_vector(std::vector<int>& v) {
	int sum = 0;
	for (int i = 0; i < v.size(); ++i) {
		sum = v[i] + sum;
	}
	return sum;
}
int knn(int k) {
	using std::cout;
	using std::endl;
	using std::vector;
	vector<vector<int>> x;	
	vector<int> x_sample = {2, 3, 4};	
	for (int i = 0; i < 4; ++i) {
		x.push_back(x_sample);
	}
	vector<int> y = {1, 1, 1, 1};
	int dataSetSize = x.size();		

	vector<int> x_test = {4, 3, 4};
	vector<vector<int>> x_test_matrix;
	for (int i = 0; i < dataSetSize; ++i) {
		x_test_matrix.push_back(x_test);
	}
	vector<int> v_total;
	for (int i = 0; i < dataSetSize; ++i) {
		for (int j = 0; j < x_test_matrix[i].size(); ++j) {
			x_test_matrix[i][j] = x_test_matrix[i][j] - x[i][j];
			x_test_matrix[i][j] = x_test_matrix[i][j] * 2;
		}
		int sum_vec = sum_vector(x_test_matrix[i]);
		v_total.push_back(sqrt(sum_vec));
	}
	sort(v_total.begin(), v_total.end());
	std::map<int, int> mp;
	for (int i = 0; i < k; ++i) {
		int label = y[v_total[i]];
		mp[label] += 1;
	}
	int max_end_result = 0;
	for (std::map<int, int>::iterator it = mp.begin(); it != mp.end(); it++) {
		if (it->first > max_end_result) {
			max_end_result = it->first;
		}
	}
	return max_end_result;
}
int main() {
	int k = 12;
	int value = knn(k);
	std::cout << "result:\n" << std::endl;
	return 0;
}

七、数据处理、分析、测试

处理excel和txt数据

excel数据是矩阵数据,可直接使用,在此不做处理。

文本txt数据需要一些数据处理

def file2matrix(filename):
	fr = open(filename)
	# 读取行数据直到尾部
	arrayOLines = fr.readlines()
	# 获取行数
	numberOfLines = len(arrayOLines)
	# 创建返回shape为(numberOfLines, 3)numpy矩阵
	returnMat = zeros((numberOfLines, 3))
	classLabelVector = []
	index = 0
	for line in arrayOLines:
		# 去除首尾的回车符
		line = line.strip()
		# 以tab字符'\t'为符号进行分割字符串
		listFromLine = line.split('\t')
		# 选取前3个元素,把他们存储到特征矩阵中
		returnMat[index, :] = listFromLine[0: 3]
		# 把目标变量放到目标数组中
		classLabelVector.append(int(listFromLine[-1]))
		index += 1
	return returnMat, classLabelVector

数据归一化和标准化

在数值当中,会有一些数据大小参差不齐,严重影响数据的真实性,因此,对数据进行归一化和标准化是使得数据取值在一定的区间,具有更好的拟合度。

例如归一化就是将数据取值范围处理为0到1或者-1到1之间

# max:最大特征值
# min:最小特征值
newValue = (oldValue - min)/(max-min)

写个函数

def autoNorm(dataSet):
	# min(0)返回该矩阵中每一列的最小值
	minVals = dataSet.min(0)
	# max(0)返回该矩阵中每一列的最大值
	maxVals = dataSet.max(0)
	# 求出极值
	ranges = maxVals - minVals
	# 创建一个相同行列的0矩阵
	normDataSet = zeros(shape(dataSet))
	# 得到行数
	m = dataSet.shape[0]
	# 得到一个原矩阵减去m倍行1倍列的minVals
	normDataSet = dataSet - tile(minVlas, (m,1))
	# 特征值相除
	normDataSet = normDataSet/tile(ranges, (m, 1))
	return normDataSet, ranges, minVals

归一化的缺点:如果异常值就是最大值或者最小值,那么归一化也就没有了保证(稳定性较差,只适合传统精确小数据场景)

标准化可查

八、鸢尾花数据测试

既然已经了解其内置的算法了,那么便调库来写一个吧

from sklearn.datasets import load_iris      # 导入内置数据集
from sklearn.model_selection import train_test_split        # 提供数据集分类方法
from sklearn.preprocessing import StandardScaler        # 标准化
from sklearn.neighbors import KNeighborsClassifier      # KNN


def knn_iris():
    # 获得鸢尾花数据集
    iris = load_iris()
    # 获取数据集
    # random_state为随机数种子,一个数据集中相等的行不能大于6
    x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=6)
    # 特征工程:标准化
    transfer = StandardScaler()
    # 训练集标准化
    x_train = transfer.fit_transform(x_train)
    # 测试集标准化
    x_test = transfer.transform(x_test)
    # 设置近邻个数
    estimator = KNeighborsClassifier(n_neighbors=3)
    # 训练集测试形成模型
    estimator.fit(x_train, y_train)

    # 模型预估
    # 根据预测特征值得出预测目标值
    y_predict = estimator.predict(x_test)
    print("y_predict: \n", y_predict)
    # 得出预测目标值和真实目标值之间是否相等
    print("直接比对真实值和预测值:\n", y_test == y_predict)
    # 计算准确率
    score = estimator.score(x_test, y_test)
    print("准确率为:\n", score)


def main():
    knn_iris()


if __name__ == '__main__':
    main()

九、RESULT

Python机器学习之KNN近邻算法

到此这篇关于Python机器学习之KNN近邻算法的文章就介绍到这了,更多相关Python近邻算法内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
简单介绍Python中的try和finally和with方法
May 05 Python
Python基于回溯法子集树模板解决全排列问题示例
Sep 07 Python
python配置grpc环境
Jan 01 Python
python实现贪吃蛇游戏
Mar 21 Python
使用Python3内置文档高效学习以及官方中文文档
May 19 Python
Python 使用PyQt5 完成选择文件或目录的对话框方法
Jun 27 Python
python之pexpect实现自动交互的例子
Jul 25 Python
Python 3 判断2个字典相同
Aug 06 Python
Python 类的私有属性和私有方法实例分析
Sep 29 Python
如何基于python实现脚本加密
Dec 28 Python
Python实现桌面翻译工具【新手必学】
Feb 12 Python
python 指定源路径来解决import问题的操作
Mar 04 Python
Python爬虫基础讲解之请求
自己搭建resnet18网络并加载torchvision自带权重的操作
May 13 #Python
如何使用flask将模型部署为服务
May 13 #Python
教你用python控制安卓手机
Python数据分析入门之数据读取与存储
May 13 #Python
python执行js代码的方法
pytorch加载预训练模型与自己模型不匹配的解决方案
May 13 #Python
You might like
一个PHP的String类代码
2010/04/20 PHP
php获取ip及网址的简单方法(必看)
2017/04/01 PHP
基于php流程控制语句和循环控制语句(讲解)
2017/10/23 PHP
Laravel timestamps 设置为unix时间戳的方法
2019/10/11 PHP
PHP发送邮件确认验证注册功能示例【修改别人邮件类】
2019/11/09 PHP
js 自定义的联动下拉框
2010/02/07 Javascript
避免回车键导致的页面无意义刷新的解决方法
2011/04/12 Javascript
给页面渲染时间加速 干掉Dom Level 0 Event
2012/12/19 Javascript
jQuery 的全选(全非选)即取得被选中的值使用介绍
2013/11/12 Javascript
基于mouseout和mouseover等类似事件的冒泡问题解决方法
2013/11/18 Javascript
jQuery数据缓存用法分析
2015/02/20 Javascript
jQuery实现两款有动画功能的导航菜单代码
2015/09/16 Javascript
Bootstrap 布局组件(全)
2016/07/18 Javascript
JS获取url参数、主域名的方法实例分析
2016/08/03 Javascript
微信小程序小组件 基于Canvas实现直播点赞气泡效果
2020/05/29 Javascript
Node.js常用工具之util模块
2017/03/09 Javascript
详解JavaScript中return的用法
2017/05/08 Javascript
JS动态添加的div点击跳转到另一页面实现代码
2017/09/30 Javascript
ES6中Symbol、Set和Map用法详解
2019/08/20 Javascript
element的el-table中记录滚动条位置的示例代码
2019/11/06 Javascript
vue通过v-html指令渲染的富文本无法修改样式的解决方案
2020/05/20 Javascript
原生JS实现微信通讯录
2020/06/18 Javascript
VUE动态生成word的实现
2020/07/26 Javascript
Python打造出适合自己的定制化Eclipse IDE
2016/03/02 Python
搭建Python的Django框架环境并建立和运行第一个App的教程
2016/07/02 Python
python 读取修改pcap包的例子
2019/07/23 Python
PyTorch中Tensor的维度变换实现
2019/08/18 Python
Python 使用 Pillow 模块给图片添加文字水印的方法
2019/08/30 Python
Python xml、字典、json、类四种数据类型如何实现互相转换
2020/05/27 Python
Pycharm安装Qt Design快捷工具的详细教程
2020/11/18 Python
北美最大的零售退货翻新商:VIP Outlet
2019/11/21 全球购物
责任胜于能力演讲稿
2014/05/20 职场文书
2015年办公室主任工作总结
2015/04/09 职场文书
2015年秋季小学开学标语
2015/07/16 职场文书
CSS3 制作精美的定价表
2021/04/06 HTML / CSS
关于python中readlines函数的参数hint的相关知识总结
2021/06/24 Python