1. 程式人生 > >TensorFlow入門--Chapter02

TensorFlow入門--Chapter02

深層神經網路

1 深層神經網路


1.1 深度學習基本概念

維基百科定義:一類通過多層非線性變換對高複雜性資料建模演算法的集合
兩個重要特性:多層非線性


1.2 線性模型的侷限性

  • 線性模型的最大特點是任意線性模型的組合任然是線性模型
  • 一個線性模型通過輸入得到輸出的函式被稱為一個線性變換

缺點:由於現實中的問題往往不具有線性,因此線性模型解決的問題具有侷限性


1.3 使用啟用函式去線性化

chapter01 介紹的神經網路是一個線性模型,原因是對神經元結構的輸出為所有輸入的加權和,線性模型具有侷限性

解決:如果將每個神經元的輸出通過一個非線性函式(啟用函式),那麼整個神經網路就是非線性的了,去線性化前後對比程式碼如下:

#只展示部分程式碼
#去線性化之前
#random_normal生成隨機的符合正態分佈且 方差為1(stddev=1) 的 2x3陣列
w1 = tf.Variable(tf.random_normal([2, 3],stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal([3, 1],stddev=1, seed=1))
x = tf.placeholder(tf.float32, shape=(1, 2), name="input")
a = tf.matmul(x,w1)
y = tf.matmul(a,w2)

#去線性化之後
a =
tf.nn.relu(tf.matmul(x, w1) + biases1) y = tf.nn.relu(tf.matmul(x, w2) + biases2)
  • 常見啟用函式
函式名 函式作用
tf.nn.relu relu函式的定義:f(x)=max(x,0),x<0時,輸出始終為0。x>0時,導數為1
tf.sigmoid 可以將整個實數區間對映到(0,1)區間
tf.tanh tanh是雙曲正切函式,它將整個實數區間對映到了(-1,1),anh的收斂速度比sigmoid快

2 損失函式定義

神經網路模型的效果和優化的目標都是通過 損失函式 來定義的


2.1 經典損失函式

分類問題和迴歸問題是監督學習的兩大種類

  • 分類問題:解決的是將不同的樣本分到事先定義好的類別中
  1. 損失函式:交叉熵(刻畫了連個概率分佈之間的距離,分類問題中經常用)
  2. Softmax迴歸:交叉熵刻畫的是概率分佈之間的距離,然而神經網路輸出並不一定是概率分佈,概率分佈刻畫的是不同事件發生的概率,Softmax將神經網路的輸出變成一個概率分佈。
    在這裡插入圖片描述
    此時便可用交叉熵計算預測和真實的概率分佈之間的距離了。
#沒softmax迴歸的交叉熵損失函式
#tf.clip_by_value(A, min, max):張量A,A中元素的值都壓縮在min和max之間。小於min的讓它等於min,大於max的元素的值等於max
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))

  1. 交叉熵和Softmax迴歸
    因為經常交叉熵和softmax一起使用,所以TensorFlow對這兩個功能進行了封裝,tf.nn.sotfmax_cross_entropy_with_logits()函式 即softmax迴歸後的交叉熵損失函式
#labels代表是真實值,logist代表是預測值(神經網路輸出的結果)
cross_entropy = tf.nn.sotfmax_cross_entropy_with_logits(labels=y_, logist = y)
#在只有一個正確答案的時候,可以用tf.nn.sparse_softmax_cross_entropy_with_logits函式加速計算
  • 迴歸問題:對具體數值的預測,要預測的不是事先定義好的類別,而是一個任意實數
  1. 損失函式:最常用的就是均方誤差(MSE)
#y代表神經網路輸出答案,y_代表標準答案
mse = tf.reduce_mean(tf.square(y_ - y))

2.2 自定義損失函式

引入:在預測商品銷售時,如果預測多了,即預測值大於真實值,則會使商家虧生產商品的成本,如果預測少了,即預測值小於真實值,則會使商家少掙很多利潤。假如成本為1元,利潤為10元,多預測一個虧1元,少預測一個少掙10元。
如果神經網路最小化的是均值誤差,那麼有可能此模型無法最大化利潤,為了最大化利潤可以將損失函式和利潤聯絡起來


依據上面引入

  • 定義損失函式
    預測值>真實值 與 預測值<真實值 有不同的損失函式
    L o s s ( y , y ) = i = 1 N f ( y i , y i ) Loss(y,y&#x27;)=\sum_{i=1}^Nf(y_i,y_i&#x27;) , f ( x , y ) = { a ( x y ) x &gt; y b ( y x ) x y f(x,y) = \begin{cases} a(x-y) &amp; x&gt;y \\b(y-x) &amp; x\leq y \end{cases}

與均值方差類似: y i y_i 為一個batch中第i個數據的正確答案, y i y_i&#x27; 為神經網路得到的預測值,a=10代表 y i &gt; y i y_i &gt;y_i&#x27; 的代價,b=1代表 y i &lt; y i y_i&lt;y_i&#x27; 的代價
通過對這個自定義損失函式的優化,模型提供的預測值可能達到最大收益。

#tf.where函式類似C語言中的三目運算子 : ?,引數一為true時選第二個引數false選第三個
#tf.greater(v1,v2),比較v1和v2的值,v1>v2返回true否則false,v1,v2是張量

loss = tf.reduce_sum(tf.where(tf.greater(v1,v2), (v1-v2)*a, (v2-v1)*b))

#案例
import tensorflow as tf
v1 = tf.constant([1.0,2.0,3.0,4.0])
v2 = tf.constant([4.0,3.0,2.0,1.0])
sess = tf.InteractiveSession()
print(tf.greater(v1, v2).eval())
## 輸出:[False False  True  True]
print(tf.where(tf.greater(v1,v2),v1,v2).eval())
## 輸出:[4. 3. 3. 4.]
  • 損失函式對訓練結果的影響
#損失函式對模型的影響
import tensorflow as tf
from numpy.random import RandomState

#定義batch的大小
batch_size = 8

#兩個輸入節點
x = tf.placeholder(tf.float32, shape=(None, 2), name='x-input')

#迴歸問題一般只有一個輸出節點
y_ = tf.placeholder(tf.float32, shape=(None, 1), name='y-input')

#定義了一個單層的神經網路前向傳播的過程,這裡就是簡單的加權和
w1 = tf.Variable(tf.random_normal([2,1], stddev=1, seed=1))
y = tf.matmul(x, w1)

#定義預測多了和預測少了的成本
loss_less = 10
loss_more = 1
loss = tf.reduce_sum(tf.where(tf.greater(y, y_),(y-y_)*loss_more,(y_-y)*loss_less))
train_step = tf.train.AdamOptimizer(0.001).minimize(loss)

#通過隨機數生成一個模擬資料集
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size, 2)

#設定真實值,為兩個輸入的和加上一個隨機量(為了加入不可預測的噪音)否則不同損失函式意義不大, 噪音一般均值為0的小量,這裡設定為-0.05~0.05
Y = [[x1 + x2 + rdm.rand()/10.0 - 0.05] for(x1, x2) in X]

#訓練神經網路
with tf.Session() as sess:
    init = tf.global_variables_initializer()
    sess.run(init)
    for i in range(5000):
        #每次選一個batch的資料量來訓練
        start = (i*batch_size) % dataset_size
        end = min(start+batch_size, dataset_size) #start和end之間相差一個batch
        #訓練
        sess.run(train_step, feed_dict={x: X[start:end], y_:Y[start:end]})
        print(sess.run(w1))

輸出結果:
在這裡插入圖片描述

2.3 神經網路優化演算法

  • 梯度下降演算法:不能保證優化的函式達到全域性最優解

  • 隨機梯度下降演算法:可能無法達到區域性最優
    這個演算法的優化不是全部的資料集上的損失函式,而是在每一次的迭代過程中,隨機優化某一條資料上的損失函式

  • batch:為了綜合梯度下降和隨機梯度下降演算法,採用折中辦法,每次集散一小部分訓練資料的損失函式,這一小部分被稱為一個batch