凌云时刻 · 技术

导读:上一篇笔记主要介绍了NumPy,Matplotlib和Scikit Learn中Datasets三个库的用法,以及基于欧拉定理的kNN算法的基本实现。这一篇笔记的主要内容是通过PyCharm封装kNN算法并且在Jupyter Notebook中调用,以及计算器算法的封装规范,kNN的k值如何计算,如何使用Scikit Learn中的kNN算法。

作者 | 计缘

来源 | 凌云时刻(微信号:linuxpk)

封装kNN算法

上一篇笔记中我们对kNN算法在Jupyter Notebook中进行了实现,但是想要复用这个算法就很不方便,所以我们来看看如何在PyCharm中封装算法,并且在Jupyter Notebook中进行调用。

PyCharm的配置这里我就不再累赘,如图所示,我们创建了一个Python文件kNN.py,然后定义了kNNClassify方法,该方法有4个参数,分别是kNN算法的k值,训练样本特征数据集XTrain,训练样本类别数据集yTrain,预测特征数据集x。该方法中的实现和在Jupyter Notebook中实现的一模一样,只不过加了三个断言,让方法的健壮性更好一点。我们给出N维欧拉定理

# kNN.py
import numpy as np
from math import sqrt
from collections import Counterdef kNNClassify(k, XTrain, yTrain, x):assert 1 <= k <= XTrain.shape[0], "k 的取值范围不正确"assert XTrain.shape[0] == yTrain.shape[0], "训练样本数据行数应该与训练结果集行数相同"assert XTrain.shape[1] == x.shape[0], "训练样本数据特性个数应该与被预测数据特性个数相同"distances = [sqrt(np.sum((xTrain - x) ** 2)) for xTrain in XTrain]nearest = np.argsort(distances)topKy = [yTrain[i] for i in nearest[:k]]votes = Counter(topKy)return votes.most_common(1)[0][0]

这样我们就在PyCharm中封装好了kNN算法的方法,我们再来看看如何在Jupyter Notebook中调用封装好的方法呢,这就需要使用%run这个

import numpy as npraw_data_X = [[3.393533211, 2.331273381],[3.110073483, 1.781539638],[1.343808831, 3.368360954],[3.582294042, 4.679179110],[2.280362439, 2.866990263],[7.423436942, 4.696522875],[5.745051997, 3.533989803],[9.172168622, 2.511101045],[7.792783481, 3.424088941],[7.939820817, 0.791637231]]
raw_data_y = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]XTrain = np.array(raw_data_X)
yTrain = np.array(raw_data_y)x = np.array([8.093607318, 3.365731514])# 使用%run命令可以引入Python文件,并可使用该Python文件中定义的属性和方法
%run ../pycharm/kNN.py
predicty = kNNClassify(6, XTrain, yTrain, x)
predicty
# 结果
1

机器学习流程

这一小节我们来看看机器学习的大概流程是怎样的,如下图所示:

监督学习算法首先需要的是训练数据集,然后通过一个机器学习算法生成一个模型,最后就可以用这个模型来预测新的数据得到结果。通常,我们将使用机器学习生成模型的过程用fit来表示,使用模型预测新的数据的过程用predict来表示。这就是机器学习最基本的一个流程。

在第一篇笔记中,介绍了线性回归的概念,我们最后得到了一个二元线性回归的公式:

这个公式其实就是通过线性回归算法得到的模型,通过fit过程,训练模型得到ab,然后通过predict过程预测新的样例数据得到结果。

但是我们发现kNN算法不存在训练模型的过程,因为新的样例数据其实是需要通过训练数据集来进行预测的,所以换个角度来看,kNN算法的模型就是它的训练数据集,在上图中模型阶段其实就是把训练数据集复制了一份作为模型来使用,那么对于fit和predict过程而言,kNN算法的predict过程其实是核心,而fit过程非常简单。

使用Scikit Learn中的kNN算法

这一节我们来看看如何使用Scikit Learn中封装的kNN算法:

# 导入Scikit Learn中的kNN算法的类库
from sklearn.neighbors import KNeighborsClassifier
# 初始化kNN算法分类器的实例,参数n_neighbors就是k值
kNNClassifier = KNeighborsClassifier(n_neighbors=6)
# 训练,拟合模型
kNNClassifier.fit(XTrain, yTrain)
# 预测新的样例数据,该方法接受的参数类型为二维数组,如果只有一行也需要转换为一行的二维数组
kNNClassifier.predict(x.reshape(1, -1))
# 结果
array([1])

从示例代码中可以看出,Scikit Learn中封装的kNN算法严格遵从了上一节介绍的机器学习的基本流程,其实不止是kNN算法,Scikit Learn中的所有机器学习算法都遵从这个基本流程。

重新封装kNN算法

所以我们可以优化一下我们之前封装的kNN算法的方法,将其封装为类似Scikit Learn中的方式:

class KNNClassifier:# 初始化kNN分类器def __init__(self, k):assert k >= 1, "k 值不能小于1"self.k = kself._XTrain = Noneself._yTrain = None# 根据训练数据集XTrain和yTrain训练kNN分类器,在kNN中这一步就是复制训练数据集def fit(self, XTrain, yTrain):assert XTrain.shape[0] == yTrain.shape[0], \"训练样本特征数据集的行数要与训练样本分类结果数据集的行数相同"assert XTrain.shape[0] >= self.k, \"训练样本特征数据集的行数,既样本点的数量要大于等于k值"self._XTrain = XTrainself._yTrain = yTrainreturn self# 输入样本数据,根据模型进行预测def predict(self, XPredict):assert self._XTrain is not None and self._yTrain is not None, \"在执行predict方法前必须先执行fit方法"assert XPredict.shape[1] == self._XTrain.shape[1], \"被预测数据集的特征数,既列数必须与模型数据集中的特征数相同"ypredict = [self._predict(x) for x in XPredict]return np.array(ypredict)# 实现私有的预测方法,kNN算法的核心代码def _predict(self, x):assert x.shape[0] == self._XTrain.shape[1], \"输入的样本数据的特征数量必须等于模型数据,既训练样本数据的特征数量"distance = [sqrt(np.sum((xTrain - x) ** 2)) for xTrain in self._XTrain]nearest = np.argsort(distance)topK = [self._yTrain[i] for i in nearest[:self.k]]votes = Counter(topK)return votes.most_common(1)[0][0]def __repr__(self):return "kNN(k=%d)" % self.k

上面的代码清晰的定义了fitpredict方法,至于_predict这个私有方法可以随意,可以将逻辑直接写在predict方法里,也可以拆分出来。然后我们在Jupyter Notebook中再来使用一下我们封装的kNN算法:

%run ../pycharm/kNN/kNN.py
myKNNClassifier = KNNClassifier(6)
myKNNClassifier.fit(XTrain, yTrain)
# 结果
kNN(k=6)
xTrain = x.reshape(1, -1)
myKNNClassifier.predict(xTrain)
# 结果
array([1])

判断机器学习算法的性能

现在大家应该知道机器算法的目的主要是训练出模型,然后输入样本,通过模型来预测结果,可见这个模型是非常关键的,模型的好坏直接影响预测结果的准确性,继而对实际运用会产生巨大的影响。模型的训练除了机器学习算法以外,对它影响比较大的还有训练样本数据,我们在实现kNN算法时,是将所有的样本数据用于训练模型,那么模型训练出来后就已经没有数据供我们验证模型的好坏了,只能直接投入真实环境使用,这样的风险是很大的。

所以为了避免上述这种情况,最简单的做法是将所有训练样本数据进行切分,将大部分数据用于训练模型,而另外一小部分数据用来测试训练出的模型,这样如果我们用测试数据发现这个模型不够好,那么我们就有机会在将模型投入真实环境使用之前改进算法,训练出更好的模型。

我们来看看如何封装拆分训练数据的方法:

import numpy as np# 训练样本数据 X 和 y 按照 test_radio 分割成 X_train, y_train, X_test, y_test
def train_test_split(X, y, test_radio = 0.2, seed = None):assert X.shape[0] == y.shape[0], \"训练样本特征数据集的行数要与训练样本分类结果数据集的行数相同"assert 0.0 <= test_radio <= 1.0, \"test_radio 的值必须在 0 到 1 之间"# 如果 seed 有值,将其设置进numpy的随机函数中if seed:np.random.seed(seed)shuffled_indexes = np.random.permutation(len(X))test_size = int(len(X) * test_radio)test_indexes = shuffled_indexes[:test_size]train_indexes = shuffled_indexes[test_size:]X_train = X[train_indexes]y_train = y[train_indexes]X_test = X[test_indexes]y_test = y[test_indexes]return X_train, y_train, X_test, y_test

我们来解读一下上面的代码:

  • 首先train_test_split函数有四个参数,两个必填参数,两个非必填有默认值的参数。X是训练样本特征数据集,y是训练样本分类结果数据集,test_radio是设置训练数据和测试数据的比例,seed就很好理解了,就是NumPy的随机函数提供的随机种子机制。

  • 上面代码中有一个方法大家之前应该没见过,那就是permutation(x),该方法表示返回一个乱序的一维向量,元素从0到x,所以shuffled_indexes是一个乱序的一维向量数组,它的元素总数为训练样本数据的总数,既训练样本数据矩阵的行数,元素的范围从0到训练样本数据的总数。

  • 根据test_radio计算出需要分割出的测试数据数量test_size

  • 根据test_sizeshuffled_indexes中取出test_indexestrain_indexes,这两个数组中存的元素就是作为索引来用的。

  • 根据test_indexestrain_indexesXy中得到X_trainy_trainX_testy_test

之前在Jupyter Notebook中我们使用%run命令使用我们封装的代码 ,这一节我们来看看如何使用import的方式使用我们自己封装的代码。其实这和Jupyter Notebook没多大关系,我们需要做的只是给Python设置一个搜索包的路径而已,这里这会对MacOS,以及安装了Anaconda的环境作以说明,Windows系统大同小异。

首先找到路径/anaconda3/lib/python3.6/site-packages,在该路径下创建一个文件XXX.pth,该文件的扩展名必须为pth,文件名称可以随意。然后在该文件中输入你希望Python搜索包的绝对路径即可。

设置完搜索路径后,我们需要修改一下PyCharm中的目录结构:

我新建了一个目录名为myMLkNN.py是我们之前封装的kNN算法相关的方法,modelSelection.py里就是我们刚才封装好的拆分训练和测试数据的方法,另外还增加了一个__init__.py的文件,因为有了这个文件,myML就变为了一个包。__init__.py的作用这里不做过多解释。

这样我们就可以在Jupyter Notebook中用import的方式导入我们封装的模块了:

from myML.modelSelection import train_test_split
X_train, y_train, X_test, y_test = train_test_split(X, y)
X_train.shape
# 结果
(120, 4)
y_train.shape
# 结果
(120,)
X_test.shape
# 结果
(30, 4)
y_test.shape
# 结果
(30,)

这样就可以很方便的使用我们封装的模块了,下面我们来看看怎么判断我们封装的kNN算法的好坏程度:

# 先用训练数据训练模型,然后输入测试样本特征数据,得到预测结果
from myML.kNN import KNNClassifier
my_knn_classifier = KNNClassifier(6)
my_knn_classifier.fit(X_train, y_train)
my_y_test = my_knn_classifier.predict(X_test)
my_y_test
# 结果
array([1, 0, 1, 1, 0, 1, 2, 2, 0, 1, 0, 1, 2, 1, 2, 1, 0, 1, 2, 2, 1, 1, 1,1, 0, 1, 2, 1, 1, 2])
# 用预测出的结果和测试样本分类结果数据做对比,得出准确率
y_test
# 结果
array([1, 0, 1, 1, 0, 1, 2, 2, 0, 1, 0, 1, 2, 1, 2, 1, 0, 1, 2, 2, 1, 1, 1,1, 0, 1, 1, 1, 1, 2])sum(my_y_test == y_test) / len(y_test)
# 结果,准确率为96.67%
0.96666666666666667

这样我们就得出了一个算法的好坏程度。

END

往期精彩文章回顾

机器学习笔记(三):NumPy、Matplotlib、kNN算法

机器学习笔记(二):矩阵、环境搭建、NumPy

机器学习笔记(一):机器的学习定义、导数和最小二乘

Kafka从上手到实践 - 实践真知:搭建Kafka相关的UI工具

Kafka从上手到实践 - Kafka集群:启动Kafka集群

Kafka从上手到实践 - Kafka集群:Kafka Listeners

Kafka从上手到实践 - Kafka集群:配置Broker

Kafka从上手到实践:搭建Zookeeper集群

Kafka从上手到实践-Zookeeper CLI:CRUD zNode

Kafka从上手到实践 - 初步认知:Zookeeper

长按扫描二维码关注凌云时刻

每日收获前沿技术与科技洞见

机器学习笔记(四):kNN算法 | 凌云时刻相关推荐

  1. 机器学习笔记(5) KNN算法

    这篇其实应该作为机器学习的第一篇笔记的,但是在刚开始学习的时候,我还没有用博客记录笔记的打算.所以也就想到哪写到哪了. 你在网上搜索机器学习系列文章的话,大部分都是以KNN(k nearest nei ...

  2. 机器学习笔记之EM算法(一)隐变量与EM算法公式的收敛性

    机器学习笔记之EM算法--隐变量与EM算法公式的收敛性 引言 隐变量 示例1 示例2 EM算法 包含隐变量的混合概率模型 EM算法的表达形式 EM算法的收敛性 EM算法的收敛性证明的条件与目标 EM算 ...

  3. 机器学习笔记——支持向量机SMO算法完整版代码分析

    机器学习笔记--支持向量机SMO算法完整版代码分析 代码大体分析 外循环 参数类 内循环 KKT条件判断 eCache参数 完整SMO代码 添加核函数代码 代码参考书籍:<机器学习实战> ...

  4. 机器学习笔记之EM算法(二)EM算法公式推导过程

    机器学习笔记之EM算法--EM算法公式推导过程 引言 回顾:EM算法公式 推导过程 引言 上一节介绍了隐变量和EM算法,以及 以EM算法公式为条件,证明了随着EM算法迭代步骤的增加,每次迭代得到新的模 ...

  5. 机器学习实战(笔记)------------KNN算法

    1.KNN算法 KNN算法即K-临近算法,采用测量不同特征值之间的距离的方法进行分类. 以二维情况举例:         假设一条样本含有两个特征.将这两种特征进行数值化,我们就可以假设这两种特种分别 ...

  6. python的knn算法list_机器学习实战学习笔记1——KNN算法

    一.KNN算法概述: 1.KNN算法的工作原理是: (1)存在一个训练样本集,并且知道样本集中每一数据与所属分类的对应关系,即每个数据都存在分类标签. (2)若此时输入不带标签的新数据之后,将新数据的 ...

  7. 机器学习入门 —— 超级详细的KNN算法学习笔记、KNN算法的三要素、KNN算法的优缺点

    文章目录 KNN(K nearest neighbors) K值的选择和影响 k取值偏小 k取值偏大 样本点距离的计算方式 闵可夫斯基距离 曼哈顿距离 欧几里得距离 切比雪夫距离 余弦距离 决策函数的 ...

  8. 机器学习:基于Knn算法的用户属性判断方案设计

    本文作者通过Knn算法进行了一次用户判断预测的流程,文章为作者根据自身经验所做出的总结,希望通过此文能够加深你对Knn算法的认识. knn算法简介 K最近邻(k-Nearest Neighbor,KN ...

  9. 【机器学习实战】KNN算法

    机器学习作为人工智能的重要分支,同时也是数据挖掘中不可或缺的算法支撑.本人接触时间不短,但研究尚浅.我计划用python来实现机器学习中较为常见的算法. 看透了自己,便无须小看别人. (老舍) 机器学 ...

  10. 【机器学习实战】KNN算法的两个经典例子(电影类型判断,约会网站的改进)

    KNN算法的两个常用实际例子 一.使用K-邻近算法来对电影的类型进行判断 1.实验思路: 2.代码实现: 3.运行截图: 4.完整代码展示: 二.在约会网站上使用KNN算法 (一)准备数据:从文本文件 ...

最新文章

  1. php 伪静态 page-18.html,PHP 伪静态实现技术原理讲解
  2. 【组队学习】【29期】6. 动手学数据分析
  3. 设置float后,后面的元素位置问题。
  4. form中的onblur事件简单的介绍
  5. python tkinter 布局_(4)python tkinter-布局
  6. adobe premiere elements 2019中文版
  7. 【实验】不会端口映射?看完就会了
  8. 高级系统项目管理师笔记1
  9. python编译器怎么运行不在路径中的py文件_对python当中不在本路径的py文件的引用详解...
  10. POJ 1042 Gone Fishing【枚举+贪心】
  11. AD+DNS安装步骤详解
  12. 结构专业规范大全_一级注册结构工程师专业考试所使用的规范、标准、规程
  13. 洛谷 P5660 数字游戏
  14. java读写锁死锁例子_Java并发关于重入锁与读写锁的详解
  15. macOS Monterey新功能:抹掉所有内容和设置
  16. LoadRunner测试一个简单的AJAX例子
  17. Oracle数据库用户查询常用命令
  18. 【MIKE HYDRO】断面处理-excel断面数据转成可导入的txt格式
  19. Rust 智能指针(二)
  20. 关于多元正态分布向量表示的Notation问题

热门文章

  1. 尝试在RHEL6安装Wordpress —— 接触LAMP
  2. Python安装学习
  3. VMware的CentOS部署环境
  4. sql 操作常用操作语句 新增、修改字段等
  5. cocos creator动画编辑器学习
  6. HDU1427 速算24点
  7. java常见类型的转化以及风险
  8. [SOA] Mule ESB 3.x 入门(二)—— 配置(spring, properties, log4j)
  9. BT 与 Magnet 的下载方式及原理
  10. 图形数据库Neo4j(1)----简介及使用