python3下tensorflow练习(二)

时间:2023-02-13 20:04:07

MNIST手写字识别

流程:
1、将要识别的图片转为灰度图,并且转化为784矩阵(单通道,每个像素范围0-255,0为黑色,255为白色,这一点与MNIST中的正好相反)
2、将28*28的矩阵转换成1维矩阵[[784]](也就是把第2,3,4,5....行矩阵纷纷接入到第一行的后面)
3、用一个1*10的向量代表标签,也就是这个数字到底是几,举个例子e数字1对应的矩阵就是[0,1,0,0,0,0,0,0,0,0]
4、softmax回归预测图片是哪个数字的概率

5、用交叉熵和梯度下降法训练参数

注意:这里我建立的是单层神经网络

(1)softmax激活函数详解:

softmax直白来说就是将原来输出是3,1,-3通过softmax函数一作用,就映射成为(0,1)的值,而这些值的累和为1(满足概率的性质),那么我们就可以将它理解成概率,在最后选取输出结点的时候,我们就可以选取概率最大(也就是值对应最大的)结点,作为我们的预测目标!

像这里的MNIST要把它分成10类,就必须用softmax来进行分类了。  
P(y=0)=p0,P(y=1)=p1,p(y=2)=p2......P(y=9)=p9.这些表示预测为数字i的概率,(跟上面标签的格式正好对应起来了),它们的和为1,即 ∑(pi)=1。

tensorflow实现了这个函数,我们直接调用这个softmax函数即可,原理图:

python3下tensorflow练习(二)

(2)交叉熵刻画了两个概率分布之间的距离,它是分类问题中使用比较广的一种损失函数。给定两个概率分布p和q,通过q来表示p的交叉熵为: 

python3下tensorflow练习(二)
在tensorflow中的函数表示:
   cross_entropy = -tf.reduce_mean(
        y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0))
    )
    其中y_代表正确结果,y代表预测结果,tf.clip_by_value函数可以将一个张量中的数值限制在一个范围之内,tf.log完成对张量中所有元素依次求对数
    ,* 实现两个矩阵元素之间直接相乘(矩阵乘法需要使用tf.matmul函数来完成)。

注意:

交叉熵和最大似然估计的联系与区别

引用https://blog.csdn.net/diligent_321/article/details/53115369该文章的解释

在利用深度学习模型解决有监督问题时,比如分类、回归、去噪等,我们一般的思路如下:

     (1)最大似然误差是从概率的角度,求解出能完美拟合训练样例的模型参数theta,使得概率p(y | x, theta)最大化;

  

     (2)交叉熵损失函数,衡量的是两个分布p、q的相似性。在给定集合上两个分布p和q的cross entropy定义如下:

python3下tensorflow练习(二)

                  在机器学习应用中,p一般表示样例的标签的真实分布, 在分类问题中,交叉熵的本质就是似然函数的最大化。证明如下:
  • 记带标签的样例为(x, y), 其中x表示输入特征向量,y=[y1, y2, ..., yc]表示真实标签的one-hot表示,y_=[y_1, y_2, ..., y_c]表示模型输出的分布,c表示样例输出的类别数,那么,
           (1)对于二分类问题,p(x)=[1, 0],q(x)=[y_1, y_2],y_1=p(y=1|x)表示模型输出为真的概率,交叉熵H(p, q)=-(1*y_1+0*y_2)=-y_1,显然此时交叉熵的最小化等价于似然函数的最大化;
           (2)对于多分类问题, 假设p(x)=[0, 0, 0, ..., 1, 0, 0],q(x)=[y_1, y_2, y_3, ..., y_k, y_(k+1), y_(k+2)],即表示真实样例标签为第k类,y_k=p(y=k|x)表示模型输出为第k类的概率,交叉熵H(p, q)=-( 0*y_1+0*y_2+0*y_3+...+1*y_k+0*y_(k+1)+0*y_(k+2) ) = -y_k, 此时同上。
"""
author:jiancgehng
2018.05.04
"""
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import matplotlib.pyplot as plt#导入plt绘图模块

# number 1 to 10 data提前下下来了再“MNIST”文件夹下
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)#one_hot一种编码格式0000000100(0-9数字)

建立网络层函数:

def add_layer(inputs, in_size, out_size, activation_function=None,):
    # #biases和Weights并不是纯随机数,一定的初始值跟有利于寻找到最优解
    Weights = tf.Variable(tf.random_normal([in_size, out_size]))
    biases = tf.Variable(tf.zeros([1, out_size]) + 0.1,)
    Wx_plus_b = tf.matmul(inputs, Weights) + biases
    if activation_function is None:
        outputs = Wx_plus_b
    else:
        outputs = activation_function(Wx_plus_b,)
    return outputs

建立评估模型准确率公式:

"""
    tf.argmax(y_pre,1),tf.argmax(vector, 1):返回的是vector中的最大值的索引号,如果vector是一个向量,那就返回一个值,
    如果是一个矩阵,那就返回一个向量,这个向量的每一个维度都是相对应矩阵行的最大值元素的索引号。
    [[100000000]]输入,输出最大数的索引0
    
    tf.equal(A, B)是对比这两个矩阵或者向量的相等的元素,如果是相等的那就返回True,反正返回False,返回的值的矩阵维度和A是一样的
    将实际值和预测值进行比较,返回Bool数据类型
    
     tf.cast(x, dtype, name=None) 
     将x的数据格式转化成dtype.例如,原来x的数据格式是bool, 
     那么将其转化成float以后,就能够将其转化成0和1的序列。
"""
def compute_accuracy(v_xs, v_ys):
    global prediction#全局变量
    y_pre = sess.run(prediction, feed_dict={xs: v_xs})#预测值
    correct_prediction = tf.equal(tf.argmax(y_pre,1), tf.argmax(v_ys,1))#100个样本,就是1*100的向量
    accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))#将上面的bool类型转为float,求得矩阵中所有元素的平均值 如:98/100=.98
    result = sess.run(accuracy, feed_dict={xs: v_xs, ys: v_ys})#run()运行才能有结果
    return result    

以palceholder传入样本X值:

"""
    define placeholder for inputs to network
    相当于一个容器,feed_dict()就是调用容器的方法
    placeholder一共两个参数:1.数据类型,tf.float32或者“FLOAT32” 2.出入参数(矩阵)的形状,第一维None:不限制样本个数(X),第二维:特征个数
"""
xs = tf.placeholder(tf.float32, [None, 784]) # 28x28,输入特征784个
ys = tf.placeholder(tf.float32, [None, 10])#输出10个数字

输出预测值:

# add output layer单层神经网络
#数字1对应的矩阵就是[0,1,0,0,0,0,0,0,0,0],输出结果为10个矩阵
prediction = add_layer(xs, 784, 10,  activation_function=tf.nn.softmax)#错误:其实就是二分类问题,输出的10个数{0,1};多分类:tf.nn.softmax

计算损失值(准备反向传播):

"""
    the error between prediction and real data,损失值
    tf.reduce_mean(input_tensor, reduction_indices=None, keep_dims=False, name=None)
    计算一个张量的维数的平均值。如果还原指数没有条目,则所有维度都被还原,一个带有单个元素的张量被返回。
    input_tensor: 张量减少。应该有数字类型。
    reduction_indices: 尺寸减少。如果没有(默认),则减少所有维度。
    keep_dims: 如果是真的,则保留长度为1的维度。
    name: 操作的名称
    
    -tf.reduce_sum(ys * tf.log(prediction),reduction_indices=[1])
"""
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction),
                                              reduction_indices=[1]))       # loss

选择优化器(梯度下降)一次训练:

train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)#一次正向传播+反向传播,得到模型

打开会话开始训练:

sess = tf.Session()
# important step
sess.run(tf.initialize_all_variables())


#plot_images_labels_prediction(mnist.train.images,
#                              mnist.train.labels,prediction,0)
for i in range(1000):
    #读取批次数据,为了更快的收敛
    #每次读取1001项批次训练数据,读取的训练数据存放在 batch_xs, batch_ys ,准备训练使用
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={xs: batch_xs, ys: batch_ys})#训练模型
    if i % 50 == 0:
        print(compute_accuracy(
            mnist.test.images, mnist.test.labels))

训练结果:

python3下tensorflow练习(二)