TensorFlow:实战Google深度学习框架(四)MNIST数据集识别问题
- 第5章 MNIST數(shù)字識別問題
- 5.1 MNIST數(shù)據(jù)處理
- 5.2 神經(jīng)網(wǎng)絡(luò)的訓(xùn)練以及不同模型結(jié)果的對比
- 5.2.1 TensorFlow訓(xùn)練神經(jīng)網(wǎng)絡(luò)
- 5.2.2 使用驗證數(shù)據(jù)集判斷模型的效果
- 5.2.3 不同模型效果比較
- 5.3 變量管理
- 5.4 TensorFlow模型持久化
- 5.4.1 持久化代碼實現(xiàn)
- 1. ckpt文件的保存
- 2. 加載已經(jīng)保存的TensorFlow模型
- 5.4.2 持久化原理及數(shù)據(jù)格式
- 5.4.1 持久化代碼實現(xiàn)
- 5.5 最佳實踐樣例程序
- 1. 定義神經(jīng)網(wǎng)絡(luò)的前向傳播過程
- 2. 訓(xùn)練程序
- 3. 代碼
- 5.6 補(bǔ)充
- 5.6.1 單層神經(jīng)網(wǎng)絡(luò)
- 5.6.2 梯度下降
- 5.6.3 學(xué)習(xí)速率衰減
- 5.6.4 過擬合和dropout
第5章 MNIST數(shù)字識別問題
5.1 MNIST數(shù)據(jù)處理
MNIST數(shù)據(jù)集是NIST數(shù)據(jù)集的一個子集,包含60000張作為訓(xùn)練數(shù)據(jù),10000張作為測試數(shù)據(jù),圖片大小為28*28。
- TensorFlow提供了一個類來處理MINIST數(shù)據(jù),會自動下載并轉(zhuǎn)化MINIST數(shù)據(jù)的格式,解析成訓(xùn)練和測試神經(jīng)網(wǎng)絡(luò)時的使用格式
讀取mnist數(shù)據(jù)集的程序如下
# 在Yann LeCun教授的網(wǎng)站中(http://yann.lecun.com/exdb/mnist ) 對MNIST數(shù)據(jù)集做出了詳細(xì)的介紹。 # 1. 讀取數(shù)據(jù)集,第一次TensorFlow會自動下載數(shù)據(jù)集到下面的路徑中 from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)# 2. 數(shù)據(jù)集會自動被分成3個子集,train、validation和test。以下代碼會顯示數(shù)據(jù)集的大小。 print("Training data size: ", mnist.train.num_examples) print("Validating data size: ", mnist.validation.num_examples) print("Testing data size: ", mnist.test.num_examples)# 3. 查看training數(shù)據(jù)集中某個成員的像素矩陣生成的一維數(shù)組和其屬于的數(shù)字標(biāo)簽。 print("Example training data: ", mnist.train.images[0]) print("Example training data label: ", mnist.train.labels[0])# 4. 使用mnist.train.next_batch來實現(xiàn)隨機(jī)梯度下降。 batch_size = 100 xs, ys = mnist.train.next_batch(batch_size) # 從train的集合中選取batch_size個訓(xùn)練數(shù)據(jù)。 print("X shape:", xs.shape) print("Y shape:", ys.shape)輸出結(jié)果
Extracting MNIST_data/train-images-idx3-ubyte.gz Extracting MNIST_data/train-labels-idx1-ubyte.gz Extracting MNIST_data/t10k-images-idx3-ubyte.gz Extracting MNIST_data/t10k-labels-idx1-ubyte.gzTraining data size: 55000 Validating data size: 5000 Testing data size: 10000 Example training data:[太多了,不列舉了] Example training data label: [ 0. 0. 0. 0. 0. 0. 0. 1. 0. 0.] X shape: (100, 784) Y shape: (100, 10)5.2 神經(jīng)網(wǎng)絡(luò)的訓(xùn)練以及不同模型結(jié)果的對比
神經(jīng)網(wǎng)絡(luò)在驗證數(shù)據(jù)集上的表現(xiàn)可以近似的作為評價不同神經(jīng)網(wǎng)絡(luò)模型的標(biāo)準(zhǔn)或決定迭代次數(shù)的依據(jù)。
為了評測神經(jīng)網(wǎng)絡(luò)模型在不同參數(shù)下的效果,一般會從訓(xùn)練數(shù)據(jù)中抽取一部分作為驗證數(shù)據(jù)。使用驗證數(shù)據(jù)就可以評判不同參數(shù)取值下模型的表現(xiàn)。除了使用驗證數(shù)據(jù)集,還可以采用交叉驗證(cross validation)的方式來驗證模型效果,但因為神經(jīng)網(wǎng)絡(luò)訓(xùn)練實踐本身就比較長,采用cross validation會花費(fèi)大量時間。所以在海量數(shù)據(jù)的情況下,一般會更多地采用驗證數(shù)據(jù)集的形式來評測模型的效果。
為了說明驗證數(shù)據(jù)在一定程度上可以作為模型效果的評判標(biāo)準(zhǔn),我們將對比在不同迭代輪數(shù)的情況下,模型在驗證數(shù)據(jù)和測試數(shù)據(jù)上的正確率。為了同時得到同一個模型在驗證數(shù)據(jù)和測試數(shù)據(jù)上的正確率,可以在每1000輪的輸出中加入在測試數(shù)據(jù)集上的正確率。
在神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)的設(shè)計上,需要使用激活函數(shù)和多層隱藏層。在神經(jīng)網(wǎng)絡(luò)優(yōu)化時,可以使用指數(shù)衰減的學(xué)習(xí)率,加入正則化的損失函數(shù)以及滑動平均模型。
5.2.1 TensorFlow訓(xùn)練神經(jīng)網(wǎng)絡(luò)
# 《TensorFlow實戰(zhàn)Google深度學(xué)習(xí)框架》05 minist數(shù)字識別問題 # filename:ts05.02.py # TensorFlow訓(xùn)練神經(jīng)網(wǎng)絡(luò)--全模型import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data# 1.設(shè)置輸入和輸出節(jié)點的個數(shù),配置神經(jīng)網(wǎng)絡(luò)的參數(shù) INPUT_NODE = 784 # 輸入節(jié)點個數(shù),對于該數(shù)據(jù)集就是圖片像素總數(shù) OUTPUT_NODE = 10 # 輸出節(jié)點,等同于類別個數(shù) LAYER1_NODE = 500 # 隱藏層數(shù),此處使用僅有一個隱藏層,500個節(jié)點BATCH_SIZE = 100 # 一個batch中樣本個數(shù),數(shù)字越小,越接近隨機(jī)梯度下降,數(shù)字越大,越接近梯度下降# 模型相關(guān)的參數(shù) LEARNING_RATE_BASE = 0.8 # 基礎(chǔ)學(xué)習(xí)率 LEARNING_RATE_DECAY = 0.99 # 學(xué)習(xí)率的衰減率 REGULARAZTION_RATE = 0.0001 # 描述模型復(fù)雜度的正則化項在損失函數(shù)中的系數(shù) TRAINING_STEPS = 30000 # 訓(xùn)練次數(shù) MOVING_AVERAGE_DECAY = 0.99 # 滑動平均衰減率# 2. 定義輔助函數(shù)來計算前向傳播結(jié)果,使用ReLU做為激活函數(shù)。 def inference(input_tensor, avg_class, weights1, biases1, weights2, biases2):# 不使用滑動平均類if avg_class == None:layer1 = tf.nn.relu(tf.matmul(input_tensor, weights1) + biases1)return tf.matmul(layer1, weights2) + biases2else:# 使用滑動平均類layer1 = tf.nn.relu(tf.matmul(input_tensor, avg_class.average(weights1)) + avg_class.average(biases1))return tf.matmul(layer1, avg_class.average(weights2)) + avg_class.average(biases2)# 3. 定義訓(xùn)練過程 def train(mnist):x = tf.placeholder(tf.float32, [None, INPUT_NODE], name='x-input')y_ = tf.placeholder(tf.float32, [None, OUTPUT_NODE], name='y-input')# 生成隱藏層的參數(shù)。weights1 = tf.Variable(tf.truncated_normal([INPUT_NODE, LAYER1_NODE], stddev=0.1))biases1 = tf.Variable(tf.constant(0.1, shape=[LAYER1_NODE]))# 生成輸出層的參數(shù)。weights2 = tf.Variable(tf.truncated_normal([LAYER1_NODE, OUTPUT_NODE], stddev=0.1))biases2 = tf.Variable(tf.constant(0.1, shape=[OUTPUT_NODE]))# 計算不含滑動平均類的前向傳播結(jié)果y = inference(x, None, weights1, biases1, weights2, biases2)# 定義訓(xùn)練輪數(shù)及相關(guān)的滑動平均類global_step = tf.Variable(0, trainable=False)variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)variables_averages_op = variable_averages.apply(tf.trainable_variables())average_y = inference(x, variable_averages, weights1, biases1, weights2, biases2)# 計算交叉熵及其平均值cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))cross_entropy_mean = tf.reduce_mean(cross_entropy)# 損失函數(shù)的計算regularizer = tf.contrib.layers.l2_regularizer(REGULARAZTION_RATE)regularaztion = regularizer(weights1) + regularizer(weights2)loss = cross_entropy_mean + regularaztion# 設(shè)置指數(shù)衰減的學(xué)習(xí)率。learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE,global_step,mnist.train.num_examples / BATCH_SIZE,LEARNING_RATE_DECAY,staircase=True)# 優(yōu)化損失函數(shù)train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)# 反向傳播更新參數(shù)和更新每一個參數(shù)的滑動平均值with tf.control_dependencies([train_step, variables_averages_op]):train_op = tf.no_op(name='train')# 計算正確率correct_prediction = tf.equal(tf.argmax(average_y, 1), tf.argmax(y_, 1))accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))# 初始化回話并開始訓(xùn)練過程。with tf.Session() as sess:tf.global_variables_initializer().run()validate_feed = {x: mnist.validation.images, y_: mnist.validation.labels}test_feed = {x: mnist.test.images, y_: mnist.test.labels}# 循環(huán)的訓(xùn)練神經(jīng)網(wǎng)絡(luò)。for i in range(TRAINING_STEPS):if i % 1000 == 0:validate_acc = sess.run(accuracy, feed_dict=validate_feed)print("After %d training step(s), validation accuracy using average model 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(("After %d training step(s), test accuracy using average model is %g" % (TRAINING_STEPS, test_acc)))# 4. 主程序入口,這里設(shè)定模型訓(xùn)練次數(shù)為5000次。 def main(argv=None):mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)train(mnist)if __name__=='__main__':tf.app.run()結(jié)果:
After 0 training step(s), validation accuracy using average model is 0.111 After 1000 training step(s), validation accuracy using average model is 0.977 After 2000 training step(s), validation accuracy using average model is 0.9824 After 3000 training step(s), validation accuracy using average model is 0.9832 After 4000 training step(s), validation accuracy using average model is 0.9848 After 5000 training step(s), test accuracy using average model is 0.9822 ...由以上結(jié)果可以看出,在訓(xùn)練初期,隨著訓(xùn)練的進(jìn)行,模型在驗證數(shù)據(jù)集上的表現(xiàn)越來越好,但從4000輪開始,模型在驗證數(shù)據(jù)集上的表現(xiàn)開始波動,這說明模型已經(jīng)接近極小值了,所以迭代已經(jīng)可以結(jié)束了。
5.2.2 使用驗證數(shù)據(jù)集判斷模型的效果
所需初始參數(shù):上述程序的開始,設(shè)置了初始學(xué)習(xí)率、學(xué)習(xí)率衰減率、隱藏層節(jié)點數(shù)、迭代次數(shù)、batch_size、正則項系數(shù)、滑動平均衰減數(shù)等7個不同的參數(shù)。
如何設(shè)置初始參數(shù):一般情況需要實驗來調(diào)整
設(shè)置初始參數(shù)難點:雖然模型的最終效果是在測試數(shù)據(jù)上進(jìn)行判定的,但不能直接使用測試數(shù)據(jù),否則會過擬合,從而丟失對未知數(shù)據(jù)的判斷能力,所以要保證測試數(shù)據(jù)在訓(xùn)練過程中是不可見的。
解決方法:
- 從訓(xùn)練數(shù)據(jù)中抽取一部分作為驗證數(shù)據(jù),來評判不同參數(shù)取值下模型的表現(xiàn)。
- 使用“交叉驗證(cross validation)”,但是神經(jīng)網(wǎng)絡(luò)的訓(xùn)練時間本身就比較長,所以采用該方法會花費(fèi)大量的時間,故一般不會選用。
下面使用代碼來對比模型在不同迭代次數(shù)情況下,在驗證數(shù)據(jù)和測試數(shù)據(jù)上的正確率。
# 為了同時得到模型在測試數(shù)據(jù)和驗證數(shù)據(jù)上的正確率,可以在每1000輪的輸出中加入在測試數(shù)據(jù)集上的正確率for i in range(TRAINING_STEPS):if i % 1000 == 0:# 計算滑動平均模型在測試數(shù)據(jù)集和驗證數(shù)據(jù)集上的正確率validate_acc = sess.run(accuracy, feed_dict=validate_feed)test_acc = sess.run(accuracy, feed_dict=test_feed)print("After %d training step(s), validation accuracy using average model is %g ,test accuracy using average model is %g" % (i, validate_acc,test_acc))xs, ys = mnist.train.next_batch(BATCH_SIZE)sess.run(train_op, feed_dict={x: xs, y_: ys})結(jié)果:
After 0 training step(s), validation accuracy using average model is 0.1114 , test accuracy using average model is 0.109 After 1000 training step(s), validation accuracy using average model is 0.9778 , test accuracy using average model is 0.9741 After 2000 training step(s), validation accuracy using average model is 0.9822 , test accuracy using average model is 0.9798 After 3000 training step(s), validation accuracy using average model is 0.9838 , test accuracy using average model is 0.9816 After 4000 training step(s), validation accuracy using average model is 0.9846 , test accuracy using average model is 0.9824 After 5000 training step(s), validation accuracy using average model is 0.9852 , test accuracy using average model is 0.9823 After 6000 training step(s), validation accuracy using average model is 0.9858 , test accuracy using average model is 0.9829 After 7000 training step(s), validation accuracy using average model is 0.985 , test accuracy using average model is 0.983 After 8000 training step(s), validation accuracy using average model is 0.9854 , test accuracy using average model is 0.9831可以看出,驗證集和測試集雖然不完全一樣,但是其趨勢相同,且它們的相關(guān)系數(shù)為0.9999,意味著在MNIST數(shù)據(jù)集上完全可以通過模型在驗證數(shù)據(jù)集上的表現(xiàn)來判斷一個模型的優(yōu)劣。
5.2.3 不同模型效果比較
在神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)的設(shè)計上,需要使用激活函數(shù)和多層隱藏層。在神經(jīng)網(wǎng)絡(luò)優(yōu)化時,可以使用指數(shù)衰減的學(xué)習(xí)率,加入正則化的損失函數(shù)以及滑動平均模型。
1. 本質(zhì)影響:神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)
2. 滑動平均模型、指數(shù)衰減的學(xué)習(xí)率、正則化對MNIST數(shù)據(jù)集影響看起來不是很大的原因:
- 因為滑動平均模型、指數(shù)衰減的學(xué)習(xí)率都在限制神經(jīng)網(wǎng)絡(luò)的參數(shù)的更新速度,而該數(shù)據(jù)庫模型收斂的速度很快,所以影響不大。
- 但是當(dāng)問題更復(fù)雜時,迭代不會很快收斂,所以滑動平均模型、指數(shù)衰減的學(xué)習(xí)率可以發(fā)揮更大的作用。
- 正則化帶來的效果更為顯著
總結(jié):優(yōu)化方法可以對模型帶來更好的效果(模型越復(fù)雜,效果越明顯)
5.3 變量管理
當(dāng)神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)復(fù)雜、參數(shù)很多時,需要更好的方式來傳遞和管理神經(jīng)網(wǎng)絡(luò)的參數(shù)。
TensorFlow提供了通過變量名稱來創(chuàng)建或獲取一個變量的機(jī)制,不同函數(shù)可以直接通過變量的名字來使用變量,不需要通過參數(shù)的形式到處傳遞。
- 通過變量名稱來獲取變量:
- TensorFlow提供了7種不同的初始化函數(shù)
| tf.constant_initializer | 將變量初始化為給定常量 | 常量的取值 |
| tf.random_normal_initializer | 將變量初始化為滿足正太分布的隨機(jī)值 | 正太分布的均值和標(biāo)準(zhǔn)差 |
| tf.truncated_normal_initializer | 將變量初始化為滿足正太分布的隨機(jī)值,但若隨機(jī)出來的值偏離平均值超過兩個標(biāo)準(zhǔn)差,那么這個數(shù)將會被重新隨機(jī) | 正太分布的均值和標(biāo)準(zhǔn)差 |
| tf.random_uniform_initializer | 將變量初始化為滿足平均分布的隨機(jī)值 | 最大,最小值 |
| tf.uniform_unit_scaling_initializer | 將變量初始化為滿足平均分布但不影響輸出數(shù)量級的隨機(jī)值 | factor(產(chǎn)生隨機(jī)值時乘以的系數(shù)) |
| tf.zeros_initializer | 將變量設(shè)置為全為0 | 變量維度 |
| tf.ones_initializer | 將變量設(shè)置為全為1 | 變量維度 |
- tf.get_variable:
- tf.get_variable變量名是一個必填參數(shù),其首先會試圖去創(chuàng)建一個名字為v的參數(shù),如果創(chuàng)建失敗(比如已經(jīng)有同名的參數(shù)),那么這個程序就會報錯。這是為了避免無意識的變量復(fù)用造成的錯誤。比如在定義神經(jīng)網(wǎng)絡(luò)參數(shù)時,第一層網(wǎng)絡(luò)的權(quán)重已經(jīng)叫weights了,那么在創(chuàng)建第二層神經(jīng)網(wǎng)絡(luò)時,如果參數(shù)名仍然叫weights,就會觸發(fā)變量重用的錯誤。否則兩層神經(jīng)網(wǎng)絡(luò)共用一個權(quán)重會出現(xiàn)一些比較難以發(fā)現(xiàn)的錯誤。
- 如果需要通過tf.get_variable獲取一個已經(jīng)創(chuàng)建的變量,需要通過tf.variable_scope函數(shù)來生成一個上下文管理器,并明確指定在這個上下文管理器中,tf.get_variable將直接獲取已經(jīng)生成的變量。
- 下面給出一段代碼說明如何通過tf.variable_scope函數(shù)來控制tf.get_variable函數(shù)獲取已經(jīng)創(chuàng)建過的變量。
通過 tf.variable_scope 控制 tf.get_variable 的語義:
- 如果tf.variable_scope函數(shù)使用參數(shù) reuse=None 或者reuse=False創(chuàng)建上下文管理器,tf.get_variable操作將創(chuàng)建新的變量,如果同名的變量已經(jīng)存在,則tf.get_variable函數(shù)將報錯。另外,Tensorflow中tf.variable_scope函數(shù)是可以嵌套的。
如果tf.variable_scope函數(shù)使用參數(shù) reuse=True 生成上下文管理器時,該上下文管理器中的所有 tf.get_variable 函數(shù)會直接獲取已經(jīng)創(chuàng)建的變量,如果變量不存在,將會報錯。
使用變量管理后,就不再需要將所有變量都作為參數(shù)傳遞到不同的函數(shù)中了,當(dāng)神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)更加復(fù)雜,參數(shù)更多時,使用這種變量管理的方式將大大提高程序的可讀性。
示例代碼:
- 通過 tf.variable_scope 來管理變量命名空間:
利用上述兩個函數(shù)對5.2.1小節(jié)定義的計算前向傳播結(jié)果做了改進(jìn),就不需要將所有變量都作為參數(shù)傳遞到不同函數(shù)中了。
import tensorflow as tf def inference(input_tensor, reuse=False):# 定義第一層神經(jīng)網(wǎng)絡(luò)的變量和前向傳播的過程with tf.variable_scope('layer', reuse=reuse):# 根據(jù)傳進(jìn)來的reuse來判斷是創(chuàng)建新變量還是使用已經(jīng)創(chuàng)建好的,# 第一次構(gòu)造網(wǎng)絡(luò)時需要創(chuàng)建新的變量,# 之后每次調(diào)用該函數(shù)都直接使用reuse=True就不需要每次將變量傳進(jìn)來了weights = tf.get_variable("weights", [INPUT_NODE, LAYER1_NODE],initializer=tf.truncated_normal_initializer(stddev=0.1))biases = tf.get_variable("biases", [LAYER1_NODE],initializer=tf.constant_initializer(0.0))layer1 = tf.nn.relu(tf.matmul(input_tensor, weights) + biases)# 類似的定義第二層神經(jīng)網(wǎng)絡(luò)的變量和前向傳播過程with tf.variable_scope('layer2', reuse=reuse):weights = tf.get_variable("weights", [LAYER1_NODE, OUTPUT_NODE],initializer=tf.truncated_normal_initializer(stddev=0.1))biases = tf.get_variable("biases", [OUTPUT_NODE],initializer=tf.constant_initializer(0.0))layer2 = tf.matmul(layer1, weights) + biases# 返回最后的前向傳播結(jié)果return layer2x = tf.placeholder(tf.float32, [None, INPUT_NODE], name='x-input') y = inference(x)# 在程序中如果需要使用訓(xùn)練好的神經(jīng)網(wǎng)絡(luò)進(jìn)行推導(dǎo)時,可以直接調(diào)用inference(new_x,True) new_x = ... new_y = inference(new_x, True)5.4 TensorFlow模型持久化
為了將訓(xùn)練得到的模型保存下來方便下次使用,即結(jié)果可以復(fù)用,需要將神經(jīng)網(wǎng)絡(luò)模型持久化。
5.4.1 持久化代碼實現(xiàn)
TensorFlow提供了一個非常簡單的API來保存和還原神經(jīng)網(wǎng)絡(luò)模型,該API就是tf.train.Saver類。
1. ckpt文件的保存
import tensorflow as tf # 聲明兩個變量,并計算其和 v1=tf.Variable(tf.constant(1.0,shape=[1]),name="v1") v2=tf.Variable(tf.constant(2.0,shape=[1]),name="v2")init_op=tf.global_variables_initializer() #聲明tf.train.Saver類用于保存模型 saver=tf.train.Saver()with tf.Session() as sess:sess.run(init_op)#將模型保存到文件saver.save(sess,"E:\pycharm\TensorFlow chap5\model.ckpt")Tensorflow模型一般會存在后綴為.ckpt文件中,雖然上面的程序只指定了一個文件路徑,但是在這個文件目錄下會出現(xiàn)三個文件,這是因為Tensorflow會將計算圖的結(jié)構(gòu)和涂上的參數(shù)取值分來保存。
2. 加載已經(jīng)保存的TensorFlow模型
# 2. 加載已經(jīng)創(chuàng)建的模型 import tensorflow as tf# 使用和保存模型代碼中一樣的方式來聲明變量 v1 = tf.Variable(tf.constant(1.0, shape=[1]), name="v1") v2 = tf.Variable(tf.constant(2.0, shape=[1]), name="v2") result = v1 + v2saver = tf.train.Saver()with tf.Session() as sess:# 加載已經(jīng)保存的模型,并通過已經(jīng)保存的模型中的變量的值來計算加法saver.restore(sess, "E:\pycharm\TensorFlow chap5\model\model.ckpt")輸出:[ 3.]加載模型的代碼中,沒有運(yùn)行變量的初始化過程,而是將變量的值通過已經(jīng)保存的模型加載進(jìn)來
- 如果不希望重復(fù)定義圖上的運(yùn)算,也可以直接加載已經(jīng)持久化的圖
如何加載部分變量
上面給出的程序中,默認(rèn)保存和加載了Tensorflow計算圖上定義的全部變量。但有時候可能只需要保存或者加載部分變量,比如,可能有一個之前訓(xùn)練好的五層神經(jīng)網(wǎng)絡(luò)模型,但現(xiàn)在想嘗試一個六層的神經(jīng)網(wǎng)絡(luò),那么可以將前面五層神經(jīng)網(wǎng)絡(luò)中的參數(shù)直接加載到新的模型,而僅僅將最后一層神經(jīng)網(wǎng)絡(luò)重新訓(xùn)練。為了保存或者加載部分變量,在聲明tf.train.Saver類時可以提供一個列表來指定需要保存或者加載的變量。比如在加載模型的代碼中使用saver=tf.train.Saver([v1])命令來構(gòu)建tf.train.Saver類,那么只有變量v1會被加載進(jìn)來,如果運(yùn)行修改后之家在v1的代碼會得到變量未初始化的錯誤:tensorflow.python.framework.errors.FailedPreconditionError:Attempting to use uninitialized value v2
因為v2沒有被加載,所以v2在運(yùn)行初始化之前是沒有值的。除了可以選取需要被加載的變量,tf.train.Saver類也支持在保存或者加載時給變量重命名。
下面給出一個簡單的程序來說明重命名時如何被調(diào)用的
在這個程序中,對變量v1和v2的名稱進(jìn)行了修改,如果直接通過tf.train.Saver默認(rèn)的構(gòu)造函數(shù)來加載保存的模型,那么程序會報變量找不到的錯誤,因為保存時候變量的名稱和加載時變量的名稱不一致。為了解決這個問題,Tensorflow可以通過字典(dictionary)將模型保存時的變量名和需要加載的變量聯(lián)系起來。這樣做主要目的之一時方便使用變量的滑動平均值,在Tensorflow中,每一個變量的滑動平均值是通過影子變量維護(hù)的,所以要獲取變量的滑動平均值實際上就是獲取這個影子變量的取值。如果在加載模型時直接將影子變量映射到變量自身,那么在使用訓(xùn)練好的模型時就不需要再調(diào)用函數(shù)來獲取變量的滑動平均值了。下面的代碼給出了一個保存滑動平均模型的樣例:
# 《TensorFlow實戰(zhàn)Google深度學(xué)習(xí)框架》05 minist數(shù)字識別問題 # win10 Tensorflow1.0.1 python3.5.3 # CUDA v8.0 cudnn-8.0-windows10-x64-v5.1 # filename:ts05.10.py # 滑動平均類的保存import tensorflow as tf# 1. 使用滑動平均 v = tf.Variable(0, dtype=tf.float32, name="v") for variables in tf.global_variables():print(variables.name) ''' v:0 ''' ema = tf.train.ExponentialMovingAverage(0.99) maintain_averages_op = ema.apply(tf.global_variables()) for variables in tf.global_variables():print(variables.name) ''' v:0 v/ExponentialMovingAverage:0 ''' # 2. 保存滑動平均模型 saver = tf.train.Saver() with tf.Session() as sess:init_op = tf.global_variables_initializer()sess.run(init_op)sess.run(tf.assign(v, 10))sess.run(maintain_averages_op)# 保存的時候會將v:0 v/ExponentialMovingAverage:0這兩個變量都存下來。saver.save(sess, "Saved_model/model2.ckpt")print(sess.run([v, ema.average(v)])) ''' [10.0, 0.099999905] ''' # 3. 加載滑動平均模型 v = tf.Variable(0, dtype=tf.float32, name="v")# 通過變量重命名將原來變量v的滑動平均值直接賦值給v。 saver = tf.train.Saver({"v/ExponentialMovingAverage": v}) with tf.Session() as sess:saver.restore(sess, "Saved_model/model2.ckpt")print(sess.run(v))# 輸出:0.0999999使用tf.train.Saver會保存運(yùn)行Tensorflow程序所需要的全部信息,然后有時并不需要某些信息。比如在測試或者離線預(yù)測時,只需要知道如何從神經(jīng)網(wǎng)絡(luò)的輸入層經(jīng)過前向傳播計算得到輸出層即可,而不需要類似于變量初始化,模型保存等輔助節(jié)點的信息。而且,將變量取值和計算圖結(jié)構(gòu)分成不同的文件存儲有時候也不方便,于是Tensorflow提供了convert_variables_to_constants函數(shù),通過這個函數(shù)可以將計算圖中的變量及其取值通過常量的方式保存,這樣整個Tensorflow計算圖可以統(tǒng)一存放在一個文件中。如下:
通過下面的程序可以直接計算定義的加法運(yùn)算的結(jié)果,當(dāng)只需要得到計算圖中某個節(jié)點的取值時,該方法更為簡便。
import tensorflow as tffrom tensorflow.python.platform import gfilewith tf.Session() as sess:model_filename = "/path/to/model/combined_model.pb"#讀取保存的模型文件,并將文件解析成對應(yīng)的GraphDef Protocol Bufferwith gfile.FastGFile(model_filename,'rb') as f:graph_def = tf.GraphDef()graph_def.ParseFromString(f.read())#將graph_def中保存的圖加載到當(dāng)前的圖中.return_elements=["add:0"]給出了返回的張量的名稱。#在保存能的時候給出的時計算節(jié)點的名稱,所以為"add",在加載的時候給出的是張量的名稱,所以時add:0result = tf.import_graph_def(graph_def,return_elements=["add:0"])print(sess.run(result))5.4.2 持久化原理及數(shù)據(jù)格式
- Tensorflow是一個通過圖的形式來表達(dá)計算的編程系統(tǒng),Tensorflow程序中的所有計算都會表達(dá)為計算圖上的節(jié)點。
- Tensorflow通過元圖(MetGraph)來記錄計算圖中節(jié)點的信息以及運(yùn)行計算圖中節(jié)點所需要的元數(shù)據(jù)。
- Tensorflow中元圖是由MetaGraphDef Protocol BUffer定義的,MetaGraphDef中的內(nèi)容就構(gòu)成了Tensorflow持久化時的第一個文件。
元圖(MetGraph)主要記錄5類信息
保存MetGraph信息的文件默認(rèn)以.meta為后綴名,是一個二進(jìn)制文件,無法直接查看,TensorFlow提供export_meta_graph函數(shù)來以json格式導(dǎo)出MetaGraphDef Protocol BUffer。
- 下面分別介紹元圖存儲的信息
- meta_info_def 屬性:記錄了計算圖中的元數(shù)據(jù)(計算圖版本號、標(biāo)簽等)及程序中所有用到的運(yùn)算方法信息。
- graph_def 屬性:記錄了計算圖上的節(jié)點信息,因為在meta_info_def屬性已經(jīng)包含了所有運(yùn)算的信息,所以graph_def只關(guān)注運(yùn)算的連接結(jié)構(gòu)。
- saver_def 屬性:記錄了持久化模型時需要使用的一些參數(shù),如保存到文件的文件名、保存操作和加載操作的名稱,以及保存頻率等。
- collection_def 屬性:計算圖中維護(hù)集合的底層實現(xiàn),該屬性是一個從集合名稱到集合內(nèi)容的映射。
5.5 最佳實踐樣例程序
1. 定義神經(jīng)網(wǎng)絡(luò)的前向傳播過程
# 《TensorFlow實戰(zhàn)Google深度學(xué)習(xí)框架》05 minist數(shù)字識別問題 # win10 Tensorflow1.0.1 python3.5.3 # CUDA v8.0 cudnn-8.0-windows10-x64-v5.1 # filename:mnist_inference.py # 定義神經(jīng)網(wǎng)絡(luò)的前向傳播過程import tensorflow as tf# 1. 定義神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)相關(guān)的參數(shù) INPUT_NODE = 784 OUTPUT_NODE = 10 LAYER1_NODE = 500# 2. 通過tf.get_variable函數(shù)來獲取變量 def get_weight_variable(shape, regularizer):weights = tf.get_variable("weights", shape, initializer=tf.truncated_normal_initializer(stddev=0.1))if regularizer != None:tf.add_to_collection('losses', regularizer(weights))return weights# 3. 定義神經(jīng)網(wǎng)絡(luò)的前向傳播過程 def inference(input_tensor, regularizer):with tf.variable_scope('layer1'):weights = get_weight_variable([INPUT_NODE, LAYER1_NODE], regularizer)biases = tf.get_variable("biases", [LAYER1_NODE], initializer=tf.constant_initializer(0.0))layer1 = tf.nn.relu(tf.matmul(input_tensor, weights) + biases)with tf.variable_scope('layer2'):weights = get_weight_variable([LAYER1_NODE, OUTPUT_NODE], regularizer)biases = tf.get_variable("biases", [OUTPUT_NODE], initializer=tf.constant_initializer(0.0))layer2 = tf.matmul(layer1, weights) + biasesreturn layer22. 訓(xùn)練程序
# 《TensorFlow實戰(zhàn)Google深度學(xué)習(xí)框架》05 minist數(shù)字識別問題 # win10 Tensorflow1.0.1 python3.5.3 # CUDA v8.0 cudnn-8.0-windows10-x64-v5.1 # filename:mnist_train.py # 訓(xùn)練程序import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import mnist_inference import os# 1. 定義神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)相關(guān)的參數(shù) BATCH_SIZE = 100 LEARNING_RATE_BASE = 0.8 LEARNING_RATE_DECAY = 0.99 REGULARIZATION_RATE = 0.0001 TRAINING_STEPS = 30000 MOVING_AVERAGE_DECAY = 0.99 MODEL_SAVE_PATH = "MNIST_model/" # 在當(dāng)前目錄下存在MNIST_model子文件夾 MODEL_NAME = "mnist_model"# 2. 定義訓(xùn)練過程 def train(mnist):# 定義輸入輸出placeholder。x = tf.placeholder(tf.float32, [None, mnist_inference.INPUT_NODE], name='x-input')y_ = tf.placeholder(tf.float32, [None, mnist_inference.OUTPUT_NODE], name='y-input')regularizer = tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)y = mnist_inference.inference(x, regularizer)global_step = tf.Variable(0, trainable=False)# 定義損失函數(shù)、學(xué)習(xí)率、滑動平均操作以及訓(xùn)練過程。variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)variables_averages_op = variable_averages.apply(tf.trainable_variables())cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))cross_entropy_mean = tf.reduce_mean(cross_entropy)loss = cross_entropy_mean + tf.add_n(tf.get_collection('losses'))learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE,global_step,mnist.train.num_examples / BATCH_SIZE, LEARNING_RATE_DECAY,staircase=True)train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)with tf.control_dependencies([train_step, variables_averages_op]):train_op = tf.no_op(name='train')# 初始化TensorFlow持久化類。saver = tf.train.Saver()with tf.Session() as sess:tf.global_variables_initializer().run()for i in range(TRAINING_STEPS):xs, ys = mnist.train.next_batch(BATCH_SIZE)_, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: xs, y_: ys})if i % 1000 == 0:print("After %d training step(s), loss on training batch is %g." % (step, loss_value))saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=global_step)# 3. 主程序入口 def main(argv=None):mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)train(mnist)if __name__ == '__main__':tf.app.run()輸出:
Extracting MNIST_data/train-images-idx3-ubyte.gz Extracting MNIST_data/train-labels-idx1-ubyte.gz Extracting MNIST_data/t10k-images-idx3-ubyte.gz Extracting MNIST_data/t10k-labels-idx1-ubyte.gzAfter 1 training step(s), loss on training batch is 3.4301. After 1001 training step(s), loss on training batch is 0.245217. After 2001 training step(s), loss on training batch is 0.177494. After 3001 training step(s), loss on training batch is 0.137083. After 4001 training step(s), loss on training batch is 0.123793. After 5001 training step(s), loss on training batch is 0.102773. After 6001 training step(s), loss on training batch is 0.0973897. After 7001 training step(s), loss on training batch is 0.0889735. ...3. 代碼
# 《TensorFlow實戰(zhàn)Google深度學(xué)習(xí)框架》05 minist數(shù)字識別問題 # win10 Tensorflow1.0.1 python3.5.3 # CUDA v8.0 cudnn-8.0-windows10-x64-v5.1 # filename:mnist_eval.py # 測試程序 import time import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import mnist_inference import mnist_train# 1. 每10秒加載一次最新的模型 # 加載的時間間隔。 EVAL_INTERVAL_SECS = 10def evaluate(mnist):with tf.Graph().as_default() as g:x = tf.placeholder(tf.float32, [None, mnist_inference.INPUT_NODE], name='x-input')y_ = tf.placeholder(tf.float32, [None, mnist_inference.OUTPUT_NODE], name='y-input')validate_feed = {x: mnist.validation.images, y_: mnist.validation.labels}y = mnist_inference.inference(x, None)correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))variable_averages = tf.train.ExponentialMovingAverage(mnist_train.MOVING_AVERAGE_DECAY)variables_to_restore = variable_averages.variables_to_restore()saver = tf.train.Saver(variables_to_restore)while True:with tf.Session() as sess:ckpt = tf.train.get_checkpoint_state(mnist_train.MODEL_SAVE_PATH)if ckpt and ckpt.model_checkpoint_path:saver.restore(sess, ckpt.model_checkpoint_path)global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]accuracy_score = sess.run(accuracy, feed_dict=validate_feed)print("After %s training step(s), validation accuracy = %g" % (global_step, accuracy_score))else:print('No checkpoint file found')returntime.sleep(EVAL_INTERVAL_SECS)# 主程序 def main(argv=None):mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)evaluate(mnist)if __name__ == '__main__':tf.app.run()5.6 補(bǔ)充
5.6.1 單層神經(jīng)網(wǎng)絡(luò)
MNIST數(shù)據(jù)集,圖像大小為28x28,將其進(jìn)行分類的最簡單的方法就是使用784個像素作為單層神經(jīng)網(wǎng)絡(luò)的輸入。
神經(jīng)網(wǎng)絡(luò)中的每個神經(jīng)元對其所有的輸入進(jìn)行加權(quán)求和,并添加一個被稱為偏置的常數(shù),之后通過一些非線性激活函數(shù)來反饋結(jié)果。
為了將數(shù)字分為10類,我們設(shè)計了一個具有10個輸出神經(jīng)元的單層神經(jīng)網(wǎng)絡(luò),對于分類問題,常用的激活函數(shù)是softmax函數(shù),該函數(shù)通過取每個元素的指數(shù),然后歸一化向量,從而將softmax應(yīng)用于向量。
softmax(Ln)=eLn||eL||softmax(Ln)=eLn||eL||
其中,LnLn為所有權(quán)重的和+偏置
softmax名稱的來源:
指數(shù)是驟增的函數(shù),這將加大向量中每個元素的差異,也會迅速的產(chǎn)生一個巨大的值,然后當(dāng)進(jìn)行向量標(biāo)準(zhǔn)化時,支配范數(shù)(norm)的最大的元素將會被標(biāo)準(zhǔn)化為一個接近于1的數(shù)字,其他的元素將會被一個較大的值分割并標(biāo)準(zhǔn)化為一個接近于0的數(shù)字,所得到的向量清楚的顯示了哪個是其最大值,即max,但是卻又保留了其值的原始的相對排列順序,因此即為soft
假設(shè)我們有一個數(shù)組,V,Vi表示V中的第i個元素,那么這個元素的Softmax值就是
也就是說,是該元素的指數(shù),與所有元素指數(shù)和的比值
這個定義可以說非常的直觀,當(dāng)然除了直觀樸素好理解以外,它還有更多的優(yōu)點,比如可以計算樣本和標(biāo)注之間的差距,并且計算上非常方便。
假設(shè)輸入樣本為3,-1,3,則softmax直觀來說就是將輸入映射為(0,1)的值,且這些值的累加和為1(滿足概率性質(zhì)),那么我們就可以將其理解為概率,在最后選擇輸出的時候,就可以選擇概率最大(也就是值對應(yīng)最大的)結(jié)點作為預(yù)測目標(biāo)。
使用矩陣乘法進(jìn)行前向傳播:
我們現(xiàn)在將使用矩陣乘法將這個單層的神經(jīng)元的行為總結(jié)進(jìn)一個簡單的公式當(dāng)中。直接這樣做:將包含100 個圖像的「mini-batch」作為輸入,產(chǎn)生 100 個預(yù)測(10 元素向量)作為輸出。
權(quán)值矩陣是784x10的大小,784對應(yīng)784個像素,10對應(yīng)10個神經(jīng)元的輸出。
第一個神經(jīng)元對應(yīng)的是圖像和第一列權(quán)值相乘之和,第二個神經(jīng)元是圖像和第二列權(quán)值相乘之和,以此類推,并且每個神經(jīng)元都要添加一個偏置bias,
5.6.2 梯度下降
神經(jīng)網(wǎng)絡(luò)從輸入圖像中產(chǎn)生預(yù)測,但是我們需要知道預(yù)測結(jié)果和真實值之間的差距,任何一種定義的距離都可以這樣操作,但是對于分類問題,一般使用交叉熵距離來度量:
crossentropy=?∑Y′i?log(Yi)crossentropy=?∑Yi′?log(Yi)
其中,Y′iYi′是真實值,YiYi是
獨熱碼(one-hot):編碼意味著你使用一個 10 個值的向量,其中除了第 6 個值為 1 以外的所有值都是 0。這非常方便,因為這樣的格式和我們神經(jīng)網(wǎng)絡(luò)預(yù)測輸出的格式非常相似,同時它也作為一個 10 值的向量。
訓(xùn)練:使用訓(xùn)練圖像和標(biāo)簽來調(diào)整權(quán)值和偏置,以使交叉熵?fù)p失函數(shù)最小。
梯度的數(shù)學(xué)意義在于它指向「上(up)」。因為我們想要到達(dá)一個交叉熵低的地方,那么我們就去向相反的方向。我們用一小部分的梯度更新權(quán)重和偏置并且使用下一批訓(xùn)練圖像再次做同樣的事情。我們希望的是,這可以使我們到達(dá)交叉熵最小的凹點的低部。
交叉熵是一個關(guān)于權(quán)重、偏置、訓(xùn)練圖像的像素和其已知標(biāo)簽的函數(shù)。
如果我們相對于所有的權(quán)重和所有的偏置計算交叉熵的偏導(dǎo)數(shù),我們就得到一個對于給定圖像、標(biāo)簽和當(dāng)前權(quán)重和偏置的「梯度」。請記住,我們有 7850 個權(quán)重和偏置,所以計算梯度需要大量的工作。
梯度下降算法遵循著一個最陡的坡度下降到局部最小值的路徑。訓(xùn)練圖像在每一次迭代中同樣會被改變,這使得我們向著一個適用于所有圖像的局部最小值收斂。
學(xué)習(xí)率:在整個梯度的長度上,你不能在每一次迭代的時候都對權(quán)重和偏置進(jìn)行更新。這就會像是你穿著七里靴卻試圖到達(dá)一個山谷的底部。你會直接從山谷的一邊到達(dá)另一邊。為了到達(dá)底部,你需要一些更小的步伐,即只使用梯度的一部分,通常在 1/1000 區(qū)域中。我們稱這個部分為「學(xué)習(xí)率(Learning rate)」。
神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)過程:
初始化偏置和權(quán)值→→定義損失函數(shù)→→梯度下降法更新參數(shù)→→使用下一個mini-batch優(yōu)化參數(shù)
為什么使用mini-batch:
當(dāng)只用一個圖像來進(jìn)行參數(shù)更新的過程叫做隨機(jī)梯度下降,在 100 個樣本上都這樣做可以得到一個更好地表示由不同樣本圖像施加約束的梯度并且可能更快地朝著解決方案收斂。mini-batch 的大小是可調(diào)整的參數(shù)。還有一個更加技術(shù)化的原因:使用批處理也意味著使用較大的矩陣,而這些通常更容易在 GPU 上優(yōu)化。
增加層
為了提高識別的準(zhǔn)確度,可以將神經(jīng)網(wǎng)絡(luò)增加更多的層,第二層神經(jīng)元將計算前一層神經(jīng)元輸出的加權(quán)和,而非計算像素的加權(quán)和,下面是5層全連接的神經(jīng)網(wǎng)絡(luò):
最后一層的激活函數(shù)仍然使用softmax,中間層使用sigmoid函數(shù)。
隨著層數(shù)的增加,神經(jīng)網(wǎng)絡(luò)的收斂越來越難,因為梯度消失,如何來改進(jìn)呢?
——修正線性單元ReLU激活函數(shù)
sigmoid函數(shù)的問題:
該函數(shù)將所有的值都?xì)w到了(0,1)之間,是飽和函數(shù),當(dāng)層數(shù)越來越多的時候,神經(jīng)元的輸入和梯度已經(jīng)基本歸零了,因為變化非常小。出于歷史原因,一些現(xiàn)代神經(jīng)網(wǎng)絡(luò)使用了 ReLU(修正線性單元)。
升級:
① 用ReLU替換之后,收斂更快準(zhǔn)確度更高。
② 將你的 tf.train.GradientDescentOptimiser 替換為 tf.train.AdamOptimizer。
隨機(jī)初始化:
如果準(zhǔn)確性一直卡在0.1,可以看看有沒有將權(quán)值初始化為隨機(jī)值了,對于偏置值,如何使用ReLU的話,最好的辦法就是將它們都初始化為小的正值,這樣神經(jīng)元一開始就會工作在ReLU的非零區(qū)域內(nèi)。
W = tf.Variable(tf.truncated_normal([K, L] ,stddev=0.1))B = tf.Variable(tf.ones([L])/10)③ 不定值NaN
如果準(zhǔn)確率曲線陡然下滑,并輸出的交叉熵為NaN,則是正在計算log(0),而這個值正是NaN,
5.6.3 學(xué)習(xí)速率衰減
通過四五個中間層之后,準(zhǔn)確度可以提升至98%,但是當(dāng)?shù)螖?shù)5000以上的時候,你會發(fā)現(xiàn)結(jié)果并非如此,而是跳動很大的曲線,也就是在全百分比范圍內(nèi)跳動,這意味著學(xué)習(xí)率太大了,一個好的解決方案是開始很快隨后將學(xué)習(xí)速率指數(shù)級衰減至很小,比如0.0001。
5.6.4 過擬合和dropout
在數(shù)千次迭代之后,測試和訓(xùn)練數(shù)據(jù)的交叉熵曲線開始不相連。學(xué)習(xí)算法只是在訓(xùn)練數(shù)據(jù)上做工作并相應(yīng)地優(yōu)化訓(xùn)練的交叉熵。它再也看不到測試數(shù)據(jù)了,所以這一點也不奇怪:過了一會兒它的工作不再對測試交叉熵產(chǎn)生任何影響,交叉熵停止了下降,有時甚至反彈回來。
它不會立刻影響你模型對于真實世界的識別能力,但是它會使你運(yùn)行的眾多迭代毫無用處,而且這基本上是一個信號——告訴我們訓(xùn)練已經(jīng)不能再為模型提供進(jìn)一步改進(jìn)了。這種無法連接通常會被標(biāo)明「過擬合(overfitting)」,而且當(dāng)你看到這個的時候,你可以嘗試采用一種規(guī)范化(regularization)技術(shù),稱之為「dropout」。
在 dropout 里,在每一次訓(xùn)練迭代的時候,你可以從網(wǎng)絡(luò)中隨機(jī)地放棄一些神經(jīng)元。你可以選擇一個使神經(jīng)元繼續(xù)保留的概率 pkeep,通常是 50% 到 75% 之間,然后在每一次訓(xùn)練的迭代時,隨機(jī)地把一些神經(jīng)元連同它們的權(quán)重和偏置一起去掉。在一次迭代里,不同的神經(jīng)元可以被一起去掉(而且你也同樣需要等比例地促進(jìn)剩余神經(jīng)元的輸出,以確保下一層的激活不會移動)。當(dāng)測試你神經(jīng)網(wǎng)絡(luò)性能的時候,你再把所有的神經(jīng)元都裝回來 (pkeep=1)。
TensorFlow 提供一個 dropout 函數(shù)可以用在一層神經(jīng)網(wǎng)絡(luò)的輸出上。它隨機(jī)地清零一些輸出并且把剩下的提升 1/pkeep。
總結(jié)
以上是生活随笔為你收集整理的TensorFlow:实战Google深度学习框架(四)MNIST数据集识别问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原来中国科幻的背后是中国制造:《流浪地球
- 下一篇: 梳理百年深度学习发展史-七月在线机器学习