田安Anne

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
 
 
 
 
 
 
 
 
这里的代码是基于Python3的
这里先上详解
最后附上完整代码注释
我的博客素:https://www.cnblogs.com/EvilAnne/
如果我比较勤劳的话,会更新完整本书
否则,我会放弃!
 
①dataSetSize = dataSet.shape[0]
是来计算共有多少数据集,如是([[1,3],[3,4]]),就是两组数据集,相当于
  | x1 | x2 |
  |  1 |  3 |
  |  3 |  4 |
dataSetSize = dataSet.shape[0] = 2
 
②diffMat = tile(inX,(dataSetSize,1)) - dataSet
这是来计算,未知类的数据集与已知数据集的差,但为了方便
  要把未知类的数据集化成矩阵计算,设未知类数据是([[0,3]])
即 | x1' | x2' |
     |  0   |  3  |
我们想计算 0-1,3-3;0-3,3-4
这样可以更方便
  |  0   3 |  -  | 1  3 |  = | -1   0 | (-dataSet计算差值)
  |  0   3 |     | 3  4 |    | -3  -1 |
而diffMat = tile(inX,(dataSetSize,1))就是
把[0,3] - > | 0  3 | 来方便计算的
                 | 0  3 |
 
③sqDiffMat = diffMat ** 2
把差值平方化即
| -1   0 |    ** 2   = | 1  0 |
| -3  -1 |                | 9  1 |     
 
④distances = sqDiffMat.sum(axis=1)
相当于把(未平方根化之前的)未知数据集与两个已知数据的距离分别计算出来
得出[1,10],1是未知与已知①的距离,10是未知与已知②的距离
 
⑤distances = sqdistances ** 0.5
将两个距离分别进行平方根化,得到
该未知标签向量与已知①的欧式距离,该未知标签向量与已知②的欧式距离
 
⑥sortedDistIndices = distances.argsort()
比如说,
[3,5,1] ---> [2,0,1] 从小到大的索引
从小到大分别是:1,3,5.对应的索引是2,0,1
这样我们在循环的时候,可以将欧式距离list按值的大小从小到大遍历出来
------------------------------------------------------------------------------------

把按值大小顺序排列的欧氏距离索引list前k个对应的labels遍历出来
⑨classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
比如说,k = {};k['A'] = k.get('A',1);k = {'A':1}
而      k = {};k['A'] = k.get('A',1) + 1;k = {'A':2}
但我不太明白这里为什么要+1
所以我们来实验一下⑨到底是什么意思
for i in range(k):                                    #k是我们自己定的
        voteIlabel = labels[sortedDistIndicies[i]]        #把按值大小顺序排列的欧氏距离索引list前k个对应的labels遍历出来
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
 
假设labels = ['A','A','B','B']
假设sortedDistIndicies = [0,3,2,1]
令k = 4
---------
当k = 0,
voteIlabel = labels[sortedDistIndicies[0]]
     = labels[0]
     = 'A'
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
classCount['A'] = classCount.get('A', 0) + 1
所以有classCount = {'A':1}
---------
k = 1
voteIlabel = labels[sortedDistIndicies[1]]
     = labels[1]
     = 'A'
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
classCount['A'] = classCount.get('A', 0) + 1
所以有classCount = {'A':2}
---------
k = 2
voteIlabel = labels[sortedDistIndicies[2]]
     = labels[2]
     = 'B'
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
classCount['B'] = classCount.get('B', 0) + 1
所以有classCount = {'A':2,'B':1}
---------
k = 3
voteIlabel = labels[sortedDistIndicies[3]]
     = labels[3]
     = 'B'
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
classCount['B'] = classCount.get('B', 0) + 1
所以有classCount = {'A':2,'B':2}
---------
可以看出,整合的是分类所出现的频数
所以⑨应该是整合的是,按值大小顺序排列的欧氏距离list前k个对应的labels的频数
 
假设classCount = {“A”:2,"B":2}
classCount.items()返回的是dict_items
 
operator.itemgetter()返回的是一个函数
operator.itemgetter(1)按照第二个元素的次序对元组进行排序,reverse=True是逆序,即按照从大到小的顺序排列
意思是取dict_items第1个值(从0开始)
所以 sorted这里的意思是:
classCount.items()将classCount字典分解为元组列表
即由变成
并且按第二个元素进行从大到小的排列例子如下
因为我这里都是2,所以不明显,大家自己可以试试把数字改一下
 
最后return sortedClassCount[0][0]
容易理,就是出解现频数最高的那个对应的分类标签
 

file2matrix数据预处理函数
 
string.strip([chars])
strip: 用来去除头尾字符、空白符(包括\n、\r、\t、' ',即:换行、回车、制表符、空格)
参数chars是可选的,当chars为空,默认删除string头尾的空白符(包括\n、\r、\t、' ')
 
split([char])
split():拆分字符串。通过指定分隔符对字符串进行切片,并返回分割后的字符串列表(list)
 
不理解的意思
先不百度,自己实验一下
可以知道returnMat[index,:] ,这里index = 0,就是取该数据的第一行数据,由于初始化为零矩阵
所以是[0,0,0]
 
对于通过实验可以知道取前三个数据
也就是说读取特征向量
所以的意思就是
取这个文件的特征向量
 
如果字符串只包含数字则返回 True 否则返回 False。

img2vector
 
 
这句不理解,自己实验下,可知道是取第0行的第(32*i+j)个数据
我们知道returnVect是 1 * 1024的零矩阵
 
linestr是遍历读取的每行数据
所以整体的意思就是说把原来32 * 32的数据
转换成1 * (32*32) = 1 * 1024 的数据
这个4 * 3的向量
我把它转换成1 * (4*3) = 1 * 12的向量
就是[1,2,3,4,5,6,7,8,9,9,9,9]
 
handwritingClassTest函数
 
解释下以下代码
其实看test就能很好理解了
 
 
 完整代码及注释:
posted on 2018-10-03 16:47  田安Anne  阅读(3239)  评论(1编辑  收藏  举报