knn的本质:假设一张待检测的图片,与存在的样本进行比较,如果样本存在k个与待检测图样相类似,那么把当前k记录下,在这k中找到相似性最大的,假设样本10个,有8个描述的当前的数字是1,那么检测结果就是1。
也就是说在样本中找出最接近的图片,然后在最接近的图片中统计哪个出现的概率最高,把这个概率最高的作为检测结果。
安装时候出现的小插曲:
使用手写字识别的时候,因为tensorflow1.15之后的版本移除了'tensorflow.contrib'的模块,导致没法使用数据集,此时需要卸载了
pip uninstall tensorflow==1.15
安装1.13.1版本
pip install tensorflow==1.13.1
如果使用:pip install tensorflow
默认安装的是最新版tensorflow,目前最新为2.0
导入数据的时候出现提示: Instructions for updating: Please use urllib or similar directly.
在 from tensorflow.examples.tutorials.mnist import input_data
之前,加入
old_v = tf.logging.get_verbosity()
tf.logging.set_verbosity(tf.logging.ERROR)
在mnist = input_data.read_data_sets('./data/mnist', one_hot=True)
之后,加入
tf.logging.set_verbosity(old_v)
如下
mnist = input_data.read_data_sets('MNIST_data',one_hot=True)
one_hot,表示有一个数为1,其余为0,例如:0001000000
'MNIST_data',表示数据集的文件路径
测试图片,训练图片,测试标签,训练标签
import tensorflow as tf
import numpy as np
import random
old_v = tf.logging.get_verbosity()
tf.logging.set_verbosity(tf.logging.ERROR)
from tensorflow.examples.tutorials.mnist import input_data #导入数据集
# load data 2 one_hot : 1 0000 1 fileName
mnist = input_data.read_data_sets('MNIST_data',one_hot=True) #装载数据
tf.logging.set_verbosity(old_v)
再运行等待下载mnist数据集
代码如下:
import tensorflow as tf
import numpy as np
import random
from tensorflow.examples.tutorials.mnist import input_data #导入数据集
# load data 2 one_hot : 1 0000 1 fileName
mnist = input_data.read_data_sets('MNIST_data',one_hot=True) #装载数据,数据中,有一个为1其余为0000,例如0001000000
# 属性设置
trainNum = 55000
testNum = 10000
trainSize = 500 #训练的时候使用500张照片
testSize = 5 #测试图片5张
k = 4 #样本有K张图与测试图片最接近
# data 分解 1 trainSize 2范围0-trainNum 3 replace=False
#将数据分成4种类型:训练数据,训练标签,测试数据,测试标签
trainIndex = np.random.choice(trainNum,trainSize,replace=False) #生产一组随机数
testIndex = np.random.choice(testNum,testSize,replace=False) #范围在0-testNum之间,一共生产testSize个,不可重复
trainData = mnist.train.images[trainIndex]# 训练图片
trainLabel = mnist.train.labels[trainIndex]# 训练标签
testData = mnist.test.images[testIndex]# 测试图片(数据)
testLabel = mnist.test.labels[testIndex]# 测试标签
# 28*28 = 784
print('trainData.shape=',trainData.shape)#500*784 1 图片个数 2 784?
print('trainLabel.shape=',trainLabel.shape)#500*10
print('testData.shape=',testData.shape)#5*784
print('testLabel.shape=',testLabel.shape)#5*10
print('testLabel=',testLabel)# 4 :testData [0] 3:testData[1] 6
运行结果:
trainData.shape= (500, 784)
trainLabel.shape= (500, 10)
testData.shape= (5, 784)
testLabel.shape= (5, 10)
testLabel= [[0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]]
[Finished in 8.3s]
在testLabel中,第一列[0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]表示代表数字6
第二列 [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]代表数字1
一次类推
分别执行f1,f2,f3得到p1,p2,p3,输出结果:
import tensorflow as tf
import numpy as np
import random
from tensorflow.examples.tutorials.mnist import input_data #导入数据集
# load data 2 one_hot : 1 0000 1 fileName
mnist = input_data.read_data_sets('MNIST_data',one_hot=True) #装载数据
# 属性设置
trainNum = 55000
testNum = 10000
trainSize = 500 #训练的时候使用500张照片
testSize = 5 #测试图片5张
k = 4 #样本有K张图与测试图片最接近
# data 分解 1 trainSize 2范围0-trainNum 3 replace=False
#将数据分成4种类型:训练数据,训练标签,测试数据,测试标签
trainIndex = np.random.choice(trainNum,trainSize,replace=False) #生产一组随机数
testIndex = np.random.choice(testNum,testSize,replace=False) #范围在0-testNum之间,一共生产testSize个,不可重复
trainData = mnist.train.images[trainIndex]# 训练图片
trainLabel = mnist.train.labels[trainIndex]# 训练标签
testData = mnist.test.images[testIndex]# 测试图片(数据)
testLabel = mnist.test.labels[testIndex]# 测试标签
# 28*28 = 784
print('trainData.shape=',trainData.shape)#500*784 1 图片个数 2 784?
print('trainLabel.shape=',trainLabel.shape)#500*10
print('testData.shape=',testData.shape)#5*784
print('testLabel.shape=',testLabel.shape)#5*10
print('testLabel=',testLabel)# 4 :testData [0] 3:testData[1] 6
# tf input (500*784) 784->image,每个784代表一张完整图片,500代表图片张数
trainDataInput = tf.placeholder(shape=[None,784],dtype=tf.float32)
trainLabelInput = tf.placeholder(shape=[None,10],dtype=tf.float32)
testDataInput = tf.placeholder(shape=[None,784],dtype=tf.float32)
testLabelInput = tf.placeholder(shape=[None,10],dtype=tf.float32)
#以上为数据加载,以下为开始计算,计算训练图片与测试图片的距离之差
#knn distance 5*785. 5*1*784(转换为:5行*1列*784)
# 5张侧视图 500张训练图 每张784维 (3D) 2500*784 这里是三维的,所以要把下面拓展到三维
f1 = tf.expand_dims(testDataInput,1) # 维度扩展到三维
f2 = tf.subtract(trainDataInput,f1)# 784 sum(784) (训练图片与测试图片只差)
f3 = tf.reduce_sum(tf.abs(f2),reduction_indices=2)# 在第二维度上完成数据取绝对值累加 784 abs,
# 5*500
with tf.Session() as sess:
# f1 <- testData 5张图片
p1 = sess.run(f1,feed_dict={testDataInput:testData[0:5]})
print('p1=',p1.shape)# p1= (5, 1, 784)
p2 = sess.run(f2,feed_dict={trainDataInput:trainData,testDataInput:testData[0:5]})
print('p2=',p2.shape)#p2= (5, 500, 784) (1,100)
p3 = sess.run(f3,feed_dict={trainDataInput:trainData,testDataInput:testData[0:5]})
print('p3=',p3.shape)#p3= (5, 500)
print('p3[0,0]=',p3[0,0]) #130.451 knn distance p3[0,0]= 155.812
p1= (5, 1, 784)
p2= (5, 500, 784)
p3= (5, 500)
p3[0,0]= 111.24315 #距离差值
在500张照片中,找到4张与测试图片最接近的图片
# 1 重要
# 2 KNN CNN 2种
# 3 样本
# 4 旧瓶装新酒 :数字识别的不同
# 4.1 网络 4。2 每一级 4.3 先原理 后代码
# 本质:knn test 样本 K个 max4 3个1 -》1
# 1 load Data 1.1 随机数 1.2 4组 训练 测试 (图片 和 标签)
# 2 knn test train distance 5*500 = 2500 784=28*28
# 3 knn k个最近的图片5 500 1-》500train (4)
# 4 k个最近的图片-> parse centent label
# 5 label -》 数字 p9 测试图片-》数据
# 6 检测概率统计
import tensorflow as tf
import numpy as np
import random
from tensorflow.examples.tutorials.mnist import input_data #导入数据集
# load data 2 one_hot : 1 0000 1 fileName
mnist = input_data.read_data_sets('MNIST_data',one_hot=True) #装载数据
# 属性设置
trainNum = 55000
testNum = 10000
trainSize = 500 #训练的时候使用500张照片
testSize = 5 #测试图片5张
k = 4 #样本有K张图与测试图片最接近
# data 分解 1 trainSize 2范围0-trainNum 3 replace=False
#将数据分成4种类型:训练数据,训练标签,测试数据,测试标签
trainIndex = np.random.choice(trainNum,trainSize,replace=False) #生产一组随机数
testIndex = np.random.choice(testNum,testSize,replace=False) #范围在0-testNum之间,一共生产testSize个,不可重复
trainData = mnist.train.images[trainIndex]# 训练图片
trainLabel = mnist.train.labels[trainIndex]# 训练标签
testData = mnist.test.images[testIndex]# 测试图片(数据)
testLabel = mnist.test.labels[testIndex]# 测试标签
# 28*28 = 784
print('trainData.shape=',trainData.shape)#500*784 1 图片个数 2 784?
print('trainLabel.shape=',trainLabel.shape)#500*10
print('testData.shape=',testData.shape)#5*784
print('testLabel.shape=',testLabel.shape)#5*10
print('testLabel=',testLabel)# 4 :testData [0] 3:testData[1] 6
# tf input (500*784) 784->image,每个784代表一张完整图片,500代表图片张数
trainDataInput = tf.placeholder(shape=[None,784],dtype=tf.float32)
trainLabelInput = tf.placeholder(shape=[None,10],dtype=tf.float32)
testDataInput = tf.placeholder(shape=[None,784],dtype=tf.float32)
testLabelInput = tf.placeholder(shape=[None,10],dtype=tf.float32)
#以上为数据加载,以下为开始计算,计算训练图片与测试图片的距离之差
#knn distance 5*785. 5*1*784(转换为:5行*1列*784)
# 5张侧视图 500张训练图 每张784维 (3D) 2500*784 这里是三维的,所以要把下面拓展到三维
f1 = tf.expand_dims(testDataInput,1) # 维度扩展到三维
f2 = tf.subtract(trainDataInput,f1)# 784 sum(784) (训练图片与测试图片只差)
f3 = tf.reduce_sum(tf.abs(f2),reduction_indices=2)# 在第二维度上完成数据取绝对值累加 784 abs,
# 5*500
f4 = tf.negative(f3)# 取反
f5,f6 = tf.nn.top_k(f4,k=4) # 选取f4 最大的四个值
# f3 最小的四个值
# f6 index->trainLabelInput
#得到了上面的5张图片分别对应最接近的4张图片和距离之后,要求其数据进行解析
f7 = tf.gather(trainLabelInput,f6)
# f8 num reduce_sum reduction_indices=1 '竖直'
f8 = tf.reduce_sum(f7,reduction_indices=1)
# tf.argmax 选取在某一个最大的值 index
f9 = tf.argmax(f8,dimension=1)
# f9 -> test5 image -> 5 num
with tf.Session() as sess:
# f1 <- testData 5张图片
p1 = sess.run(f1,feed_dict={testDataInput:testData[0:5]})
print('p1=',p1.shape)# p1= (5, 1, 784)
p2 = sess.run(f2,feed_dict={trainDataInput:trainData,testDataInput:testData[0:5]})
print('p2=',p2.shape)#p2= (5, 500, 784) (1,100)
p3 = sess.run(f3,feed_dict={trainDataInput:trainData,testDataInput:testData[0:5]})
print('p3=',p3.shape)#p3= (5, 500)
print('p3[0,0]=',p3[0,0]) #130.451 knn distance p3[0,0]= 155.812
p4 = sess.run(f4,feed_dict={trainDataInput:trainData,testDataInput:testData[0:5]})
print('p4=',p4.shape)
print('p4[0,0]',p4[0,0])
p5,p6 = sess.run((f5,f6),feed_dict={trainDataInput:trainData,testDataInput:testData[0:5]})
#p5= (5, 4) 每一张测试图片(5张)分别对应4张最近训练图片
#p6= (5, 4)
print('p5=',p5.shape)
print('p6=',p6.shape)
print('p5[0,0]',p5[0])
print('p6[0,0]',p6[0])# p6 index
p7 = sess.run(f7,feed_dict={trainDataInput:trainData,testDataInput:testData[0:5],trainLabelInput:trainLabel})
print('p7=',p7.shape)#p7= (5, 4, 10) #解析出来可以看到在9个0和1个1中,1所在的位置
print('p7[]',p7) #0010000000
p8 = sess.run(f8,feed_dict={trainDataInput:trainData,testDataInput:testData[0:5],trainLabelInput:trainLabel})
print('p8=',p8.shape)
print('p8[]=',p8) #在竖直方向上对4张图片对应的数进行累加,比如0010003000
p9 = sess.run(f9,feed_dict={trainDataInput:trainData,testDataInput:testData[0:5],trainLabelInput:trainLabel})
print('p9=',p9.shape)
print('p9[]=',p9) #在上面p8中找到最大的值,并记录其下标到p9上,比如0010003000,最大是3,其下标是6,代表数字6
p10 = np.argmax(testLabel[0:5],axis=1)
print('p10[]=',p10)
j = 0
for i in range(0,5):
if p10[i] == p9[i]:
j = j+1
print('ac=',j*100/5)
p4= (5, 500)
p4[0,0] -175.36469
p5= (5, 4)
p6= (5, 4)
p5[0,0] [-59.2235 -68.50982 -72.57253 -73.87845]
p6[0,0] [ 54 81 187 31]
p7= (5, 4, 10)
p7[] [[[1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]][[0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]][[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]][[0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 1. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 1. 0.]][[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
[0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]]]
p8= (5, 10)
p8[]= [[3. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 1. 0. 3. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 4. 0. 0.]
[0. 0. 0. 2. 0. 0. 0. 0. 2. 0.]
[0. 0. 1. 0. 2. 0. 0. 1. 0. 0.]]
p9= (5,)
p9[]= [0 6 7 3 4] #测试预测的结果
p10[]= [0 4 7 8 7] #测试集原标签的内容,人眼区分的时候
ac= 40.0 #准确率只有百分之40