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程序与系统shell交互的方式
Apr 09 Python
python实现学生管理系统
Jan 11 Python
python表格存取的方法
Mar 07 Python
Python统计单词出现的次数
Apr 04 Python
Python简单实现阿拉伯数字和罗马数字的互相转换功能示例
Apr 17 Python
深入浅析Python获取对象信息的函数type()、isinstance()、dir()
Sep 17 Python
利用Python裁切tiff图像且读取tiff,shp文件的实例
Mar 10 Python
Python实现从N个数中找到最大的K个数
Apr 02 Python
解决python Jupyter不能导入外部包问题
Apr 15 Python
Pycharm打开已有项目配置python环境的方法
Jul 03 Python
python工具——Mimesis的简单使用教程
Jan 16 Python
理解python中装饰器的作用
Jul 21 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判断所处服务器操作系统的类型
2013/06/20 PHP
php基于双向循环队列实现历史记录的前进后退等功能
2015/08/08 PHP
Laravel5.1自定义500错误页面示例
2016/10/09 PHP
在Laravel的Model层做数据缓存的实现
2019/09/26 PHP
laravel实现登录时监听事件,添加登录用户的记录方法
2019/09/30 PHP
为你的 Laravel 验证器加上多验证场景的实现
2020/04/07 PHP
Javascript中eval函数的使用方法与示例
2007/04/09 Javascript
解决jQuery插件tipswindown与hintbox冲突
2010/11/05 Javascript
jQuery插件datatables使用教程
2016/04/21 Javascript
jQuery中text() val()和html()的区别实例详解
2016/06/28 Javascript
常用的javascript设计模式
2017/01/11 Javascript
underscore之function_动力节点Java学院整理
2017/07/11 Javascript
微信小程序WebSocket实现聊天对话功能
2018/07/06 Javascript
详解新手使用vue-router传参时注意事项
2019/06/06 Javascript
jQuery HTML获取内容和属性操作实例分析
2020/05/20 jQuery
python套接字流重定向实例汇总
2016/03/03 Python
PyQt5每天必学之组合框
2018/04/20 Python
python3.4控制用户输入与输出的方法
2018/10/17 Python
Appium+python自动化怎么查看程序所占端口号和IP
2019/06/14 Python
更新pip3与pyttsx3文字语音转换的实现方法
2019/08/08 Python
python初步实现word2vec操作
2020/06/09 Python
利用python绘制中国地图(含省界、河流等)
2020/09/21 Python
详解Python中的文件操作
2021/01/14 Python
纯CSS3实现8组超炫酷鼠标滑过图片动画
2016/03/16 HTML / CSS
南非最大的花卉和送礼服务:NetFlorist
2017/09/13 全球购物
生物有机护肤品:Aurelia Probiotic Skincare
2018/01/31 全球购物
伦敦香水公司:The London Perfume Company
2019/11/13 全球购物
阿联酋手表和配饰购物网站:Rivolishop
2019/11/25 全球购物
戴尔荷兰官方网站:Dell荷兰
2020/10/04 全球购物
小学一年级评语大全
2014/04/22 职场文书
关于雷锋的演讲稿
2014/05/10 职场文书
送温暖献爱心活动总结
2014/07/08 职场文书
工作态度不好检讨书
2015/05/06 职场文书
七年级英语教学反思
2016/02/15 职场文书
会议开幕致辞怎么写
2016/03/03 职场文书
浅谈PHP7中的一些小技巧
2021/05/29 PHP