【TensorFlow】笔记2:深层神经网络
一、深度學習 vs 深層神經(jīng)網(wǎng)絡
深度學習:一類通過多層非線性變換對高復雜性數(shù)據(jù)建模算法的集合。
1、激活函數(shù)
線性模型的最大特點:任意線性模型的組合仍是線性模型,能夠解決的問題也是有限的,這就是線性模型最大的局限。
==》解決方法:激活函數(shù)實現(xiàn)去線性化
如果將前面提到的加權(quán)和節(jié)點后(注意:添加偏置項)通過一個非線性函數(shù),那么神經(jīng)網(wǎng)絡模型就是非線性的了。這個非線性函數(shù)就是激活函數(shù)(activation)。
常用激活函數(shù):
- ReLU函數(shù)—— tf.nn.relu
- sigmoid函數(shù)——tf.nn.sigmoid
- tanh函數(shù)——tf.nn.tanh
使用激活函數(shù)和偏置項的前向傳播。
2、多層網(wǎng)絡解決異或運算
二、損失函數(shù)
1、經(jīng)典損失函數(shù)
(1)分類問題
交叉熵:兩個概率分布之間的距離,廣泛用于分類問題中。交叉熵是信息論中概念,原本用于估算平均編碼的長度。
公式:
對于給定兩個概率分布 ppp 和 qqq,通過 qqq 來表示 ppp 的交叉熵為:
H(p,q)=?∑xp(x)logq(x)H(p,q)=-\sum_{x}p(x)log\ q(x)H(p,q)=?x∑?p(x)log?q(x)
注意:交叉熵不是對稱的,H(p,q)≠H(q,p)H(p,q)\neq H(q,p)H(p,q)??=H(q,p),交叉熵刻畫通過通過概率分布 qqq 來表示 ppp 的困難程度。所以, qqq 表示預測結(jié)果, ppp 表示ground-truth。
交叉熵刻畫的是兩個概率分布的距離,然而神經(jīng)網(wǎng)絡的輸出不一定是一個概率分布(任意事件發(fā)生的概率都在0和1之間,且概率總和為1)。Softmax回歸是一個常用的將前向傳播結(jié)果變成概率分布的方法。
Softmax回歸本身可以作為一個學習算法來優(yōu)化分類結(jié)果,但在tf中,Softmax回歸的參數(shù)被去掉了,只作為一個額外的處理層,將輸出變成一個概率分布。
softmax(y)i=yi′=eyi∑j=1neyisoftmax(y)_i=y_i^\prime=\frac{e^{yi}}{\sum_{j=1}^{n}e^{yi}}softmax(y)i?=yi′?=∑j=1n?eyieyi?
交叉熵代碼實現(xiàn)
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))因為交叉熵一般與Softmax回歸一起使用,tf提供了 tf.nn.softmax_cross_entropy_with_logits 函數(shù):
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y)(2)回歸問題
回歸問題目標:具體數(shù)值的預測問題。
均方誤差(MSE, mean squared error)
公式:
MSE(y,y′)=∑i=1n(yi?yi′)2nMSE(y, y')=\frac{\sum_{i=1}^{n}(y_i-y_i')^2}{n}MSE(y,y′)=n∑i=1n?(yi??yi′?)2?
其中,yiy_iyi? 為一個 batch 中第 i 個數(shù)據(jù)的正確答案,yi′y_i'yi′? 為預測值
tf 實現(xiàn):
mse = tf.reduce_mean(tf.square(y_ - y))2、自定義損失函數(shù)
為了讓神經(jīng)網(wǎng)絡優(yōu)化的結(jié)果更加接近實際問題,我們需要自定義損失函數(shù)。
比如商品銷量問題,如果預測值較大(大于真實銷量),商家損失生產(chǎn)商品的成本。如果預測值較小,損失商品的利潤。因為一般成本和利潤不相同,使用均方誤差不能夠很好地最大化利潤。比如成本是1元,利潤是10元,那么模型應該偏向預測值較大。下面的公式給出了預測值多于或少于真實值時有不同系數(shù)的損失函數(shù),通過這個損失函數(shù),模型可能最大化收益。
Loss(y,y′)=∑i=1nf(yi,yi′),f(x,y)={a(x?y),if?x>yb(y?x),if?x≤yLoss(y,y')=\sum_{i=1}^{n}f(y_i,y_i'),f(x,y)=\begin{cases} a(x-y), & \text{if $x>y$} \\ b(y-x), & \text{if $x\leq y$ } \end{cases} Loss(y,y′)=i=1∑n?f(yi?,yi′?),f(x,y)={a(x?y),b(y?x),?if?x>yif?x≤y??
注意:損失函數(shù)定義的是損失,所以要將利潤最大化,定義的損失函數(shù)應該刻畫成本或代價。
tf 實現(xiàn)
loss = tf.reduce_sum(tf.where(tf.greater(v1, v2), (v1 - v2) * a, (v2 - v1) * b))整體代碼
import tensorflow as tf from numpy.random import RandomStatebatch_size = 8# 兩個輸入節(jié)點,一個輸出節(jié)點 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_mean(tf.where(tf.greater(y, y_), (y - y_) * loss_more, (y_ - y) * loss_less))train_step = tf.train.AdamOptimizer(0.001).minimize(loss)# 隨機數(shù)生成一個模擬數(shù)據(jù)集 rdm = RandomState(1) dataset_size = 128X = rdm.rand(dataset_size, 2) Y = [[x1 + x2 + rdm.rand()/10.0 - 0.05] for (x1, x2) in X]with tf.Session() as sess:init_op = tf.global_variables_initializer()sess.run(init_op)STEPS = 5000for i in range(STEPS):start = (i * batch_size) % dataset_sizeend = min(start + batch_size, dataset_size)sess.run(train_step, feed_dict={x: X[start: end], y_: Y[start: end]})print(sess.run(w1))輸出
2019-03-09 15:21:02.100189: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA 2019-03-09 15:21:02.193850: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:897] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero 2019-03-09 15:21:02.194763: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1405] Found device 0 with properties: name: GeForce GTX 1060 major: 6 minor: 1 memoryClockRate(GHz): 1.6705 pciBusID: 0000:01:00.0 totalMemory: 5.94GiB freeMemory: 5.37GiB 2019-03-09 15:21:02.194798: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1484] Adding visible gpu devices: 0 2019-03-09 15:21:02.422253: I tensorflow/core/common_runtime/gpu/gpu_device.cc:965] Device interconnect StreamExecutor with strength 1 edge matrix: 2019-03-09 15:21:02.422279: I tensorflow/core/common_runtime/gpu/gpu_device.cc:971] 0 2019-03-09 15:21:02.422285: I tensorflow/core/common_runtime/gpu/gpu_device.cc:984] 0: N 2019-03-09 15:21:02.422603: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1097] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 5139 MB memory) -> physical GPU (device: 0, name: GeForce GTX 1060, pci bus id: 0000:01:00.0, compute capability: 6.1) [[1.0193471][1.0428091]]三、神經(jīng)網(wǎng)絡優(yōu)化算法
關鍵:通過反向傳播算法(backpropagation)和梯度下降算法(Gradient Decent)調(diào)整神經(jīng)網(wǎng)絡中的參數(shù)。梯度下降算法主要用于優(yōu)化單個參數(shù)的取值,而反向傳播算法給出了一個高效的方式在所有參數(shù)上使用梯度下降算法。
1、優(yōu)化過程
- 前向傳播階段:通過前向傳播算法計算得到預測值,并計算損失函數(shù)。
- 反向傳播階段:計算損失函數(shù)對每一個參數(shù)的梯度,再根據(jù)梯度和學習率使用梯度下降算法更新每一個參數(shù)。更新公式如下:
θn+1=θn?η??θnJ(θn)\theta_{n+1}=\theta_n-\eta\frac{\partial}{\partial\theta_n}J(\theta_n)θn+1?=θn??η?θn???J(θn?)
其中,θ\thetaθ 表示需要更新的參數(shù),?\partial? 表示學習率,J(θn)J(\theta_n)J(θn?) 表示損失函數(shù)值
2、幾個概念
- 學習率
- 局部最優(yōu)
- 隨機梯度下降
- mini-batch梯度下降:不會比單個數(shù)據(jù)慢太多,同時可以大大減小收斂所需的迭代次數(shù),使得收斂到的結(jié)果更加接近梯度下降的效果。
3、神經(jīng)網(wǎng)絡訓練模式
import tensorflow as tfbatch_size = nx = tf.placeholder(tf.float32, shape=(None, 2), name='x-input') y_ = tf.placeholder(tf.float32, shape=(None, 1), name='y-input')# 定義損失函數(shù)和優(yōu)化算法 loss = ... train_step = tf.train.AdamOptimizer(0.001).minimize(loss)# 訓練神經(jīng)網(wǎng)絡 with tf.Session() as sess:# 初始化參數(shù)...# 迭代參數(shù)更新for i in range(STEPS):current_X, current_Y = ...sess.run(train_step, feed_dict={x: current_X, y_: current_Y})四、進一步優(yōu)化
1、學習率設置
通過指數(shù)縮減的方法設置梯度下降算法中的學習率,在 tf 中使用 tf.train.exponential_decay 函數(shù)實現(xiàn)。先使用較大的學習率快速得到一個比較優(yōu)的解,隨著迭代的繼續(xù)逐步減少學習率,使得模型在訓練后期更加穩(wěn)定。它實現(xiàn)了以下代碼的功能:
decayed_learning_rate = learning_rate * decay_rate * decay_rate ^ (global_step / decay_steps)其中,decayed_learning_rate 為每一輪優(yōu)化時使用的學習率,learning_rate 為設定的初始學習率,decay_rate 為衰減系數(shù),decay_steps 為衰減速度。
tf.train.exponential_decay 可以通過設置參數(shù)staircase 選擇不同的衰減方式,默認為 False,此時學習率衰減趨勢如下圖灰色曲線。當設置為 True 時,global_step/decay_steps 會被轉(zhuǎn)化成整數(shù),使得學習率成為一個階梯函數(shù),如黑色曲線。在這樣的設置下,decay_steps 通常代表完整使用一遍訓練數(shù)據(jù)所需要的迭代輪數(shù),也就是總訓練數(shù)據(jù)/一個batch的樣本數(shù)。這樣可以使得總訓練數(shù)據(jù)中的每一個batch都使用相同的學習率,對模型產(chǎn)生相等的作用。當完整過完一遍訓練數(shù)據(jù)時,學習率就減少一次。
tf 實現(xiàn)
import tensorflow as tfglobal_step = tf.Variable(0)# 通過exponential_decay函數(shù)生成學習率 learning_rate = tf.train.exponential_decay(0.1, grobal_step, 100, 0.96, staircase=True)# 使用指數(shù)衰減的學習率。在minimize中傳入global_step參數(shù),從而更新學習率 learning_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)2、過擬合問題
(1)正則化
正則化的思想是在損失函數(shù)中加入刻畫模型復雜程度的指標。所以一般優(yōu)化的損失函數(shù)為 J(θ)+λR(w)J(\theta)+\lambda R(w)J(θ)+λR(w)。一般來說模型復雜度只由權(quán)重w決定,和偏置b無關。
常用正則化:
- L1正則化
R(w)=∣∣w∣∣1=∑i∣wi∣R(w)=||w||_1=\sum_{i}|w_i|R(w)=∣∣w∣∣1?=i∑?∣wi?∣ - L2正則化
R(w)=∣∣w∣∣2=∑i∣wi2∣R(w)=||w||_2=\sum_{i}|w_i^2|R(w)=∣∣w∣∣2?=i∑?∣wi2?∣ - 同時使用L1正則化和L2正則化
R(w)=∣∣w∣∣2=∑iα∣wi∣+(2?α)wi2R(w)=||w||_2=\sum_{i}\alpha|w_i|+(2-\alpha)w_i^2R(w)=∣∣w∣∣2?=i∑?α∣wi?∣+(2?α)wi2?
L1正則化 會讓參數(shù)變得更稀疏,可達到類似特征選擇功能;而 L2正則 不會。其次,L1正則 的計算公式不可導,L2正則 可導。因為優(yōu)化時需要計算損失函數(shù)的偏導數(shù),所以對 L2正則 損失函數(shù)的優(yōu)化要更加簡潔。優(yōu)化 L1正則 更加復雜,而且優(yōu)化方法也有很多種。
TF 實現(xiàn)
帶 L2 正則項的損失函數(shù)
- tf.contrib.layers.l2_regularizer:計算給定參數(shù)的L2正則化項的值;
- tf.contrib.layers.l1_regularizer:計算L1正則化項的值。
當網(wǎng)絡結(jié)構(gòu)復雜后,利用集合(collection)計算損失函數(shù)。eg:計算一個 5 層神經(jīng)網(wǎng)絡帶 L2 正則化的損失函數(shù)計算方法。
import tensorflow as tf# 獲取一層神經(jīng)網(wǎng)絡邊上的權(quán)重,并將這個權(quán)重的L2正則化損失加入“l(fā)osses”的集合中 def get_weight(shape, lambda1):# 生成一個變量var = tf.Variable(tf.random_normal(shape), dtype=tf.float32)# add_to_collection函數(shù)將這個新生成變量的L2正則化損失項加入集合# 第一個參數(shù):losses是集合的名字,第二個參數(shù):要加入集合的內(nèi)容tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(lambda1)(var))return varx = tf.placeholder(tf.float32, shape=(None, 2)) y_ = tf.placeholder(tf.float32, shape=(None, 1)) batch_size = 8# 定義每一層網(wǎng)絡中節(jié)點的個數(shù) layer_dimension = [2, 10, 10, 10, 1] # 定義網(wǎng)絡的層數(shù) n_layers = len(layer_dimension)# 這個變量維護前向傳播時最深層的節(jié)點,開始的時候就是輸入層 cur_layer = x # 當前層的節(jié)點個數(shù) in_dimension = layer_dimension[0]# 通過一個循環(huán)來生成5層的FC層 for i in range(1, n_layers):# layer_dimension[i] 為下一層的節(jié)點個數(shù)out_dimension = layer_dimension[i]# 生成當前層中權(quán)重的變量,并將這個變量的L2正則化損失加入計算圖上的集合weight = get_weight([in_dimension, out_dimension], 0.001)bias = tf.Variable(tf.constant(0.1, shape=[out_dimension]))# ReLU activation functioncur_layer = tf.nn.relu(tf.matmul(cur_layer, weight) + bias)# 進入下一層之前將下一層的節(jié)點個數(shù)更新為當前層節(jié)點的個數(shù)in_dimension = layer_dimension[i]# 定義前向傳播的同時已經(jīng)將所有的L2正則化損失加入圖上的集合 # 這里只需要計算刻畫模型在訓練數(shù)據(jù)上表現(xiàn)的損失函數(shù) mse_loss = tf.reduce_mean(tf.square(y_ - cur_layer))# 將均方誤差損失加入到損失集合 tf.add_to_collection('losses', mse_loss)# get_collection 返回一個列表,該列表是所有這個集合中的元素。 # 在樣例中,這些元素就是損失函數(shù)的不同部分,將它們加起來就可以得到最終的損失函數(shù) loss = tf.add_n(tf.get_collection('losses'))3、滑動平均模型
作用:在使用隨機梯度下降算法訓練網(wǎng)絡時,可以使模型在測試數(shù)據(jù)上更健壯(robust)。
tf 的實現(xiàn):tf.train.ExponentialMovingAverage
參數(shù):
-
衰減率(decay):該參數(shù)用于控制模型更新的速度。ExponentialMovingAverage 對每一個變量會維護一個影子變量(shadow_variable),這個影子變量的初始值就是相應變量的初始值,而每次運行變量更新時,影子變量的值會更新為:
shadow_variable=decay×shadow_variable+(1?decay)×variableshadow\_variable=decay\times shadow\_variable + (1-decay)\times variableshadow_variable=decay×shadow_variable+(1?decay)×variable
其中,shadow_variable為影子變量,variable為待更新的變量,decay為衰減率,衰減率越大模型越穩(wěn)定。實際中,decay一般會設置非常接近1(eg: 0.999或0.9999)。 -
num_updates參數(shù):為了在訓練的前期更新得更快,通過設置num_updates參數(shù)來動態(tài)設置decay的大小。若初始化時提供num_updates參數(shù),則衰減率為:
min{decay,1+num_updates10+1+num_updates}min\{decay,\frac{1+num\_updates}{10+1+num\_updates}\}min{decay,10+1+num_updates1+num_updates?}
TF實現(xiàn)
import tensorflow as tf# 定義一個變量用于計算滑動平均,初始值為實數(shù)型的0 v1 = tf.Variable(0, dtype=tf.float32) # step 變量模擬神經(jīng)網(wǎng)絡中迭代的輪數(shù),可以用于控制衰減率 step = tf.Variable(0, trainable = False)# 定義一個滑動平均的類。初始化:衰減率(0.99)和控制衰減率的變量 step ema = tf.train.ExponentialMovingAverage(0.99, step) # 定義一個更新變量滑動平均的操作。 # 這里需要給定一個列表,每次執(zhí)行這個操作時,這個列表中的變量都會被更新 maintain_averages_op = ema.apply([v1]) with tf.Session() as sess:# 初始化所有變量init_op = tf.global_variables_initializer()sess.run(init_op)# 通過ema.average(v1)獲取滑動平均之后變量的取值。# 在初始化之后變量v1的值和v1的滑動平均都是0print(sess.run([v1, ema.average(v1)]))# output: [0.0, 0.0]# 更新變量v1的值到5sess.run(tf.assign(v1, 5))# 更新變量v1的值到5# 更新v1的滑動平均值。衰減率為min{0.99, (1+step)/(10+step)=0.1}=0.1,# 所以v1的滑動平均被更新為0.1*0+0.9*5=4.5sess.run(maintain_averages_op)print(sess.run([v1, ema.average(v1)]))# output: [5.0, 4.5]# 更新變量step的值到10000sess.run(tf.assign(step, 10000))# 更新變量v1的值到10sess.run(tf.assign(v1, 10))# 更新v1的滑動平均值。衰減率為min{0.99, (1+step)/(10+step)}=0.99,# 所以v1的滑動平均被更新為0.99*4.5+0.01*10=4.555sess.run(maintain_averages_op)print(sess.run([v1, ema.average(v1)]))# output: [10.0, 4.5549998]# 再次更新滑動平均值,得到的新滑動平均值為0.99*4.555+0.01*10 = 4.60945sess.run(maintain_averages_op)print(sess.run([v1, ema.average(v1)]))# Output: [10.0, 4.6094499]輸出結(jié)果
2019-03-13 22:50:23.313337: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA 2019-03-13 22:50:23.444235: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:897] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero 2019-03-13 22:50:23.445227: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1405] Found device 0 with properties: name: GeForce GTX 1060 major: 6 minor: 1 memoryClockRate(GHz): 1.6705 pciBusID: 0000:01:00.0 totalMemory: 5.94GiB freeMemory: 5.38GiB 2019-03-13 22:50:23.445260: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1484] Adding visible gpu devices: 0 2019-03-13 22:50:24.216058: I tensorflow/core/common_runtime/gpu/gpu_device.cc:965] Device interconnect StreamExecutor with strength 1 edge matrix: 2019-03-13 22:50:24.216088: I tensorflow/core/common_runtime/gpu/gpu_device.cc:971] 0 2019-03-13 22:50:24.216096: I tensorflow/core/common_runtime/gpu/gpu_device.cc:984] 0: N 2019-03-13 22:50:24.216673: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1097] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 5150 MB memory) -> physical GPU (device: 0, name: GeForce GTX 1060, pci bus id: 0000:01:00.0, compute capability: 6.1) [0.0, 0.0] [5.0, 4.5] [10.0, 4.555] [10.0, 4.60945] [Finished in 4.9s]總結(jié)
以上是生活随笔為你收集整理的【TensorFlow】笔记2:深层神经网络的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【LeetCode】128. 最长连续序
- 下一篇: 【TensorFlow】笔记3:MNIS