01.06 吳恩達深度學習筆記(58)-深度學習框架Tensorflow

TensorFlow

有很多很棒的深度學習編程框架,其中一個是TensorFlow,很期待幫助你開始學習使用TensorFlow,我想在這個筆記中向你展示TensorFlow程序的基本結構,然後讓你自己練習,學習更多細節

先提一個啟發性的問題,假設你有一個損失函數J需要最小化,在本例中,我將使用這個高度簡化的損失函數,Jw=w^2-10w+25,這就是損失函數,也許你已經注意到該函數其實就是(w-5)^2,如果你把這個二次方式子展開就得到了上面的表達式,所以使它最小的w值是5,但假設我們不知道這點,你只有這個函數,我們來看一下怎樣用TensorFlow將其最小化,因為一個非常類似的程序結構可以用來訓練神經網絡。

其中可以有一些複雜的損失函數J(w,b)取決於你的神經網絡的所有參數,然後類似的,你就能用TensorFlow自動找到使損失函數最小的w和b的值。但讓我們先從左邊這個更簡單的例子入手。

吳恩達深度學習筆記(58)-深度學習框架Tensorflow

我在我的Jupyter notebook中運行Python,

import numpy as np
import tensorflow as tf
#導入TensorFlow
w = tf.Variable(0,dtype = tf.float32)
#接下來,讓我們定義參數w,在TensorFlow中,你要用tf.Variable()來定義參數
#然後我們定義損失函數:
cost = tf.add(tf.add(w**2,tf.multiply(- 10.,w)),25)
#然後我們定義損失函數J
#然後我們再寫:
train = tf.train.GradientDescentOptimizer(0.01).minimize(cost)
#(讓我們用0.01的學習率,目標是最小化損失)。
#最後下面的幾行是慣用表達式:
init = tf.global_variables_initializer()
session = tf.Sessions()#這樣就開啟了一個TensorFlow session。
session.run(init)#來初始化全局變量。
#然後讓TensorFlow評估一個變量,我們要用到:
session.run(w)
#上面的這一行將w初始化為0,並定義損失函數,我們定義train為學習算法,它用梯度下降法優化器使損失函數最小化,但實際上我們還沒有運行學習算法,所以#上面的這一行將w初始化為0,並定義損失函數,我們定義train為學習算法,它用梯度下降法優化器使損失函數最小化,但實際上我們還沒有運行學習算法,所以session.run(w)評估了w,讓我::
print(session.run(w))
#所以如果我們運行這個,它評估w等於0,因為我們什麼都還沒運行。

#現在讓我們輸入:
session.run(train),它所做的就是運行一步梯度下降法。
#接下來在運行了一步梯度下降法後,讓我們評估一下w的值,再print:
print(session.run(w))
#在一步梯度下降法之後,w現在是0.1。
吳恩達深度學習筆記(58)-深度學習框架Tensorflow

現在我們運行梯度下降1000次迭代:

吳恩達深度學習筆記(58)-深度學習框架Tensorflow

這是運行了梯度下降的1000次迭代,最後w變成了4.99999,記不記得我們說(w-5)^2最小化,因此w的最優值是5,這個結果已經很接近了

希望這個讓你對TensorFlow程序的大致結構有了瞭解,當你做編程練習,使用更多TensorFlow代碼時,我這裡用到的一些函數你會熟悉起來,這裡有個地方要注意,w是我們想要優化的參數,因此將它稱為

變量,注意我們需要做的就是定義一個損失函數,使用這些add和multiply之類的函數。

TensorFlow知道如何對add和mutiply,還有其它函數求導,這就是為什麼你只需基本實現前向傳播,它能弄明白如何做反向傳播和梯度計算,因為它已經內置在add,multiply和平方函數中。

對了,要是覺得這種寫法不好看的話,TensorFlow其實還重載了一般的加減運算等等,因此你也可以把cost寫成更好看的形式,把之前的cost標成註釋,重新運行,得到了同樣的結果。

吳恩達深度學習筆記(58)-深度學習框架Tensorflow

吳恩達深度學習筆記(58)-深度學習框架Tensorflow

一旦w被稱為TensorFlow變量,平方,乘法和加減運算都重載了,因此你不必使用上面這種不好看的句法。

TensorFlow還有一個特點,我想告訴你,那就是這個例子將w的一個固定函數最小化了。如果你想要最小化的函數是訓練集函數又如何呢?不管你有什麼訓練數據x,當你訓練神經網絡時,訓練數據x會改變,那麼如何把訓練數據加入TensorFlow程序呢?

我會定義x,把它想做扮演訓練數據的角色,事實上訓練數據有x和y,但這個例子中只有x,把x定義為:

x = tf.placeholder(tf.float32,[3,1]),讓它成為[3,1]數組,我要做的就是,因為cost這個二次方程的三項前有固定的係數,它是w^2+10w+25,我們可以把這些數字1,-10和25變成數據,我要做的就是把cost替換成:

cost = x[0][0]*w**2 +x[1][0]*w + x[2][0],

現在x變成了控制這個二次函數係數的數據,這個placeholder函數告訴TensorFlow,你稍後會為x提供數值。

讓我們再定義一個數組,coefficient = np.array([[1.],[-10.],[25.]]),這就是我們要接入x的數據。最後我們需要用某種方式把這個係數數組接入變量x,做到這一點的句法是,在訓練這一步中,要提供給x的數值,我在這裡設置:

feed_dict = {x:coefficients}

我們重新運行它,希望得到和之前一樣的結果。

吳恩達深度學習筆記(58)-深度學習框架Tensorflow

吳恩達深度學習筆記(58)-深度學習框架Tensorflow

現在如果你想改變這個二次函數的係數,假設你把:

coefficient = np.array([[1.],[-10.],[25.]])

改為:

coefficient = np.array([[1.],[-20.],[100.]])

現在這個函數就變成了(w-10)^2,如果我重新運行,希望我得到的使(w-10)^2最小化的w值為10,讓我們看一下,很好,在梯度下降1000次迭代之後,我們得到接近10的w。

吳恩達深度學習筆記(58)-深度學習框架Tensorflow

吳恩達深度學習筆記(58)-深度學習框架Tensorflow

在你做編程練習時,見到更多的是,TensorFlow中的placeholder是一個你之後會賦值的變量,這種方式便於把訓練數據加入損失方程,把數據加入損失方程用的是這個句法,當你運行訓練迭代,用feed_dict來讓x=coefficients。如果你在做mini-batch梯度下降,在每次迭代時,你需要插入不同的mini-batch,那麼每次迭代,你就用feed_dict來喂入訓練集的不同子集,把不同的mini-batch喂入損失函數需要數據的地方。

希望這讓你瞭解了TensorFlow能做什麼,讓它如此強大的是,你只需說明如何計算損失函數,它就能求導,而且用一兩行代碼就能運用梯度優化器,Adam優化器或者其他優化器。

吳恩達深度學習筆記(58)-深度學習框架Tensorflow

這還是剛才的代碼,稍微整理了一下,儘管這些函數或變量看上去有點神秘,但你在做編程練習時多練習幾次就會熟悉起來了。

吳恩達深度學習筆記(58)-深度學習框架Tensorflow

還有最後一點我想提一下,這三行(藍色大括號部分)在TensorFlow裡是符合表達習慣的,有些程序員會用這種形式來替代,作用基本上是一樣的。

但這個with結構也會在很多TensorFlow程序中用到,它的意思基本上和左邊的相同,但是Python中的with命令更方便清理,以防在執行這個內循環時出現錯誤或例外。所以你也會在編程練習中看到這種寫法。那麼這個代碼到底做了什麼呢?讓我們看這個等式:

cost = x[0][0]*w**2 +x[1][0]*w + x[2][0]#(w-5)**2

TensorFlow程序的核心是計算損失函數,然後TensorFlow自動計算出導數,以及如何最小化損失,因此這個等式或者這行代碼所做的就是讓TensorFlow建立計算圖,計算圖所做的就是取x[0][0],取w,然後將它平方,然後x[0][0]和w^2相乘,你就得到了x[0][0]*w^2,以此類推,最終整個建立起來計算cost=[0][0]*w**2+x[1][0]*w+x[2][0],最後你得到了損失函數。

吳恩達深度學習筆記(58)-深度學習框架Tensorflow

TensorFlow的優點在於,通過用這個計算損失,計算圖基本實現前向傳播,TensorFlow已經內置了所有必要的反向函數,回憶一下訓練深度神經網絡時的一組前向函數和一組反向函數,而像TensorFlow之類的編程框架已經內置了必要的反向函數,這也是為什麼通過內置函數來計算前向函數,它也能自動用反向函數來實現反向傳播,即便函數非常複雜,再幫你計算導數,這就是為什麼你不需要明確實現反向傳播,這是編程框架能幫你變得高效的原因之一。

吳恩達深度學習筆記(58)-深度學習框架Tensorflow

如果你看TensorFlow的使用說明,我只是指出TensorFlow的說明用了一套和我不太一樣的符號來畫計算圖,它用了x[0][0],w,然後它不是寫出值,想這裡的w^2,TensorFlow使用說明傾向於只寫運算符,所以這裡就是平方運算,而這兩者一起指向乘法運算,以此類推,然後在最後的節點,我猜應該是一個將x[2][0]加上去得到最終值的加法運算。

吳恩達深度學習筆記(58)-深度學習框架Tensorflow

我認為計算圖用第一種方式會更容易理解,但是如果你去看TensorFlow的使用說明,如果你看到說明裡的計算圖,你會看到另一種表示方式,節點都用運算來標記而不是值,但這兩種呈現方式表達的是同樣的計算圖。

在編程框架中你可以用一行代碼做很多事情,例如,你不想用梯度下降法,而是想用Adam優化器,你只要改變這行代碼,就能很快換掉它,換成更好的優化算法。

所有現代深度學習編程框架都支持這樣的功能,讓你很容易就能編寫複雜的神經網絡。


分享到:


相關文章: