tensorflow第二篇、简单线性回归与手写数字识别(加深优化)

2.线性回归实例

2.1通过神经网络训练线性回归

知识点

  1. np.linspace(a,b,n) 在a,b之间生成n个均匀分布的数

  2. x_data = np.linspace(-0.5,0.5,200)

    [:,np.newaxis][:,np.newaxis]的作用是将原本被(n,)类型的数值,转化为(n,1)类型

  3. noise = np.random.normal(0,0.02,x_data.shape) x_data.shape就是将noise设成x_data的类型

  4. loss = tf.reduce_mean(tf.square(y-L2)) tensorflow中的求平均值函数

  5. promise = tf.train.GradientDescentOptimizer(0.2) 梯度下降函数

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
x_data = np.linspace(-0.5,0.5,200)[:,np.newaxis]
noise = np.random.normal(0,0.02,x_data.shape)
y_data = np.square(x_data) + noise

x = tf.placeholder(tf.float32,[None,1])
y = tf.placeholder(tf.float32,[None,1])

###构建中间层####
weights1 = tf.Variable(tf.random_normal([1,10]))
biase1 = tf.Variable(tf.zeros([1,10]))
wx_plus_b_L1 = tf.matmul(x,weights1) +biase1
L1 = tf.nn.tanh(wx_plus_b_L1)

#####构建输出层#####
weights2 = tf.Variable(tf.random_normal([10,1]))
biase2 = tf.Variable(tf.zeros([1,1]))
wx_plus_b_L2 = tf.matmul(L1,weights2) +biase2
L2 = tf.nn.tanh(wx_plus_b_L2)

###loss
loss = tf.reduce_mean(tf.square(y-L2))
##3#梯度下降
promise = tf.train.GradientDescentOptimizer(0.2)

##训练结果取loss最小的
train = promise.minimize(loss)

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    for step in range(200):
        sess.run(train,feed_dict={x:x_data,y:y_data})
    prediction = sess.run(L2, feed_dict={x:x_data})
    print(prediction)
    plt.figure()
    plt.scatter(x_data,y_data)
    plt.plot(x_data,prediction,'r-',lw = 5)
    plt.show()

2.2 手写数字识别

2.2.1 简单实现

手写数据集网站:http://yann.lecun.com/exdb/mnist/

通过tensorflow实现简单的神经网络,进行手写数字识别

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
# 批次的大小
batch_size = 100
n_batch = mnist.train.num_examples // batch_size

x = tf.placeholder(tf.float32, [None,784])
y = tf.placeholder(tf.float32, [None, 10])

# 创建一个简单的神经网络
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([1, 10]))
prediction = tf.nn.softmax(tf.matmul(x,W) + b)

# 代价函数
loss = tf.reduce_mean(tf.square(y-prediction))

# 梯度下降法
train_step = tf.train.GradientDescentOptimizer(0.2).minimize(loss)

# 初始化变量
init = tf.global_variables_initializer()

# 得到一个布尔型列表,存放结果是否正确
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(prediction,1)) #argmax 返回一维张量中最大值索引

# 求准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32)) # 把布尔值转换为浮点型求平均数

with tf.Session() as sess:
    sess.run(init)
    for epoch in range(2):
        for batch in range(n_batch):
            # 获得批次数据
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            sess.run(train_step, feed_dict={x:batch_xs, y:batch_ys})
        prediction1 = sess.run(prediction,feed_dict={x:mnist.test.images})
        print(prediction1)
        acc = sess.run(accuracy, feed_dict={x:mnist.test.images,y:mnist.test.labels})
        print("Iter " + str(epoch) + " Testing Accuracy: " + str(acc))

注意事项:在tensorflow中,输入变量的名字,不能与接受结果的变量相等,主要是在循环中。原因:tensorflow的run()里边接受的是tensor张量,如果接收结果的的变量名相等,再次输入是,会输入接受的结果变量,但结果的类型一般为数组、矩阵等,错误示例:

prediction = sess.run(prediction,feed_dict={x:mnist.test.images})
print(prediction)

输出的结果:

[外链图片转存失败(img-IJO1MOx5-1564902809837)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\1564834538676.png)]

以下程序学习自:https://github.com/Parker-Lyu/TensorFLow-Learning/blob/master/3-2MNIST数据集分类简单版本.ipynb

2.2.2 优化代码

创建三层的神经网络,添加激活层,drop层,并使用交叉熵计算loss

1.dropout
  • 什么是drop

dropout是指在深度学习网络的训练过程中,对于神经网络单元,按照一定的概率将其暂时从网络中丢弃。注意是暂时,对于随机梯度下降来说,由于是随机丢弃,故而每一个mini-batch都在训练不同的网络。

一个非常好的解释:http://f.dataguru.cn/thread-714116-1-1.html

  • drop的作用原理

Dropout说的简单一点就是我们让在前向传导的时候,让某个神经元的激活值以一定的概率p,让其停止工作,示意图如下:

img

左边是原来的神经网络,右边是采用Dropout后的网络。怎么让某个神经元以一定的概率停止工作?这个我想很多人还不是很了解,代码层面的实现方法,下面就讲解一下其代码层面的实现。以前我们网络的计算公式是:

[外链图片转存失败(img-nLwLUEHB-1564902809840)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\1564835436421.png)]

上面公式中Bermoull函数,是为了以概率p,随机生成一个0、1的向量。

  • dropout的源代码
#dropout函数的实现  
def dropout(x, level):  
    if level < 0. or level >= 1:#level是概率值,必须在0~1之间  
        raise Exception('Dropout level must be in interval [0, 1[.')  
    retain_prob = 1. - level  
    #我们通过binomial函数,生成与x一样的维数向量。binomial函数就像抛硬币一样,我们可以把每个神经元当做抛硬币一样  
    #硬币 正面的概率为p,n表示每个神经元试验的次数  
    #因为我们每个神经元只需要抛一次就可以了所以n=1,size参数是我们有多少个硬币。  
    sample=np.random.binomial(n=1,p=retain_prob,size=x.shape)#即将生成一个0、1分布的向量,0表示这个神经元被屏蔽,不工作了,也就是dropout了  
    print sample  
    x *=sample#0、1与x相乘,我们就可以屏蔽某些神经元,让它们的值变为0  
    print x  
    x /= retain_prob  
  
    return x  
#对dropout的测试,大家可以跑一下上面的函数,了解一个输入x向量,经过dropout的结果  
x=np.asarray([1,2,3,4,5,6,7,8,9,10],dtype=np.float32)  
dropout(x,0.4)</span>  
  • dropout在tensorflow中的应用

    在tensorflow中dropout的应用tf.nn.dropout(x, keep_prob, noise_shape=None, seed=None,name=None)

    • x : 输入tensor
    • keep_prob : float类型,每个元素被保留下来的概率。 设置神经元被选中的概率,在初始化时keep_prob是一个占位符, keep_prob = tf.placeholder(tf.float32) 。tensorflow在run时设置keep_prob具体的值,例如keep_prob: 0.5
    • noise_shape : 一个1维的int32张量,代表了随机产生“保留/丢弃”标志的shape。
    • seed : 整形变量,随机数种子。
    • name : 名字,没啥用。
  • 区别tf.layers.dropout()tf.nn.dropout()

    在tf.layers中也有一个函数叫dropout(),他的作用是与上边的相同,不同在于

    • tf.nn.dropout 中参数 keep_prob :每一个元素被保存下的概率。而 tf.layer.dropout 中参数 rate :每一个元素丢弃的概率。所以,keep_prob = 1 - rate。
    • 在 tf.layer.dropout 中有一个 training 参数:在training模式中,返回应用dropout后的输出;或者在非training模式下,正常返回输出(没有dropout)。这里说的training模式也即是training参数为True的时候。
2.交叉熵

在tensorflow中,交叉熵一般调用以下函数:tf.nn.softmax_cross_entropy_with_logits(logits,labels,name=None)
除去name参数用以指定该操作的name,与方法有关的一共两个参数:
第一个参数logits:就是神经网络最后一层的输出,如果有batch的话,它的大小就是
[batchsize,num_classes],单样本的话,大小就是num_classes第二个参数labels:实际的标签,大小同上
具体的执行流程大概分为两步:
第一步是先对网络最后一层的输出做一个softmax,这一步通常是求取输出属于某一类的概率,对于单样本而言,输出就是一个num_classes大小的向量([Y1,Y2,Y3…]其中Y1,Y2,Y3…分别代表了是属于该类的概率)

其中softmax:

img

第二步是softmax的输出向量[Y1,Y2,Y3…]和样本的实际标签做一个交叉嫡,公式如下:

img

其中 y i ′ y_{i}^{&#x27;} yi指代实际的标签中第i个的值(用mnist数据举例,如果是3,那么标签是[0,0,0,1,0,0,0,0,0,0],除了第4个值为1,其他全为0)

y i y_{i} yi就是softmax的输出向量[Y1,Y2,Y3…]中,第i个元素的值显而易见,预测越准确,结果的值越小(别忘了前面还有负号),最后求一个平均,得到我们想要的loss注意!!!这个函数的返回值并不是一个数,而是一个向量,如果要求交叉篇,我们要再做一步tf.reduce_sum操作,就是对向量里面所有元素求和,最后才得到结果

如果求loss,则要做一步tf.reduce_mean操作,对向量求均值!

3.正式进入优化代码
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
# 批次的大小
batch_size = 100
n_batch = mnist.train.num_examples // batch_size

x = tf.placeholder(tf.float32, [None,784])
y = tf.placeholder(tf.float32, [None, 10])
keep_prob = tf.placeholder(tf.float32)    ##为什么需要这个变量,为了dropout时输入一个概率

#####################################创建一个三层的神经网络############################

W1 = tf.Variable(tf.truncated_normal([784,200],stddev=0.1))
b1 = tf.Variable(tf.zeros([1, 200]))
#######激活层
L1 = tf.nn.relu(tf.matmul(x,W1) + b1)
#######drop层
L1 = tf.nn.dropout(L1, keep_prob=keep_prob)

######第二层
W2 = tf.Variable(tf.truncated_normal([200,50],stddev=0.1))
b2 = tf.Variable(tf.zeros([1, 50]))
L2 = tf.nn.relu(tf.matmul(L1,W2) + b2)
L2 = tf.nn.dropout(L2, keep_prob=keep_prob)

#####第三层
W3 = tf.Variable(tf.truncated_normal([50,10],stddev=0.1))             ###stddev表示标准差
b3 = tf.Variable(tf.zeros([1, 10]))
L3 = tf.nn.relu(tf.matmul(L2,W3) + b3)
L3 = tf.nn.dropout(L3, keep_prob=keep_prob)

# 代价函数
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels = y,logits= L3))

# 梯度下降法
train_step = tf.train.GradientDescentOptimizer(0.2).minimize(loss)

# 初始化变量
init = tf.global_variables_initializer()
prediction = tf.nn.softmax(L3)

# 得到一个布尔型列表,存放结果是否正确
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(prediction, 1))

'''argmax 返回一维张量中最大值索引,例如对于y而言,[0 0 0 1 0 0 0 0 0 0],则返回3
对于prediction,[4.8889524e-05 4.8889524e-05 4.8889524e-05 9.1617345e-05 4.8889524e-05 4.8889524e-05 4.8889524e-05 9.9951732e-01 4.8889524e-05 4.8889524e-05]则返回7。
如果这两个返回的数值相等,则tf.equal()返回Ture,否则返回False
'''

# 求准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32)) 
# cast把布尔值转换为浮点型求平均数 Ture转换为1.0,False转换为0.0

with tf.Session() as sess:
    sess.run(init)
    for epoch in range(2):
        for batch in range(n_batch):
            # 获得批次数据
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            #mnist.train.next_batch(batch_size) 每次从训练集中取出batch_size大小的数据集,然后后移,下一次取时,从本次取值的后一位开始取
            sess.run(train_step, feed_dict={x:batch_xs, y:batch_ys,keep_prob:0.8})
        prediction1 = sess.run(prediction,feed_dict={x:mnist.test.images,keep_prob:0.8})
        print(prediction1)
        acc = sess.run(accuracy, feed_dict={x:mnist.test.images,y:mnist.test.labels,keep_prob:1.0})
        print("Iter " + str(epoch) + " Testing Accuracy: " + str(acc))

相关函数说明

  1. tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)

    • shape: 一维的张量,也是输出的张量。
    • mean: 正态分布的均值。
    • stddev: 正态分布的标准差。
    • dtype: 输出的类型。seed: 一个整数,当设置之后,每次生成的随机数都一样。
    • seed 随机种子,指定后,每次循环,生成的随机数都不变
    • name: 操作的名字

    ​ 该函数 从截断的正态分布中输出随机值。这是一个截断的产生正太分布的函数,就是说产生正太分布的值如果与均值的差值大于两倍的标准差,那就重新生成。和一般的正太分布的产生随机数据比起来,这个函数产生的随机数与均值的差距不会超过两倍的标准差,但是一般的别的函数是可能的。
    在正态分布的曲线中,横轴区间 ( μ − σ , μ + σ ) (\mu-\sigma, \mu+\sigma) (μσ,μ+σ)内的面积为68.268949%。
    横轴区间 ( μ − 2 σ , μ + 2 σ ) (\mu-2\sigma, \mu+2\sigma) (μ2σ,μ+2σ))内的面积为95.449974%。横轴区间 ( μ − 3 σ , μ + 3 σ ) (\mu-3\sigma, \mu+3\sigma) (μ3σ,μ+3σ)内的面积为99.730020%。
    X落在( ( μ − 3 σ , μ + 3 σ ) (\mu-3\sigma, \mu+3\sigma) (μ3σ,μ+3σ)以外的概率小于千分之三,在实际问题中常认为相应的事件是不会发生的,基本上可以把区间 ( μ − 3 σ , μ + 3 σ ) (\mu-3\sigma, \mu+3\sigma) (μ3σ,μ+3σ)看作是随机变量X实际可能的取值区间,这称之为正态分布的“30”原则。
    在tf.truncated_normal中如果x的取值在区间 ( μ − 2 σ , μ + 2 σ ) (\mu-2\sigma, \mu+2\sigma) (μ2σ,μ+2σ))内的之外则重新进行选择。这样保证了生成的值都在均值附近。

)内的面积为95.449974%。横轴区间 ( μ − 3 σ , μ + 3 σ ) (\mu-3\sigma, \mu+3\sigma) (μ3σ,μ+3σ)内的面积为99.730020%。
X落在( ( μ − 3 σ , μ + 3 σ ) (\mu-3\sigma, \mu+3\sigma) (μ3σ,μ+3σ)以外的概率小于千分之三,在实际问题中常认为相应的事件是不会发生的,基本上可以把区间 ( μ − 3 σ , μ + 3 σ ) (\mu-3\sigma, \mu+3\sigma) (μ3σ,μ+3σ)看作是随机变量X实际可能的取值区间,这称之为正态分布的“30”原则。
在tf.truncated_normal中如果x的取值在区间 ( μ − 2 σ , μ + 2 σ ) (\mu-2\sigma, \mu+2\sigma) (μ2σ,μ+2σ))内的之外则重新进行选择。这样保证了生成的值都在均值附近。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值