1.TensorFlow 系統架構:
分為設備層和網絡層、數據操作層、圖計算層、API 層、應用層。其中設備層和網絡層、數據操作層、圖計算層是 TensorFlow 的核心層。
2.TensorFlow 設計理念:
(1)將圖的定義和圖的運行完全分開。TensorFlow 完全采用符號式編程。
符號式計算一般是先定義各種變量,然后建立一個數據流圖,在數據流圖中規定各個變量之間的計算關系,最后需要對數據流圖進行編譯,此時的數據流圖還是一個空殼,里面沒有任何實際數據,只有把需要的輸入放進去后,才能在整個模型中形成數據流,從而形成輸出值。
如下圖所示:定義了一個操作,但實際上並沒有運行。
(2) TensorFlow 中涉及的運算都要放在圖中,而圖的運行只發生在會話(session)中。開啟會話后,就可以用數據去填充節點,進行運算;關閉會話則不能進行計算。會話提供了操作運行和 Tensor 求值的環境。
一個簡單的例子:
3. TensorFlow 各個概念:
(1)邊:TensorFlow 的邊有兩種連接關系:數據依賴(實線表示)和控制依賴(虛線表示)。實現邊表示數據依賴,代表數據,即張量。任意維度的數據統稱為張量。虛線邊稱為控制依賴,可以用於控制操作的運行,這類邊上沒有數據流過,但源節點必須在目的節點開始執行前完成執行。
(2)節點:節點代表一個操作,一般用來表示施加的數學運算。
(3)圖:把操作任務描述成有向無環圖。創建圖使用 tf.constant() 方法:
a = tf.constant([1.0,2.0])
(4)會話:啟動圖的第一步是創建一個 Session 對象。會話提供在圖中執行操作的一些方法。使用 tf.Session() 方法創建對象,調用 Session 對象的 run()方法來執行圖:
with tf.Session() as sess: result = sess.run([product]) print(result)
(5)設備:設備是指一塊可以用來運算並且擁有自己的地址空間的硬件。方法:tf.device()
(6)變量:變量是一種特殊的數據,它在圖中有固定的位置,不向普通張量那樣可以流動。使用 tf.Variable() 構造函數來創建變量,並且該構造函數需要一個初始值,初始值的形狀和類型決定了這個變量的形狀和類型。
#創建一個變量,初始化為標量0
state = tf.Variable(0, name="counter")
(7)內核:內核是能夠運行在特定設備(如 CPU、GPU)上的一種對操作的實現。
4.TensorFlow 批標准化:
批標准化(BN)是為了克服神經網絡層數加深導致難以訓練而誕生的。
方法:批標准化一般用在非線性映射(激活函數)之前,對 x=Wu+b 做規划化,使結果(輸出信號各個維度)的均值為0,方差為1。
用法:在遇到神經網絡收斂速度很慢火梯度爆炸等無法訓練的情況下,都可以嘗試用批標准化來解決。
5.神經元函數:
(1)激活函數:激活函數運行時激活神經網絡中某一部分神經元,將激活信息向后傳入下一層的神經網絡。介紹幾個常用的激活函數。
a.sigmoid 函數。sigmoid 將一個 real value 映射到 (0, 1) 的區間,這樣可以用來做二分類。
使用方法如下:
a = tf.constant([[1.0,2.0], [1.0, 2.0], [1.0, 2.0]]) sess = tf.Session() print(sess.run(tf.sigmoid(a))
b.softmax 函數。softmax把一個 k 維的 real value 向量(a1, a2 a3, a4, ...)映射成一個(b1, b2, b3, b4, ...)其中bi 是一個0-1的常數,然后可以根據 bi 的大小來進行多分類的任務,如取權重最大的一維。
函數表達式:
其輸出的是一個多維向量,不論有多少個分量,其和加都是1,每個向量的分量維度都是一個小於1的值,這也是與 sigmoid 函數的重要區別。
函數圖像:
c.relu 函數。relu 函數可以解決 sigmoid 函數梯度下降慢,消失的問題。
使用方法如下:
a = tf.constant([-1.0, 2.0]) with tf.Session() as sess: b = tf.nn.relu(a) print(sess.run(b))
d.dropout 函數。一個神經元將以概率keep_prob 決定是否被抑制。如果被抑制,該神經元輸出就為0;如果不被抑制,那么該神經元的輸出值將被放大到原來的1/keep_prob 倍。(可以解決過擬合問題)。
使用方法如下:
a = tf.constant([[-1.0, 2.0, 3.0, 4.0]]) with tf.Sessin() as sess: b = tf.nn.dropout(a, 0.5, noise_shape=[1,4]) print(sess.run(b))
(2)卷積函數:卷積函數是構建神經網絡的重要支架,是在一批圖像上掃描的二維過濾器。這里簡單介紹一下卷積函數的幾個方法。
a. 這個函數計算 N 維卷積的和。
tf.nn.convolution(input, filter, padding, strides=None, dilation_rate=None, name=None, data_format=None)
b.這個函數的作用是對一個四維的輸入數據 input 和四維的卷積核 filter 進行操作,然后對輸入數據進行一個二維的卷積操作,最后得到卷積之后的結果。
tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None, name=None)
此外還有 tf.nn.depthwise_conv2d()、tf.nn.separable_conv2d() 等方法,這里不再一一說明。
(3)池化函數:在神經網絡中,池化函數一般跟在卷積函數的下一層池化操作是利用一個矩陣窗口在張量上進行掃描,將每個矩陣窗口中的值通過取最大值或平均值來減少元素個數。每個池化操作的矩陣窗口大小是有 ksize 指定的,並且根據步長 strides 決定移動步長。
a.計算池化區域中元素的平均值。
tf.nn.avg_pool(value, ksize, strides, padding, data_format='NHWC', name=None)
b.計算池化區域中元素的最大值。
tf.nn.max_pool(value, ksize, strides, padding, data_format='NHWC', name=None)
6.模型的存儲於加載
(1)模型存儲主要是建立一個 tf.train.Saver() 來保存變量,通過在 tf.train.Saver 對象上調用 Saver.save() 生成,並且制定保存的位置,一般模型的擴展名為 .ckpt。
saver.save(sess, ckpt_dir + "/model.ckpt", global_step=global_step)
(2)加載模型可以用 saver.resotre 來進行模型的加載。
with tf.Session() as sess: tf.initialize_all_variables().run() ckpt = tf.train.get_checkpoint_state(ckpt_dir) if ckpt and ckpt.model_checkpoint_path: print(ckpt.model_checkpoint_path) saver.restore(sess, ckpt.model_checkpoint_path) #加載所有的參數
PS: 一張圖看懂擬合、過擬合和欠擬合。畫的有點丑就是。。。