深度学习进阶:多分类与TensorFlow
學(xué)習(xí)目標(biāo)
- 目標(biāo) - 知道softmax回歸的原理
- 應(yīng)用softmax_cross_entropy_with_logits實現(xiàn)softamx以及交叉熵損失計算
- 應(yīng)用matmul實現(xiàn)多隱層神經(jīng)網(wǎng)絡(luò)的計算
 
- 應(yīng)用 - 應(yīng)用TensorFlow完成Mnist手寫數(shù)字勢識別
 
到目前為止,我們所接觸的都是二分類問題,神經(jīng)網(wǎng)絡(luò)輸出層只有一個神經(jīng)元,表示預(yù)測輸出\hat{y}?y?^??是正類的概率{P}(y=1|x), \hat{y} > {0.5}P(y=1∣x),?y?^??>0.5則判斷為正類,反之判斷為負類。那么對于多分類問題怎么辦?
2.1.1 Softmax 回歸
對于多分類問題,用 N表示種類個數(shù),那么神經(jīng)網(wǎng)絡(luò)的輸出層的神經(jīng)元個數(shù)必須為L[output]=N, 每個神經(jīng)元的輸出依次對應(yīng)屬于N個類別當(dāng)中某個具體類別的概率,即?P(y=N_1|x),..,P(y=N_n|x)P(y=N?1??∣x),..,P(y=N?n??∣x)。
輸出層即:
Z^{[L]} = W^{[L]}a^{[L-1]} + b^{[L]}Z?[L]??=W?[L]??a?[L?1]??+b?[L]??,Z的輸出值個數(shù)為類別個數(shù)
需要對所有的輸出結(jié)果進行一下softmax公式計算:
a^{[L]}_i = \frac{e^{Z^{[L]}_i}}{\sum^C_{i=1}e^{Z^{[L]}_i}}a?i?[L]??=?∑?i=1?C??e?Z?i?[L]??????e?Z?i?[L]??????,并且滿足\sum^C_{i=1}a^{[L]}_i = 1∑?i=1?C??a?i?[L]??=1,我們來看一下計算案例:
?
2.1.2 交叉熵損失
對于softmax回歸(邏輯回歸代價函數(shù)的推廣,都可稱之為交叉熵損失),它的代價函數(shù)公式為:
L(\hat y, y) = -\sum^C_{j=1}y_jlog\hat y_jL(?y?^??,y)=?∑?j=1?C??y?j??log?y?^???j??
總損失函數(shù)可以記為J = \frac{1}{m}\sum^m_{i=1}L(\hat y, y)J=?m??1??∑?i=1?m??L(?y?^??,y)
邏輯回歸的損失也可以這樣表示,:
?
所以與softmax是一樣的,一個二分類一個多分類衡量。
對于真實值會進行一個one-hot編碼,每一個樣本的所屬類別都會在某個類別位置上標(biāo)記。
?
上圖改樣本的損失值為:
0log(0.10)+0log(0.05)+0log(0.15)+0log(0.10)+0log(0.05)+0log(0.20)+1log(0.10)+0log(0.05)+0log(0.10)+0log(0.10)0log(0.10)+0log(0.05)+0log(0.15)+0log(0.10)+0log(0.05)+0log(0.20)+1log(0.10)+0log(0.05)+0log(0.10)+0log(0.10)
注:關(guān)于one_hot編碼
?
框架使用
-  便于編程:包括神經(jīng)網(wǎng)絡(luò)的開發(fā)和迭代、配置產(chǎn)品; 
-  運行速度:特別是訓(xùn)練大型數(shù)據(jù)集時; 
目前最火的深度學(xué)習(xí)框架大概是 Tensorflow 了。Tensorflow 框架內(nèi)可以直接調(diào)用梯度下降算法,極大地降低了編程人員的工作量。例如以下代碼:
2.1.3 案例:Mnist手寫數(shù)字識別神經(jīng)網(wǎng)絡(luò)實現(xiàn)
2.1.3.1 數(shù)據(jù)集介紹
?
文件說明:
- train-images-idx3-ubyte.gz: training set images (9912422 bytes)
- train-labels-idx1-ubyte.gz: training set labels (28881 bytes)
- t10k-images-idx3-ubyte.gz: test set images (1648877 bytes)
- t10k-labels-idx1-ubyte.gz: test set labels (4542 bytes)
網(wǎng)址:http://yann.lecun.com/exdb/mnist/
2.1.3.2 特征值
?
?
?
2.1.3.3 目標(biāo)值
?
?
2.1.3.4 Mnist數(shù)據(jù)獲取API
TensorFlow框架自帶了獲取這個數(shù)據(jù)集的接口,所以不需要自行讀取。
- from tensorflow.examples.tutorials.mnist import input_data - mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True) - mnist.train.next_batch(100)(提供批量獲取功能)
- mnist.train.images、labels
- mnist.test.images、labels
 
 
- mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True) 
2.1.3.5 網(wǎng)絡(luò)設(shè)計
我們采取兩個層,除了輸入層之外。第一個隱層中64個神經(jīng)元,最后一個輸出層(全連接層)我們必須設(shè)置10個神經(jīng)元的神經(jīng)網(wǎng)絡(luò)。
?
2.1.3.6 全連接層計算
- tf.matmul(a, b,name=None)+bias - return:全連接結(jié)果,供交叉損失運算
 
- tf.train.GradientDescentOptimizer(learning_rate) - 梯度下降
- learning_rate:學(xué)習(xí)率
- method: - minimize(loss):最小優(yōu)化損失
 
 
2.1.3.7 前期確定事情與流程
- 確定網(wǎng)絡(luò)結(jié)構(gòu)以及形狀 - 第一層參數(shù):輸入:x [None, 784] 權(quán)重:[784, 64] 偏置[64],輸出[None, 64]
- 第二層參數(shù):輸入:[None, 64] 權(quán)重:[64, 10] 偏置[10],輸出[None, 10]
 
- 流程: - 獲取數(shù)據(jù)
- 前向傳播:網(wǎng)絡(luò)結(jié)構(gòu)定義
- 損失計算
- 反向傳播:梯度下降優(yōu)化
 
- 功能完善 - 準(zhǔn)確率計算
- 添加Tensorboard觀察變量、損失變化
- 訓(xùn)練模型保存、模型存在加載模型進行預(yù)測
 
2.1.3.8 主網(wǎng)絡(luò)搭建流程
- 獲取數(shù)據(jù)
mnist = input_data.read_data_sets("./data/mnist/input_data/", one_hot=True)
- 定義數(shù)據(jù)占位符,Mnist數(shù)據(jù)實時提供給placeholder
# 1、準(zhǔn)備數(shù)據(jù)
# x [None, 784] y_true [None. 10]
with tf.variable_scope("mnist_data"):x = tf.placeholder(tf.float32, [None, 784])y_true = tf.placeholder(tf.int32, [None, 10])
- 兩層神經(jīng)元網(wǎng)絡(luò)結(jié)果計算
# 2、全連接層神經(jīng)網(wǎng)絡(luò)計算# 類別:10個類別  全連接層:10個神經(jīng)元# 參數(shù)w: [784, 10]   b:[10]# 全連接層神經(jīng)網(wǎng)絡(luò)的計算公式:[None, 784] * [784, 10] + [10] = [None, 10]# 隨機初始化權(quán)重偏置參數(shù),這些是優(yōu)化的參數(shù),必須使用變量op去定義# 要進行全連接層的矩陣運算 [None, 784]*[784, 64] + [64] = [None,64]# [None, 64]*[64, 10] + [10] = [None,10]with tf.variable_scope("fc_model"):# 第一層:隨機初始化權(quán)重和偏置參數(shù),要使用變量OP 定義weight_1 = tf.Variable(tf.random_normal([784, 64], mean=0.0, stddev=1.0),name="weightes_1")bias_1 = tf.Variable(tf.random_normal([64], mean=0.0, stddev=1.0),name='biases_1')# 第二層:隨機初始化權(quán)重和偏置參數(shù),要使用變量OP 定義weight_2 = tf.Variable(tf.random_normal([64, 10], mean=0.0, stddev=1.0),name="weightes_2")bias_2 = tf.Variable(tf.random_normal([10], mean=0.0, stddev=1.0),name='biases_2')# 全連接層運算# 10個神經(jīng)元# y_predict = [None,10]y1 = tf.matmul(x, weight_1) + bias_1y_predict = tf.matmul(y1, weight_2) + bias_2
- 損失計算與優(yōu)化
    # 3、softmax回歸以及交叉熵損失計算with tf.variable_scope("softmax_crossentropy"):# labels:真實值 [None, 10]  one_hot# logits:全臉層的輸出[None,10]# 返回每個樣本的損失組成的列表loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true,logits=y_predict))# 4、梯度下降損失優(yōu)化with tf.variable_scope("optimizer"):# 學(xué)習(xí)率train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
2.1.3.9 完善模型功能
- 1、增加準(zhǔn)確率計算
- 2、增加變量tensorboard顯示
- 3、增加模型保存加載
- 4、增加模型預(yù)測結(jié)果輸出
如何計算準(zhǔn)確率
?
- equal_list = tf.equal(tf.argmax(y, 1), tf.argmax(y_label, 1))
-  accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32)) 
-  模型評估(計算準(zhǔn)確性) 
    # 5、得出每次訓(xùn)練的準(zhǔn)確率(通過真實值和預(yù)測值進行位置比較,每個樣本都比較)with tf.variable_scope("accuracy"):equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1))accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))
?
?
增加變量tensorboard顯示
- 在會話外當(dāng)中增加以下代碼
 # (1)、收集要顯示的變量# 先收集損失和準(zhǔn)確率tf.summary.scalar("losses", loss)tf.summary.scalar("acc", accuracy)# 維度高的張量值tf.summary.histogram("w1", weight_1)tf.summary.histogram("b1", bias_1)# 維度高的張量值tf.summary.histogram("w2", weight_2)tf.summary.histogram("b2", bias_2)# 初始化變量opinit_op = tf.global_variables_initializer()# (2)、合并所有變量opmerged = tf.summary.merge_all()
- 在會話當(dāng)中去創(chuàng)建文件寫入每次的變量值
# (1)創(chuàng)建一個events文件實例
file_writer = tf.summary.FileWriter("./tmp/summary/", graph=sess.graph)# 運行合變量op,寫入事件文件當(dāng)中
summary = sess.run(merged, feed_dict={x: mnist_x, y_true: mnist_y})file_writer.add_summary(summary, i)
增加模型保存加載
創(chuàng)建Saver,然后保存
# 創(chuàng)建模型保存和加載
saver = tf.train.Saver()# 每隔100步保存一次模型
if i % 100 == 0:saver.save(sess, "./tmp/modelckpt/fc_nn_model")
在訓(xùn)練之前加載模型
# 加載模型
if os.path.exists("./tmp/modelckpt/checkpoint"):saver.restore(sess, "./tmp/modelckpt/fc_nn_model")
?
?
增加模型預(yù)測結(jié)果輸出
增加標(biāo)志位
tf.app.flags.DEFINE_integer("is_train", 1, "指定是否是訓(xùn)練模型,還是拿數(shù)據(jù)去預(yù)測")
FLAGS = tf.app.flags.FLAGS
然后判斷是否訓(xùn)練,如果不是訓(xùn)練就直接預(yù)測,利用tf.argmax對樣本的真實目標(biāo)值y_true,和預(yù)測的目標(biāo)值y_predict求出最大值的位置
            # 如果不是訓(xùn)練,我們就去進行預(yù)測測試集數(shù)據(jù)for i in range(100):# 每次拿一個樣本預(yù)測mnist_x, mnist_y = mnist.test.next_batch(1)print("第%d個樣本的真實值為:%d, 模型預(yù)測結(jié)果為:%d" % (i+1,tf.argmax(sess.run(y_true, feed_dict={x: mnist_x, y_true: mnist_y}), 1).eval(),tf.argmax(sess.run(y_predict, feed_dict={x: mnist_x, y_true: mnist_y}), 1).eval()))
?
?
4.7.3.6 完整代碼
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data# 定義一個是否訓(xùn)練、預(yù)測的標(biāo)志
tf.app.flags.DEFINE_integer("is_train", 1, "訓(xùn)練or預(yù)測")FLAGS = tf.app.flags.FLAGSdef full_connected_nn():"""全連接層神經(jīng)網(wǎng)絡(luò)進行Mnist手寫數(shù)字識別訓(xùn)練:return:"""mnist = input_data.read_data_sets("./data/mnist/input_data/", one_hot=True)# 1、獲取數(shù)據(jù),定義特征之和目標(biāo)值張量# xwith tf.variable_scope("data"):# 定義特征值占位符x = tf.placeholder(tf.float32, [None, 784], name="feature")# 定義目標(biāo)值占位符y_true = tf.placeholder(tf.int32, [None, 10], name="label")# 2、根據(jù)識別的類別數(shù),建立全連接層網(wǎng)絡(luò)# 手寫數(shù)字10個類別# 設(shè)計了一層的神經(jīng)網(wǎng)絡(luò),最后一層,10個神經(jīng)元# 確定網(wǎng)絡(luò)的參數(shù)weight [784, 10] bias[10]# 要進行全連接層的矩陣運算 [None, 784]*[784, 64] + [64] = [None,64]# [None, 64]*[64, 10] + [10] = [None,10]with tf.variable_scope("fc_model"):# 第一層:隨機初始化權(quán)重和偏置參數(shù),要使用變量OP 定義weight_1 = tf.Variable(tf.random_normal([784, 64], mean=0.0, stddev=1.0),name="weightes_1")bias_1 = tf.Variable(tf.random_normal([64], mean=0.0, stddev=1.0),name='biases_1')# 第二層:隨機初始化權(quán)重和偏置參數(shù),要使用變量OP 定義weight_2 = tf.Variable(tf.random_normal([64, 10], mean=0.0, stddev=1.0),name="weightes_2")bias_2 = tf.Variable(tf.random_normal([10], mean=0.0, stddev=1.0),name='biases_2')# 全連接層運算# 10個神經(jīng)元# y_predict = [None,10]y1 = tf.matmul(x, weight_1) + bias_1y_predict = tf.matmul(y1, weight_2) + bias_2# 3、根據(jù)輸出結(jié)果與真是結(jié)果建立softmax、交叉熵損失計算with tf.variable_scope("softmax_cross"):# 先進性網(wǎng)絡(luò)輸出的值的概率計算softmax,在進行交叉熵損失計算all_loss = tf.nn.softmax_cross_entropy_with_logits(labels=y_true,logits=y_predict,name="compute_loss")# 求出平均損失loss = tf.reduce_mean(all_loss)# 4、定義梯度下降優(yōu)化器進行優(yōu)化with tf.variable_scope("GD"):train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss)# 5、求出每次訓(xùn)練的準(zhǔn)確率為with tf.variable_scope("accuracy"):# 求出每個樣本是否相等的一個列表equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1))# 計算相等的樣本的比例accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))# 1、收集要在tensorboard觀察的張量值# 數(shù)值型-->scalar 準(zhǔn)確率,損失tf.summary.scalar("loss", loss)tf.summary.scalar("acc", accuracy)# 維度高的張量值tf.summary.histogram("w1", weight_1)tf.summary.histogram("b1", bias_1)# 維度高的張量值tf.summary.histogram("w2", weight_2)tf.summary.histogram("b2", bias_2)# 2、合并變量merged = tf.summary.merge_all()# 1、創(chuàng)建保存模型的OPsaver = tf.train.Saver()# 開啟會話進行訓(xùn)練with tf.Session() as sess:# 初始化變量OPsess.run(tf.global_variables_initializer())# 創(chuàng)建events文件file_writer = tf.summary.FileWriter("./tmp/summary/", graph=sess.graph)# 加載本地模型繼續(xù)訓(xùn)練或者拿來進行預(yù)測測試集# 加載模型,從模型當(dāng)中找出與當(dāng)前訓(xùn)練的模型代碼當(dāng)中(名字一樣的OP操作),覆蓋原來的值ckpt = tf.train.latest_checkpoint("./tmp/model/")# 判斷模型是否存在if ckpt:saver.restore(sess, ckpt)if FLAGS.is_train == 1:# 循環(huán)訓(xùn)練for i in range(2000):# 每批次給50個樣本mnist_x, mnist_y = mnist.train.next_batch(50)_, loss_run, acc_run, summary = sess.run([train_op, loss, accuracy, merged],feed_dict={x: mnist_x, y_true: mnist_y})print("第 %d 步的50個樣本損失為:%f , 準(zhǔn)確率為:%f" % (i, loss_run, acc_run))# 3、寫入運行的結(jié)果到文件當(dāng)中file_writer.add_summary(summary, i)# 每隔100步保存一次模型的參數(shù)if i % 100 == 0:saver.save(sess, "./tmp/model/fc_nn_model")else:# 進行預(yù)測# 預(yù)測100個樣本for i in range(100):# label [1, 10]image, label = mnist.test.next_batch(1)# 直接運行網(wǎng)絡(luò)的輸出預(yù)測結(jié)果print("第 %d 樣本,真實的圖片數(shù)字為:%d, 神經(jīng)網(wǎng)絡(luò)預(yù)測的數(shù)字為:%d " % (i,tf.argmax(label, 1).eval(),tf.argmax(sess.run(y_predict, feed_dict={x: image, y_true: label}), 1).eval()))return Noneif __name__ == '__main__':full_connected_nn()
4.7.4 調(diào)整學(xué)習(xí)率調(diào)整網(wǎng)絡(luò)參數(shù)帶來的問題
如果我們對網(wǎng)絡(luò)當(dāng)中的學(xué)習(xí)率進行修改,也就是一開始我們并不會知道學(xué)習(xí)率填哪些值,也并不知道調(diào)整網(wǎng)絡(luò)的參數(shù)大小帶來的影響(第一部分第四節(jié))。
- 假設(shè)學(xué)習(xí)率調(diào)整到1,2
- 假設(shè)參數(shù)調(diào)整到比較大的值,幾十、幾百
總結(jié):參數(shù)調(diào)整了之后可能沒影響,是因為網(wǎng)絡(luò)較小,可能并不會造成后面所介紹的梯度消失或者梯度爆炸
4.7.5總結(jié)
- 掌握softmax公式以及特點
- tensorflow.examples.tutorials.mnist.input_data 獲取Mnist數(shù)據(jù)
- tf.matmul(a, b,name=None)實現(xiàn)全連接層計算
- tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)實現(xiàn)梯度下降優(yōu)化
總結(jié)
以上是生活随笔為你收集整理的深度学习进阶:多分类与TensorFlow的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 人工智能:深层神经网络
- 下一篇: 在Lumen中引入钉钉SDK
