一、 前言
主要记录本人在《机器学习实战》这本书中学习到的相关算法。
基本概念
数据集类型
各种算法适应的数据集种类不同,主要分为标称型和数值型。
标称型:一般在有限的数据中取,而且只存在‘是’和‘否’两种不同的结果(一般用于分类)
数值型:可以在无限的数据中取,而且数值比较具体化,例如4.02,6.23这种值(一般用于回归分析)
二、分类算法
(1)、k近邻
原理:
将待分类的输入数据特征,与已经分类好的训练集数据特征进行比较,取前K个最相似(邻近)的数据的标签,最后在这K个标签中取出现次数最多的为输出标签,即为输入数据的类别。
公式:
对于数值型的特征选用欧式距离公式,X,Y两个向量的计算公式如下:
如X为(1,2,3),Y为(4,5,6),则距离d的计算公式为:
核心算法Python代码实现
from numpy import *
import operator
'''
inX 输入向量
dataSet 训练集特征向量
labels 训练集标签列表 与训练集特征向量顺序相对应
k int型,即为K近邻中的K值
'''
def classify0(inX, dataSet, labels, k):
#计算输入值与训练集的距离
dataSetSize = dataSet.shape[0]
diffMat = tile(inX, (dataSetSize, 1)) - dataSet #tile(x,(a,b)) 将矩阵X在垂直方向复制a次,水平b次
sqDiffMat = diffMat ** 2 #平方
sqDistances = sqDiffMat.sum(axis = 1) #axis=1 按行相加
distances = sqDistances**0.5 #sqrt(0.5)
#选择距离最小的K个点
sortedDistIndicies = distances.argsort() #按值升序排序 返回数组索引
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
#选取出现次签最多的标签
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
应用举例-手写数字识别
数据分为训练集和测试集,分别位于trainingDigits和testDigits两个文件夹内。
这里手写数字数据由一个32x32的矩阵表示,如下图所示。在计算时将32x32的矩阵转变为1x1024的向量。
代码实现
import numpy as np
import os
def img2vector(filename):
returnVect = np.zeros((1,1024))
fr = open(filename)
for i in range(32):
lineStr = fr.readline()
for j in range(32):
returnVect[0,32*i+j] = int(lineStr[j])
return returnVect
def handWritingClassTest():
hwLabels = []
dataDirPath = 'trainingDigits'
trainingFileList = os.listdir(dataDirPath)
m = len(trainingFileList)
trainingMat = np.zeros((m,1024))
for i in range(m):
fileName = trainingFileList[i]
classNameStr = int(fileName.split('_')[0])
hwLabels.append(classNameStr)
trainingMat[i,:] = img2vector(dataDirPath+'/%s' % fileName)
testFileList = os.listdir('testDigits')
errorCount = 0.0
mTest = len(testFileList)
for i in range(mTest):
fileName = testFileList[i]
classNameStr = int(fileName.split('_')[0])
vectorUnderTest = img2vector('testDigits/%s' % fileName)
classifierResult = classify0(vectorUnderTest,trainingMat,hwLabels,3)
print("The classifier came back with: %d,the real answer is: %d" % (classifierResult,classNameStr))
if(classifierResult != classNameStr):
errorCount += 1.0
print("The total number of errors is: %d" % errorCount)
print("The total error rate is: %f" % (errorCount/float(mTest)))
if __name__ == '__main__':
handWritingClassTest()
运行结果,可以看到错误率为1%,还是很不错的。
代码和数据可点击这里下载
总结
k近邻算法是分类数据最简单有效的方法,但其缺点是无法利用训练数据构造模型,每次使用时都需要将输入数据的特征与训练集中所有的数据进行比对计算,因此,随着特征复杂度与训练集的加大,需要计算的次数也会增多。
训练集数据标签:需要
优点:精度高、对异常值不敏感、无数据输入假定
缺点:计算复杂度高、空间复杂度高。
适用数据范围:数值型和标称型。