TensorFlow Tutorial-1
1、Why TensorFlow?
網上有關介紹太多了,我就不多說了,這裡主要注重使用。
Intro.PNG
github.PNG
2、Programing model
2.1.Big Idea
將數值的計算轉化為圖(computational graph),任何tensorflow的計算都是基於圖的。
2.2 Graph Nodes
圖中的結點是有輸入和輸出的操作(operations),input的數量可以任意,output只有一個。
2.3 Graph Edges
圖的邊是在結點見浮動的張量(tensors),tensors可以理解為n-維數組。
2.4 Advantages
使用flow graphs作為deep learning framework的優點是可以通過簡單少量的operations來構建複雜模型,使梯度的計算容易很多。當你在編寫比較大的模型時,自動微分將會幫助到你。
2.5 Another way to think it
每一個operation可以理解為在某一點可以執行的函數。
2. 6 舉個詳細使用的例子
下面這個圖展示了只有一個隱藏層的神經網路在Tensorflow中的計算,我們以Relu作為激活函數。
Nodes.PNG
ReLu Function.PNG
- W: 待訓練的參數
- X: input
- b: bias
下面將介紹一下上圖中出現的幾個結點:
1、Variables:
W 和 b 參數作為TensorFlow中的Variables,在訓練的過程中你需要調整這些參數,使得你的loss function最小,這些變數是有狀態的結點,在圖中多種的計算結點之間保持他們的狀態,所謂保持狀態就是指它們的值會被存下來,因此想要復原數據很容易,並且可以隨時輸出他們當前的值(current value),這些變數還有一些其他的features,可以在訓練或者訓練結束後持久化到disk中,因此可以允許不同的公司不同的組織去使用這些大型模型訓練好的參數,並且默認進行梯度更新。
W 和 b這些變數也是operations。
2、Placeholders:
是一些在執行的過程中才會被賦值的結點,如果你網路的input 需要依賴一些其他外界的數據。
比如你不想用真實的值來計算。placeholders是你在訓練過程中可以加入數據的地方。對於placeholders,我們不用對其進行任何初始化,我們只定義一個data type,並且賦值一個給定大小的tensor,我們的計算圖就可以知道怎麼去計算,甚至不用存儲任何的數據。
3、Mathematical operations:
用於矩陣的乘法,加法,ReLu函數的計算。
4、廢話少說,上代碼!!!
# 導入tensorflow包
import tensorflow as tf# 創建一個有100個值的vector,作為bias, 默認為0 b=tf.Variable(tf.zeros((100,)))# 創建並出示化權重,一個784*100 的矩陣,矩陣的初始值在-1到1之間 W=tf.Variable(tf.random_uniform((784,100),-1,1))
#為輸入創建一個placeholder,不需要任何數據,只需要定義數據類型為一個32位浮點數,shape 為100*784 x=tf.placeholder(tf.float32,(100,784))# tensorflow mathematical operationsh=tf.nn.relu(tf.matmul(x,W)+b)關於h我想說:和numpy中很像,就是調用了tensorflow mathematical operations,我們沒有真的乘某個數值,而僅僅在圖中創建了一個符號來表示他,所以你不能輸出該值,因為x只是一個placeholder,沒有任何真值。我們現在只為我們的model創建了一個骨架。
5、說好的圖呢 :
看了半天,這不和numpy手擼一樣嗎,其實作為程序員我們只要心裡有著種抽象的概念就好,底層確實是以這種結點來實現的,如果你想看到,可以調用
tf.get_default_graph().get_operations()
你將會看到如下內容:
Absta.PNG
6、怎麼跑這個例子呢?
目前為止,我們已經定義了一個graph,我們需要把這個graph部署到一個session中,一個session可以綁定到一個具體的執行環境中(CPU或者GPU)
接著剛才的代碼,我們在後面補充三行:
import numpy as np
import tensorflow as tf b=tf.Variable(tf.zeros((100,)))W=tf.Variable(tf.random_uniform((784,100),-1,1))x=tf.placeholder(tf.float32,(100,784))h=tf.nn.relu(tf.matmul(x,W)+b)
#創建session對象,初始化相關的參數sess=tf.Session()# initialize b 和 wsess.run(tf.initialize_all_variables()) # 第一個參數是圖中結點的輸出,第二個參數是給placeholder賦的值,是一個map,定義每個結點的具體值 sess.run(h,{x : np.random.random(100,784)})更多的關於Session的使用方法:
#自己創建一個session,不使用默認的session,使用完記得關了
sess=tf.Session()sess=tf.run(train_step)sess.close()
with tf.Session() as sess: #使用這個創建的session計算結果 sess.run(train_step) #不用close,with體幫我們進行資源的回收 #with體使用默認的session sess=tf.Session() with sess.as_default(): print(train_step.eval()) #也是使用默認的session sess=tf.Session()print(train_step.eval(session=sess))
#定義一個可互動式的session,自動將會話註冊為默認會話sess=tf.InteractiveSession()train_step.eval() sess.close() #用自己的參數配置session config=tf.ConfigProto(allow_aoft_placement=True, log_device_placement=True)sess1=tf.InteractiveSession(config=config)sess2=tf.Session(config=config)7、損失函數的創建 :
通過prediction 和 labels 創建loss node
# neural network的最後一步,用softmax做一個邏輯回歸
prediction=tf.nn.softmax(...)label=tf.placeholder(tf.float32,[100,10])# 損失函數,用label乘上logP在列上的值cross_entropy=-tf.reduce_sum(label* tf.log(prediction),axis=1)8、如何計算梯度?:
tf.train.GradientDescentOptimizer創建了一個Optimizer是TensorFlow中定義的一個抽象類,它的每個子類,可以作為一個特定的學習演算法,默認是梯度下降。在我們的圖上面加了一個optimization operation,當我們執行這個train_step方法時(sess.run(train_step,feed_dict={x: batch_x, label: batch_label})),將會應用所有的梯度到模型中的變數中。這是因為minimize函數做了兩件事情,首先是計算cross_entropy的梯度,然後進行梯度更新。
# 梯度下降,learning rate 為0.5,minimize方法的參數是一個需要被梯度下降的結點。
train_step= tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)9、訓練模型
sess=tf.Session()
sess.run(tf.initialize_all_variables()) # 創建一個learning schedule, iterate 1000 次 for i in range(1000): batch_x, batch_label = data.next_batch() sess.run(train_step,feed_dict={x: batch_x, label: batch_label})3、變數共享
當你在使用Tensorflow時,你想在一個地方初始化所有的變數,比如我想多次實例化我的graph或者我想在GPU集群上訓練,我們需要共享變數。有以下兩個解決方案:
其中一個方法是創建一個map,在需要使用的地方調用key獲得value。但缺點是它大破了封裝的思想。
TensorFlow的variable scope解決了這個問題,它為我們提供了一個提供了一個命名空間,避免了衝突。
with tf.variable_scope("hello world"):
v=tf.get_variable("v",shape=[1])# v.name== " hello world/v:0" with tf.variable_scope("hello world" reuse=True): v=tf.get_variable("v",shape=[1]) # 可以找到共享的變數vwith tf.variable_scope("hello world" reuse=False): v=tf.get_variable("v",shape=[1])# CRASH hello world/v:0 已經存在了4、官方demo (Official Demo)
MNIST手寫體識別
4.1 基於softmax邏輯回歸
利用softmax regression,訓練一個手寫體分類:
from __future__ import absolute_import
from __future__ import divisionfrom __future__ import print_function import gzip import os import tempfile import numpy from six.moves import urllibfrom six.moves import xrange # pylint: disable=redefined-builtinimport tensorflow as tf from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_setsfrom tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)# 定義一個placeholder,x = tf.placeholder(tf.float32, [None, 784])W = tf.Variable(tf.zeros([784, 10])) b = tf.Variable(tf.zeros([10])) y = tf.nn.softmax(tf.matmul(x, W) + b)#定義一個用於存儲正確標示的佔位符y_=tf.placeholder("float",[None,10])#交叉熵損失函數cross_entropy=-tf.reduce_sum(y_*tf.log(y))#梯度下降進行訓練 train_step=tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy) init=tf.initialize_all_variables()sess=tf.Session()sess.run(init)
#隨機梯度下降 for i in range(1000): batch_xs, batch_ys=mnist.train.next_batch(100) print(sess.run(train_step,feed_dict={x:batch_xs,y_:batch_ys})) correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(y_,1)) accuracy=tf.reduce_mean(tf.cast(correct_prediction,"float"))print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))4.2 基於CNN神經網路
# 利用CNN,訓練一個手寫體分類
"""Functions for downloading and reading MNIST data.""" from __future__ import absolute_import from __future__ import divisionfrom __future__ import print_function import gzip import os import tempfile import numpy from six.moves import urllibfrom six.moves import xrange # pylint: disable=redefined-builtin import tensorflow as tf from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets from tensorflow.examples.tutorials.mnist import input_data # 將系統默認的session作ionsess = tf.InteractiveSession()mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) # 正確答案y_ = tf.placeholder(float, [None, 10])
# 定義函數用於初始化權值,和biasdef weight_initialize(shape): # 標準差為一,初始化權值 initial = tf.truncated_normal(shape, stddev=0.1) return tf.Variable(initial) def bias_variable(shape): initail = tf.constant(0.1, shape=shape) return tf.Variable(initail) x = tf.placeholder(float, [None, 784])# 卷積 def conv2d(x, W): #tf.nn.conv2d提供了一個非常方便的函數來實現卷積層向前傳播的演算法,這個函數的第一個輸入為 #當前層節點矩陣,這個矩陣是一個四維矩陣,後面的三個維度對應一個節點矩陣,第一個維度對應一個 #輸入batch.比如在輸入層,input[0,:,:,:]表示第一張圖片,input[1,:,:,:]表示第張圖片二,tf.nn.conv2d #第二個參數提供了卷積層的權重,第三個參數為步長,步長第一維,和最後一維固定是1,最後一個參數是填充方法 #SAME表示全0填充,VALID表示不添加 return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding=SAME) # 池化 def max_pool_2x2(x): #ksize提供了過濾器的大小為2*2 return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding=SAME) # 卷積層第一層W_conv1 = weight_initialize([5, 5, 1, 32]) b_conv1 = bias_variable([32]) x_image = tf.reshape(x, [-1, 28, 28, 1])# 卷積層第一層的relu和池化 h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)h_pool1 = max_pool_2x2(h_conv1)# 5*5*32# 卷積層第二層W_conv2 = weight_initialize([5, 5, 32, 64]) b_conv2 = bias_variable([64])# 卷積層第二層的relu和池化 h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) h_pool2 = max_pool_2x2(h_conv2)# 全連接層的weight和biasW_fc1 = weight_initialize([7 * 7 * 64, 1024])b_fc1 = bias_variable([1024])# output層h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1) # 使用dropout防止過擬合# 過擬合概率keep_prob = tf.placeholder("float")h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)# 1024個神經元*10個輸出W_fc2 = weight_initialize([1024, 10])b_fc2 = bias_variable([10])y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2)) # 定義一個損失函數cross_entropy = -tf.reduce_sum(y_ * tf.log(y_conv))train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))accuracy = tf.reduce_mean(tf.cast(correct_prediction,"float"))# 初始化所有變數sess.run(tf.initialize_all_variables()) for i in range(2000): batch = mnist.train.next_batch(50) if i % 100 == 0: train_accuracy = accuracy.eval(feed_dict={ x: batch[0], y_: batch[1], keep_prob: 1.0 }) print("step %d, train accuracy %g" % (i, train_accuracy)) train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: [0.5]}) print("test accuracy %g" % accuracy.eval(feed_dict={ x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))訓練結果如下:
result.png
5、 總結
- TensorFlow 每個結點都對應著梯度操作
- Computational graphy 很容易backwards每一個結點。
- 這些都是自動完成的。
- TensorFlow也把複雜的計算放在python之外完成,但是為了避免前面說的那些開銷,它做了進一步完善。Tensorflow不單獨地運行單一的複雜計算,而是讓我們可以先用圖描述一系列可交互的計算操作,然後全部一起在Python之外運行。
原文鏈接:http://www.jianshu.com/p/9d0936b0d245
推薦閱讀:
※不要慫,就是GAN (生成式對抗網路) (三):判別器和生成器 TensorFlow Model
※機器學習:通過深度神經網路再識評估器
※IOS平台TensorFlow實踐
※TensorFlow會話的配置項
TAG:TensorFlow | tutorial |