1. 程式人生 > 實用技巧 >學習進度筆記13

學習進度筆記13

TnsorFlow多層感知機

多層感知機是由感知機推廣而來,感知機學習演算法(PLA: Perceptron Learning Algorithm)用神經元的結構進行描述的話就是一個單獨的。

感知機(PLA)的神經網路表示如下:

從上述內容更可以看出,PLA是一個線性的二分類器,但不能對非線性的資料進行有效的分類。因此便有了對網路層次的加深,理論上,多層網路可以模擬任何複雜的函式。

多層感知機MLP多層感知機的一個重要特點就是多層,我們將第一層稱之為輸入層,最後一層稱之有輸出層,中間的層稱之為隱層。MLP並沒有規定隱層的數量,因此可以根據各自的需求選擇合適的隱層層數且對於輸出層神經元的個數也沒有限制。

MLP神經網路結構模型如下,本圖中只涉及了一個隱層,輸入只有三個變數[x1,x2,x3]和一個偏置量b,輸出層有三個神經元。相比於感知機演算法中的神經元模型對其進行了整合。

前向傳播

前向傳播指的是資訊從第一層逐漸地向高層進行傳遞的過程,以下圖為例來進行前向傳播的過程的分析。

假設第一層為輸入層,輸入的資訊為[x1,x2,x3]。對於層l,用Ll表示該層的所有神經元,其輸出為yl,其中第j個節點的輸出為yl(j),該節點的輸入為ul(j),連線第l層與第(l−1)層的權重矩陣為Wl,上一層(第l−1層)的第i個節點到第l層第j個節點的權重為wl(ji)。

結合之前定義的字母標記,對於第二層的三個神經元的輸出則有

將上述的式子轉換為矩陣表示式:

將第二層的前向傳播計算過程推廣到網路中的任意一層,則:

其中f(⋅)為啟用函式,bl(j)為第l層第j個節點的偏置。

反向傳播

基本的模型搭建完成後,訓練的時候所做的就是完成模型引數的更新。由於存在多層的網路結構,因此無法直接對中間的隱層利用損失來進行引數更新,但可以利用損失從頂層到底層的反向傳播來進行引數的估計。(約定:小寫字母—標量,加粗小寫字母—向量,大寫字母—矩陣)

假設多層感知機用於分類,在輸出層有多個神經元,每個神經元對應一個標籤。輸入樣本為x=[x1,x2,⋯,xn],其標籤為t;對於層l,用Ll表示該層的所有神經元,其輸出為yl,其中第j個節點的輸出為yl(j),該節點的輸入為ul(j),連線第l層與第(l−1)層的權重矩陣為Wl,上一層(第l−1層)的第i個節點到第l層第j個節點的權重為wl(ji)。

對於網路的最後一層第k層——輸出層,現在定義損失函式:

為了極小化損失函式,通過梯度下降來進行推導:

在上面式子中,根據之前的定義,很容易得到:

那麼則有:

另有,下一層所有結點的輸入都與前一層的每個結點輸出有關,因此損失函式可以認為是下一層的每個神經元結點輸入的函式。那麼:

此處定義節點的靈敏度為誤差對輸入的變化率,即:

那麼第l層第j個節點的靈敏度為:

結合靈敏度的定義,則有:

上式兩邊同時乘上f ′(ul(j)),則有

注意到上式中表達的是前後兩層的靈敏度關係,而對於最後一層,也就是輸出層來說,並不存在後續的一層,因此並不滿足上式。但輸出層的輸出是直接和誤差聯絡的,因此可以用損失函式的定義來直接求取偏導數。那麼:

至此,損失函式對各引數的梯度為:

上述的推導都是建立在單個節點的基礎上,對於各層所有節點,採用矩陣的方式表示,則上述公式可以寫成:

其中運算子∘表示矩陣或者向量中的對應元素相乘。

常見的幾個啟用函式的導數為:

根據上述公式,可以得到各層引數的更新公式為:

原始碼:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import os
os.environ["CUDA_VISIBLE_DEVICES"]="0"

mnist=input_data.read_data_sets("/home/yxcx/tf_data",one_hot=True)

#Parameters
learning_rate=0.001
training_epochs=15
batch_size=100
display_step=1

#Network Parameters
n_hidden_1=256
n_hidden_2=256
n_input=784
n_classes=10

# tf Graph input
X=tf.placeholder("float",[None,n_input])
Y=tf.placeholder("float",[None,n_classes])

#Store layers weight & bias
weights={
    "h1":tf.Variable(tf.random_normal([n_input,n_hidden_1])),
    "h2":tf.Variable(tf.random_normal([n_hidden_1,n_hidden_2])),
    "out":tf.Variable(tf.random_normal([n_hidden_2,n_classes]))
}
biases={
    'b1':tf.Variable(tf.random_normal([n_hidden_1])),
    'b2':tf.Variable(tf.random_normal([n_hidden_2])),
    'out':tf.Variable(tf.random_normal([n_classes]))
}

# Create model
def multiplayer_perceptron(x):
    # Hidden fully connected layer with 256 neurons
    layer_1=tf.add(tf.matmul(x,weights['h1']),biases['b1'])
    #Hidden fully connected layer with 256 neurons
    layer_2=tf.add(tf.matmul(layer_1,weights['h2']),biases['b2'])
    #Output fully connected layer with a neuron for each class
    out_layer=tf.matmul(layer_2,weights['out'])+biases['out']
    return out_layer

#Construct model
logits=multiplayer_perceptron(X)

#Define loss and optimizer
loss_op=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
    logits=logits,labels=Y))
train_op=tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss_op)

# Initializing the variables
init=tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    #Training cycle
    for epoch in range(training_epochs):
        avg_cost=0
        total_batch=int(mnist.train.num_examples/batch_size)
        #loop over all batches
        for i in range(total_batch):
            batch_x,batch_y=mnist.train.next_batch(batch_size)
            #Run optimizeation op and cost op to get loss value
            _,c=sess.run([train_op,loss_op],feed_dict={X:batch_x,Y:batch_y})
            #computer average loss
            avg_cost+=c/total_batch
        #Display logs per epoch step
        if epoch % display_step==0:
            print("Epoch:","%04d"%(epoch+1),"cost={:.9f}".format(avg_cost))
    print("Optimization Finished!")
    #Test model
    pred=tf.nn.softmax(logits)
    correct_prediction=tf.equal(tf.argmax(pred,1),tf.argmax(Y,1))
    # Calculate accuracy
    accuracy=tf.reduce_mean(tf.cast(correct_prediction,"float"))
    print("Accuracy:",accuracy.eval({X:mnist.test.images,Y:mnist.test.labels}))

結果截圖: