监督学习——K邻近算法及数字识别实践
1. KNN 算法
K-近邻(k-Nearest Neighbor,KNN)是分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
K邻近算法原理很简单,但是真正用好它也不容易,比如K的取值到底为多少才合适,而且知道什么场景下用它更不简单。
缺点: 该算法的执行效率并不高,每次计算都需要将 待识别的用例 与所有测试用例进行求差计算,计算量较大。随着测试数据的增多,计算量会越来越大。
2. 数字识别 Python 实现
下图为一个 二进制表示的数字“6”,每个训练数据和测试数据都是以这种形式保存在一个txt文件中,数据为32*32(1024个数据)的矩阵。
KNN算法实现数字识别步骤
1. 读取训练数据中的所有数据到一个矩阵中(矩阵中的每一列代表一个图片数据),同时读取数据的标签保存在一个数组中(数据的标签或患者说文件代表的具体数字信息在文件命中)
2. 读取测试数据,转换1024*1的矩阵。
3. 用测试数据与矩阵A中的每一列求距离,求得的L个距离存入距离数组中(距离算法)
4. 从距离数组中取出最小的K个距离所对应的训练集的索引
5. 拥有最多索引的值就是预测值(有多个众数时,按距离和最小)
数据加载函数
该函数用于打开一个数字数据源(32*32),保存在一个1*1024的矩阵中
def openFile(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 loadData(dir): fileList = listdir(dir) // 列出dir文件下的所有文件(测试数据) lable = [] index = 0 dataMat = np.zeros((1024,len(fileList))) for file in fileList: lable.append(int(file[0])); // 标签信息保存在文件的第一个字符中 dataMat[:,index] = openFile(dir+file) index +=1; return dataMat,lable
距离计算函数
该函数用于计算两个图片举证(1*1024)的距离,(相同位置如果数字相同则距离加1)
def caculateerro(data1,data2): len1 = len(data1) len2 = len(data2) sizelen = min(len1,len2); totalerro = 0; for i in range(sizelen): if data1[i] != data2[i]: totalerro +=1 return totalerro
数字识别函数
def classFier(datain):
k=15
dictErro = {} //保存 训练数据编号——测试数据与该训练数据的距离
trainingdata, traninglabel = loadData('digits\\trainingDigits\\');
m,n = trainingdata.shape;
for i in range(n):
// 计算测试图片与每张训练图片的距离 currErro = caculateerro(datain,trainingdata[:,i]) dictErro[i] = currErro sortedDict = sorted(dictErro.items(),key=lambda x:x[1],reverse=False); numofnumber = range(10) for i in range(10): numofnumber[i] = 0 for j in range(30): label = int(sortedDict[j][0]) numofnumber[int(traninglabel[label])] += 1; return numofnumber.index(max(numofnumber))
上述源码中KNN算法的K取值为15,即取出距离训练数据最小的十五个图片,然后判断这15张图片中对应的那个数字出现的平率最多,将最多的数据作为识别结果返回。
参考:
《机器学习实战》