Tensorflow学习笔记(二)

KNN手写数字识别

一:KNN概述

1. KNN(k最邻近分类算法):如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。

2.关于K的取值
  如果当K的取值过小时,一旦有噪声的存在将会对预测产生比较大影响,例如取K值为1时,一旦最近的一个点是噪声,那么就会出现偏差,K值的减小就意味着整体模型变得复杂,容易发生过拟合;

如果K的值取的过大时,就相当于用较大邻域中的训练实例进行预测,学习的近似误差会增大。这时与输入目标点较远实例也会对预测起作用,使预测发生错误。

如果K==N的时候,那么就是取全部的实例,即为取实例中某分类下最多的点,就对预测没有什么实际的意义了;

K的取值尽量要取奇数,以保证在计算结果最后会产生一个较多的类别,如果取偶数可能会产生相等的情况,不利于预测。

常用的方法是从k=1开始,使用检验集估计分类器的误差率。重复该过程,每次K增值1,允许增加一个近邻。选取产生最小误差率的K。
图例:
在这里插入图片描述
上图中,k=3时,绿点属于红色;k=5时,绿点属于蓝色。

二:步骤

  1. 加载数据
    ①随机数;②训练图片,训练标签,测试图片,测试标签;
  2. 计算测试图片和训练图片的距离
  3. 找到K个最近的图片
  4. 获取找到的图片的标签
  5. 把标签转化为数字
  6. 计算正确检测概率

三:代码实现

import tensorflow as tf
import numpy as np
import random
from tensorflow.examples.tutorials.mnist import input_data
#1.load data
#mnist数据集和此代码文件放在同一文件夹下
mnist=input_data.read_data_sets('KNN',one_hot=True)

#属性设置
trainNum=55000
testNum=10000
trainSize=500
testSize=5
k=4

#data分解,生成下标 生成trainsize个数字,范围在0-trainNum, 不可替换
trainIndex=np.random.choice(trainNum,trainSize,replace=False)
testIndex=np.random.choice(testNum,testSize,replace=False)
trainData=mnist.train.images[trainIndex]#获取训练图片
trainLabel=mnist.train.labels[trainIndex]#获取训练图片的标签
testData=mnist.test.images[testIndex]#获取测试图片
testLabel=mnist.test.labels[testIndex]#获取测试图片标签
print('trainData.shape=',trainData.shape)# 500*784(图片个数*图片所有像素点(28*28))
print('trainLabel.shape=',trainLabel.shape)# 500*10(10列数字中有一个1,其位置代表了值。标签值与图片一一对应)
print('testData.shape=',testData.shape)# 5*784
print('testLabel.shape=',testLabel.shape)# 5*10

#define input(784代表一个完整的图片)
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)

#2.knn test and train distance
f1=tf.expand_dims(testDataInput,1)#维度扩展:5*784 -> 5*1*784
f2=tf.subtract(trainDataInput,f1)
f3=tf.reduce_sum(tf.abs(f2),reduction_indices=2)#完成数据累加

#3.find k the next of images in knn
#此实例:每一张测试图片对应500张训练图片,即在500张训练图片中找到4个与测试图片最接近的图片
f4=tf.negative(f3)#取反
f5,f6=tf.nn.top_k(f4,k=4)#选取f4中最大的四个值,即f3中最小的四个值,距离最近(因为取反)

#4.parse content
f7=tf.gather(trainLabelInput,f6)

#5.convert label to number 
f8=tf.reduce_sum(f7,reduction_indices=1)
f9=tf.argmax(f8,dimension=1)

with tf.Session() as sess:
    #5张测试图片传给f1
    p1=sess.run(f1,feed_dict={testDataInput:testData[0:5]})
    #测试图片和训练图片二者之间的对应像素作差
    p2=sess.run(f2,feed_dict={trainDataInput:trainData,testDataInput:testData[0:5]})
    p3=sess.run(f3,feed_dict={trainDataInput:trainData,testDataInput:testData[0:5]})
    
    p4=sess.run(f4,feed_dict={trainDataInput:trainData,testDataInput:testData[0:5]})
    #p5:距离;  p6:index训练图片下标
    p5,p6=sess.run((f5,f6),feed_dict={trainDataInput:trainData,testDataInput:testData[0:5]})
    #p7=(5,4,10):每张测试图片(共5张)对应4张最近的训练图片,得到label值(同上,10个数字,1的位置代表值)
    p7=sess.run(f7,feed_dict={trainDataInput:trainData,testDataInput:testData[0:5],trainLabelInput:trainLabel})
    #在第一个维度上进行累加
    p8=sess.run(f8,feed_dict={trainDataInput:trainData,testDataInput:testData[0:5],trainLabelInput:trainLabel})
    #遍历p8,找到每一行中最大的值,记录位置
    p9=sess.run(f9,feed_dict={trainDataInput:trainData,testDataInput:testData[0:5],trainLabelInput:trainLabel})
    #测试集的真实值
    p10=np.argmax(testLabel[0:5],axis=1)

#6.检测概率统计
#比较p9和p10,计算正确预测概率
j=0
for i in range(0,5):
    if p10[i]==p9[i]:
        j=j+1
print('ac=',j*100/5)

四:函数及方法

  1. numpy.random.choice(a, size=None, replace=True, p=None):可以从一个int数字或1维array里随机选取内容,并将选取结果放入n维array中返回。
    a:一维数组或者int型变量,如果是数组,就按照里面的范围来进行采样,如果是单个变量,则采用np.arange(a)的形式。
    replace:布尔参数,决定采样中是否有重复值
  2. numpy.arange(start, stop, step, dtype = None):返回(start,stop]范围下,以step为步长的值。Start默认为0,step默认为1。
  3. tf.expand_dims(input, dim, name=None):给定一个input,在axis轴处给input增加一个为1的维度。 axis=0,表示第一维度,以此类推,-1表示最后一个维度。
  4. tf.reduce_sum(input,reduction_indices,keep_dims):计算input沿着指定维度的和,可用于求和后降维。 reduction_indices:指定的维度,若不指定,则计算所有元素的和。Keep_dims:是否保持原有张量的维度,默认为False。
  5. tf.negative(x):返回x的负值。
  6. tf.nn.top_k(input,k):返回input中每行最大的K个数,并且返回他们所在位置的索引。注意。返回两个值。
  7. tf.gather( params, indices, axis=0):在axis指定的维度,用一个一维的索引数组indices,将张量 params中对应索引的向量提取出来。
  8. tf.argmax(array,axis):在axis指定的维度上,寻找最大的元素,并返回索引值。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值