1. 程式人生 > 其它 >TensorFlow從0到1丨 第五篇:TensorFlow輕鬆搞定線性迴歸

TensorFlow從0到1丨 第五篇:TensorFlow輕鬆搞定線性迴歸

上一篇 第一個機器學習問題 其實是一個線性迴歸問題(line regression),呈現了用資料來訓練模型的具體方式。本篇從平行世界返回,利用TensorFlow,重新解決一遍該問題。

TensorFlow的API有低階和高階之分。

底層的API基於TensorFlow核心,它主要用於研究或需要對模型進行完全控制的場合。如果你想使用TF來輔助實現某個特定演算法、呈現和控制演算法的每個細節,那麼就該使用低階的API。

高階API基於TensorFlow核心構建,遮蔽了繁雜的細節,適合大多數場景下使用。如果你有一個想法要驗證並快速獲得結果,那麼TF的高階API就是高效的構建工具。

本篇使用TF的低階API來呈現線性迴歸的每一個步驟。

圖一:線性迴歸

第一個機器學習的TF實現

TensorFlow的計算分為兩個階段:

  • 構建計算圖
  • 執行計算圖

先給出“平行世界”版本,(a, b)初始值為(-1, 50),第二次嘗試(-1, 40)

程式輸出:

上面的python程式碼利用了在2 TensorFlow核心基礎 介紹的基本API實現了“第一個機器學習問題”。程式碼通過一步步構造計算圖,最後得到了loss節點。loss即4 第一個機器學習問題中定義過的損失函式,這裡再次給出其定義:

B-P-F-1 損失函式

構建好計算圖,接下來開始執行。執行loss節點(同時提供基於tf.placeholder的訓練資料),得到loss的值為50。然後開始第二次訓練,修改基於tf.Variable的a和b的值,再次執行loss節點,loss的值為0,降到了最低。此時的a和b就是最佳的模型引數了。

還記得那個神祕力量嗎?到底是什麼讓機器在第二次訓練中將模型引數(a, b)的值從初始的隨機值(-1, 50)遷移到最優的(-1, 40)?如果不靠運氣的話,機器如何能自動的找到最優解呢?

梯度下降演算法

在此之前,或許你已經想到了隨機窮舉的辦法,因為機器不怕累。這的確是個辦法,但面臨的挑戰也不可接受:不可控。因為即便是隻有2個引數的模型訓練,其列舉域也是無限大的,這和靠運氣沒有分別。運氣差的話,等個幾百年也說不定。

不繞圈子,那個神祕力量就是:梯度下降演算法(gradient descent)。雖然它也是讓機器一小步一小步的去嘗試不同的(a, b)的組合,但是它能指導每次前進的方向,使得每嘗試一組新的值,loss就能變小一點點,直到趨於穩定。

而這一切TF已經把它封裝好了。 本篇先把它當個黑盒子使用。

tf.train API

程式碼幾乎和TensorFlow Get Started官方程式碼一致,主要區別在於訓練資料不同,以及初始值不同。

  • TF官方的訓練資料是x_train = [1, 2, 3, 4],y_train = [0, -1, -2, -3],而我們的訓練資料是“平行世界”的觀察記錄x_train = [22, 25, 28, 30],y_train = [18, 15, 12, 10]。
  • TF官方的(a, b)初始值是(.3, -.3), 我們的是(-1., 50.)。
  • 或許你還發現在官方版本的loss函式末尾沒有/ 8,是因為我使用均方差的緣故,8由4x2得到(4個訓練資料)。

重點說下tf.train API。tf.train.GradientDescentOptimizer即封裝了梯度下降演算法。梯度下降在數學上屬於最優化領域,從其名字Optimizater也可體現出。其引數就是“學習率”(learning rate),先記住這個名詞,暫不展開,其基本的效用是決定待調整引數的調整幅度。學習率越大,調整幅度越大,學習的越快。反之亦然。可也並不是越大越好,是相對來說的。先取0.01。

另一個需要輸入給梯度下降演算法的就是loss,它是求最優化解的主體,通過optimizer.minimize(loss)傳入,並返回train節點。接下來在迴圈中執行train節點即可,迴圈的次數,即訓練的步數。

執行計算圖,程式輸出:

這個結果令人崩潰,僅僅換了下TF官方get started中例子中模型的訓練資料和初始值,它就不工作了。

先來看看問題在哪。一個除錯的小技巧就是列印每次訓練的情況,並調整loop的次數。

程式輸出:

TF實際是工作的,並沒有撂挑子。只是它訓練時每次調整(a, b)都幅度很大,接下來又矯枉過正且幅度越來越大,導致最終承載a和b的tf.float32溢位而產生了nan。這不是TF的一個bug,而是演算法本身、訓練資料、學習率、訓練次數共同導致的(它們有個共同的名字:超引數。)。可見,訓練是一門藝術

直覺上,初始值或許有優劣之分,或許是離最優值越近的初始值越容易找到。可是訓練資料則應該是無差別的吧?實則不然。但是現在我還不打算把它解釋清楚,等後面分析完梯度下降演算法後再回來看這個問題。

遇到該問題的也不再少數,Stack Overflow上已經很好的回答了。我們先通過調整學習率和訓練次數來得到一個完美的Ending。

把學習率從0.01調製0.0028,然後將訓練次數從1000調整至70000。

程式輸出:

最終程式碼如下:

TensorBoard

TF的另一個強大之處就是視覺化演算法的TensorBoard,把構造的計算圖顯示出來。圖中顯示,每一個基本運算都被獨立成了一個節點。除了圖中我標註的Rank節點、range節點,start節點、delta節點外,其他節點都是由所寫程式碼構建出來的。

TensorBoard

詞彙表

  • derivative; 導數;
  • estimator: 估計;
  • gradient descent: 梯度下降;
  • inference: 推理;
  • line regression:線性迴歸;
  • loss function: 損失函式;
  • magnitude: 量;
  • optimal: 最優的;
  • optimizers: 優化器;