1. 程式人生 > >tensorflow實現神經網路

tensorflow實現神經網路

tensorflow實現神經網路

1、全部步驟

  1. 實現前向傳播
  2. 宣告學習率
  3. 引數進行正則化計算
  4. 計算損失函式
  5. 反向傳播
  6. 引數進行滑動平均

2、各個步驟解釋

前向傳播:主要是定義這個網路的結構,網路是幾層的,以及每層使用的啟用函式是什麼,一般前向傳播完成後,這個網路結構就已經完成。

宣告學習率 :學習率是定義了進行梯度下降時下降的速率

引數進行正則化計算、 計算損失函式:這兩個可以放在一起說,因為這兩個合在一起就是最終要優化的函式,,正則化和損失函式合在一起是最終的優化函式,其中正則化(防止過擬合)可以省略,但是如果使用的話可以採用L1或者L2正則化,其中L1、L2正則化只是一種計算的方式,你可以把其看做兩個函式,對於損失函式來說,可以使用均方誤差,也可以使用交叉熵進行計算。

反向傳播:主要是更新引數,因為要尋找能使損失函式最小的引數值,所以採用一種方式進行不斷的調整引數(一般使用梯度下降等方式)

引數進行滑動平均:這也是用在引數上面的,其主要目的是是的模型更加健壯。 注意的是:進行滑動平均的引數用來計算準確率,沒有滑動平均的引數進行計算損失函式。

3、各個步驟在Tensorflow中涉及到的API

前向傳播:主要是一個矩陣乘還有就是啟用函式。tf.matmul()、tf.nn.relu()

學習率:學習率可以只是一個常數,那麼就直接learning_rate = 0.03就行了,還有一種是指數衰減學習率,這個時候就需要藉助一個tf中的函數了tf.train.exponential_decay(),其具體使用可以自己參考tf官方api也可以自己網上搜索一下。

正則化:正則化主要是對引數進行正則化,使用regularizer = tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)可以產生一個函式regularizer ,這個函式可以對別的引數進行正則化 :regularizer(weights1)

損失函式:可以使用均方誤差,使用交叉熵,也可以自定義,這裡給出交叉熵的tf.nn.softmax_cross_entropy_with_logits_v2,還要注意最後要進行求均值,tf.reduce_mean,還要注意tf.nn.sparse_softmax_cross_entropy_with_logits和tf.nn.softmax_cross_entropy_with_logits_v2的區別。

https://blog.csdn.net/u013084616/article/details/79138380

反向傳播:反向傳播其實就是更新引數的過程,一般使用梯度下降tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step = global_step),從這個api中也可以看出裡面有學習率,還有損失函式(loss就是損失函式的定義)。所以這個api的作用就是以learning_rate為學習率,對loss函式進行最優化。

引數進行滑動平均:主要也是對引數的,

	#定義一個滑動平均類		
	average_class=tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)
	#定義一個滑動平均操作
    average_class_op = average_class.apply(tf.trainable_variables())   

在這裡插入圖片描述

4、程式碼實現上面過程-參考Tensorflow實戰Google深度學習框架

'''
Created on 2018年11月5日

@author: coderwangson
'''
"#codeing=utf-8"

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


INPUT_NODE = 784
OUTPUT_NODE = 10

LAYER1_NODE = 10

BATCH_SIZE = 100

LEARNING_RATE_BASE = 0.8
LEARNING_RATE_DECAY = 0.99

REGULARIZATION_RATE = 1e-4
TRAING_STEP = 30000
MOVING_AVERAGE_DECAY = 0.99

# 進行前向傳播計算

def inference(input_tensor,avg_class,weights1,bias1,weights2,bias2):
    if avg_class ==None:
        layer1 = tf.nn.relu(tf.matmul(input_tensor,weights1)+bias1)
        return tf.matmul(layer1,weights2)+bias2
    else:
        layer1 = tf.nn.relu(tf.matmul(input_tensor,avg_class.average(weights1))+avg_class.average(bias1))
        return tf.matmul(layer1,avg_class.average(weights2))+avg_class.average(bias2)


def train(mnist):
    x = tf.placeholder(tf.float32, [None,INPUT_NODE], "x_input")
    y_ = tf.placeholder(tf.float32,[None,OUTPUT_NODE],"y_input")
    
    weights1 = tf.Variable(tf.truncated_normal([INPUT_NODE,LAYER1_NODE],stddev=0.1))
    bias1 = tf.Variable(tf.constant(0.1,shape = [LAYER1_NODE]))
    weights2 = tf.Variable(tf.truncated_normal([LAYER1_NODE,OUTPUT_NODE],stddev=0.1))
    bias2 = tf.Variable(tf.constant(0.1,shape = [OUTPUT_NODE]))
    
    # 前向傳播	   
    # 沒有使用滑動平均
	y = inference(x,None,weights1,bias1,weights2,bias2) 
    global_step = tf.Variable(0,trainable=False)
    average_class = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)
    average_class_op = average_class.apply(tf.trainable_variables())
#     使用滑動平均
    average_y = inference(x,average_class,weights1,bias1,weights2,bias2)
    
    #損失函式  sparse_softmax_cross_entropy_with_logits適用於稀疏矩陣的時候
    """
        兩個函式雖然功能類似,但是其引數labels有明顯區別。
   tf.nn.softmax_cross_entropy_with_logits()
        中的logits和labels的shape都是[batch_size, num_classes],
        而tf.nn.sparse_softmax_cross_entropy_with_logits()中的labels是稀疏表示的,
        是 [0,num_classes)中的一個數值,代表正確分類結果。
        即sparse_softmax_cross_entropy_with_logits 直接用標籤計算交叉熵,
        而 softmax_cross_entropy_with_logits 是標籤的onehot向量參與計算。
   softmax_cross_entropy_with_logits 的 labels 是 sparse_softmax_cross_entropy_with_logits 的 labels 的一個one hot version。
"""
    
	#損失函式
    cross_entropy = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels=tf.argmax(y_, 1), logits=y))
    
    #正則化
    regularizer = tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)
    regularization = regularizer(weights1) + regularizer(weights2)
    
    loss = cross_entropy+regularization
    
    #學習率
    learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE,global_step ,mnist.train.num_examples/BATCH_SIZE,LEARNING_RATE_DECAY)
    
    # 反向傳播
    train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step = global_step)
    
	#因為兩個都要更新引數,並且二者是獨立的(參考上面那個圖),所以把二者合成一個操作,方便sess.run()
    with tf.control_dependencies([train_step,average_class_op]):
        train_op = tf.no_op(name = 'train')
        
    correct_prediction = tf.equal(tf.arg_max(average_y,1),tf.argmax(y_,1))
    
    accuracy  = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
    
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        
        validate_feed = {x:mnist.validation.images,y_:mnist.validation.labels}
        test_feed = {x:mnist.test.images,y_:mnist.test.labels}
        
        for i in range(TRAING_STEP):
            if i%1000 ==0:
                validate_acc = sess.run(accuracy,feed_dict = validate_feed)
                print("this is %dth acc is %g"%(i,validate_acc))
        
            xs,ys = mnist.train.next_batch(BATCH_SIZE)
            sess.run(train_op,feed_dict = {x:xs,y_:ys})
  
            
        test_acc = sess.run(accuracy,feed_dict = test_feed)
        print("the test acc is %g"%test_acc)


    
    
mnist = input_data.read_data_sets("./data",one_hot=True)
# print(mnist.test.num_examples)
train(mnist)