《机器学习实战》之k-近邻算法-使用sklearn
之前直接使用python代码来实现了k近邻算法,但自己编写这么多的代码总归是有些繁琐,因而我们可以直接使用 * 来帮助我们,分分钟搞定这些算法。
1、Sklearn简介
sklearn全称是scikit-learn,是一个开源的基于python语言的机器学习工具包。它通过NumPy, SciPy和Matplotlib等python数值计算的库实现高效的算法应用,并且涵盖了几乎所有主流机器学习算法。sklearn有一个完整而丰富的官网,里面讲解了基于sklearn对所有算法的实现和简单应用,但是是英文的:http://scikit-learn.org/stable/index.html
在工程应用中,用python手写代码来从头实现一个算法的可能性非低,因为这样不仅耗时耗力,而且还不一定能够写出构架清晰,稳定性强的模型。在实际中,我们是分析采集到的数据,然后根据数据特征选择适合的算法,再去工具包中调用算法,调整算法的参数,获取需要的信息,从而实现算法效率和效果之间的平衡。而sklearn,正是这样一个可以帮助我们高效实现算法应用的工具包。
2、Sklearn的常用模块
sklearn对常用的机器学习方法进行了封装,常用的模块包括回归(Regression)、降维(Dimensionality Reduction)、分类(Classfication)、聚类(Clustering)等方法。这里,我们会主要简介分类方法的使用。
3、Sklearn的建模流程
sklearn的基本建模流程可以分为三步:
下面,按照这三步并以手写数字识别为例来进一步学习sklearn的使用。
4、使用Sklearn库实现手写数字识别
4.1 sklearn中k-近邻算法简介
要使用sklearn实现k近邻,我们可以使用其中的sklearn.neighbors模块。sklearn.neighbors中的具体函数方法如下:
使用其中的KNeighborsClassifier 函数就可以实现k-近邻算法了,该函数有8个参数,具体如下:
将其主要参数解释翻译成中文:
- n_neighbors:int类型,默认为5。其为K-NN查询使用的邻居数,也就是k-NN的k的值,选取最近的k个点。
- weights:str或可调用,默认是uniform,参数可以是uniform、distance,也可以是用户自己定义的函数。
- uniform:是均等的权重,就说所有的邻近点的权重都是相等的。
- distance:是不均等的权重,距离近的点比距离远的点的影响大。
- 用户自定义的函数:接收距离的数组,返回一组维数相同的权重。algorithm:{‘auto’,‘ball_tree’,‘kd_tree’,‘brute’},快速k近邻搜索算法,默认参数为auto,相当于算法自己决定合适的搜索算法。除此之外,用户也可以自己指定搜索算法ball_tree、kd_tree、brute方法进行搜索。
- brute:是蛮力搜索,也就是线性扫描,当训练集很大时,计算非常耗时时。
- kd_tree:构造kd树存储数据以便对其进行快速检索的树形数据结构,kd树也就是数据结构中的二叉树。以中值切分构造的树,每个结点是一个超矩形,在维数小于20时效率高。
- ball tree:是为了克服kd树高纬失效而发明的,其构造过程是以质心C和半径r分割样本空间,每个节点是一个超球体。
- leaf_size:int类型,默认是30,这个是构造的kd树和ball树的大小。这个值的设置会影响树构建的速度和搜索速度,同样也影响着存储树所需的内存大小。需要根据问题的性质选择最优的大小。
- p:int类型,默认为2。距离度量公式。p=1时,使使用曼哈顿距离;p=2时,使用欧氏距离;对于任意p,就是minkowski距离。
- metric:字符串或可调用,默认为’minkowski。用于距离度量,默认度量是minkowski,也就是p=2的欧氏距离(欧几里德度量)。
- metric_params:dict,默认=None。距离公式的其他关键参数,这个可以不管,使用默认的None即可。
- n_jobs:int或None,默认=None。并行处理的个数,默认为1。如果为-1,那么CPU的所有cores都用于并行工作。
同时,KNeighborsClassifier 还有一些函数供我们使用
这里,我们主要会用到训练模型的函数fit,预测函数predict。其余的可以自己去官网阅读,这里不再一一赘述。
提醒:最近邻居算法中,如果发现两个邻居,邻居k+1和k具有相同距离但不同标签,
则结果将取决于训练数据的排序。
4.2 数据处理
与前面一样,我们这里是用的简便的二进制图片。为了方便,其是以txt形式存储在文本中(与上一篇文章使用的是同一个数据集)。
同样,首先定义一个函数用于将这个转换成1*1024的向量。
import numpy as np
import operator
def img2vector(filename): #将图像转化为向量
returnVect = np.zeros((1, 1024)) #创建 1*1024 的Numpy数组
fr = open(filename)
for i in range(32): #循环读出文件的 前32行
lineStr = fr.readline()
for j in range(32): #将每行的头32个字符值存储在Numpy数组中
returnVect[0, 32*i+j] = int(lineStr[j])
return returnVect
4.3 使用sklearn库实现算法
接下来就可以编写主要的代码了。在这里面,我们先读取训练集trainingDigits文件夹,并从文件名中解析出该文件实际表示的数字,同时,使用img2vector函数将文件转化为1*1024的向量。
from os import listdir
from sklearn.neighbors import KNeighborsClassifier as kNN
def handwritingClassTest():
hwLabels = []
trainingFileList = listdir('trainingDigits') #load the training set--- 获取训练集文件夹下的文件目录
m = len(trainingFileList) #获得文件个数
trainingMat = np.zeros((m, 1024))
for i in range(m): #从文件名解析分类的数字
fileNameStr = trainingFileList[i]
fileStr = fileNameStr.split('.')[0] #take off .txt
classNumStr = int(fileStr.split('_')[0])
hwLabels.append(classNumStr) #图片向量列表对应的 数字 标签
trainingMat[i, :] = img2vector('trainingDigits/%s' % fileNameStr) # trainingMat的第i行的所有列(:)存储 该图片的向量
现在就是最重要的时刻了,使用sklearn库,按照上面所写的三步方法来进行。需要注意的是,在进行完前两步后,我们就已经构建好了模型,后面要先去读取测试集的文件,然后才可以进行第三步,也就是使用测试集对模型进行测试。
# 第一步:实例化,构建kNN分类器,基于sklearn构建
neigh = kNN(n_neighbors = 3, algorithm = 'auto')
# 第二步:训练模型,trainingMat为训练集的矩阵,hwLabels为对应的标签
neigh.fit(trainingMat,hwLabels)
#返回testDigits目录下的文件列表
testFileList = listdir('testDigits')
'''因为这里是使用的for循环一个个数据依次进行预测,所以不能使用score函数来返回预测的正确率,因此自己计数来计算错误率
score函数传入的两个参数一个为测试集,一个为标签集。两者都是集合,
而这里我是在for循环里使用predict函数依次测试每一个数据,没有用集合'''
errorCount = 0 #错误检测计数
mTest = len(testFileList) #测试集数据的数量
#从文件名中解析出测试集的类别并进行分类测试
for i in range(mTest):
#获取文件的名字
fileNameStr = testFileList[i]
#根据文件名获得数字
classNumber = int(fileNameStr.split('_')[0])
#获得测试集的1x1024向量,用于预测
vectorUnderTest = img2vector('testDigits/%s' % (fileNameStr))
# 第三步:进行预测,并获得预测结果
classifierResult = neigh.predict(vectorUnderTest)
print("分类返回结果为%d\t真实结果为%d" % (classifierResult, classNumber))
if classifierResult != classNumber: # 计算 使用模型预测时,预测错误的个数
errorCount += 1
print("总共错了%d个数据\n错误率为%f%%" % (errorCount, errorCount / mTest * 100))
运行结果:
测试集中总共有946个文件,将其使用k近邻进行预测后,总共预测错误12个数据,错误率为1.268%,这与上一篇文章使用的方法得到的错误率基本相同。
5、总结
使用sklearn库确实要比用python手写代码来从头实现一个算法简单方便的多,并且两者效果也差不多。其使用主要也就是按照三步基本流程就可以了,但还是建议自己能够敲一遍代码,从头实现一个算法,这对我们的编程能力和对算法的理解都是有好处的!
PS:感觉这一篇写的比前一篇要详细一些,后面也会不断提高,完善!
本文地址:https://blog.csdn.net/qq_28053421/article/details/107288812
上一篇: 【Flask框架学习】虚拟环境(pipenv)的搭建
下一篇: 仪式还是要有的