隨機、mini-batch、batch(見最后解釋)
在每個 epoch 送入單個數據點。這被稱為隨機梯度下降(stochastic gradient descent)。我們也可以在每個 epoch 送入一堆數據點,這被稱為 mini-batch 梯度下降,或者甚至在一個 epoch 一次性送入所有的數據點,這被稱為 batch 梯度下降。
轉自:https://cloud.tencent.com/developer/article/1004866
TensorFlow基本使用
TensorFlow的一些基本概念
1.placehoder(占位符)
tf.placeholder(dtype, shape=None, name=None) Args: dtype: The type of elements in the tensor to be fed. shape: The shape of the tensor to be fed (optional). If the shape is not specified, you can feed a tensor of any shape. name: A name for the operation (optional).
dytpe:占位符的數據類型 shape:占位符的緯度,例如[2,2]代表2x2的二維矩陣,None可以代表任意維度,例如[None,2]則代表任意行數,2列的二維矩陣 name:占位符的名字
變量在定義時要初始化,但可能有些變量我們一開始定義的時候並不一定知道該變量的值,只有當真正開始運行程序的時候才由外部輸入,比如我們需要訓練的數據,所以就用占位符來占個位置,告訴TensorFlow,等到真正運行的時候再通過輸入數據賦值。 例如
x = tf.placeholder(tf.float32, [2, 2])
就是生成了一個2x2的二維矩陣,矩陣中每個元素的類型都是tf.float32(也就是浮點型)。
有時候定義需要訓練的參數時候,會定義一個[input_size,output_size]大小的矩陣,其中input_size數輸入數據的維度,output_size是輸出數據的維度
2.Variable(變量)
官方說明 有些長,我就不引用啦,這里介紹一個簡單的用法,有一點變量在聲明的時候要有一個初始值
x = tf.Variable(tf.zeros([2,2])) # 聲明一個2x2的矩陣,並將矩陣中的所有元素的值賦為0,默認每個元素都是tf.float32類型的數據 y = tf.Variable(1.0, tf.float32) # 聲明一個tf.float32的變量,並將初始值設為1.0
我們一般還需要運行下global_variables_initializer真正在TensorFlow的Session中初始化所有變量,后面的樣例中也會有體現。
3.Constant(常量)
官方說明 同樣不引用啦,這里介紹一個簡單的用法
x = tf.constant(3.0, tf.float32) # 定義一個值為3.0的浮點型常量
4.Session(會話)
TensorFlow所有的操作都必須在Session中運行,才能真正起作用,可以將Session當作TensorFlow運行的環境,Session運行完需要close~
#用close()關閉 sess = tf.Session() sess.run(...) sess.close() #使用with..as..語句關閉 with tf.Session() as sess: sess.run(...)
5.簡單使用
我們介紹下3+5應該如何在TensorFlow中實現
import tensorflow as tf x = tf.Variable(3, tf.int16) // 聲明一個整型變量3 y = tf.Variable(5, tf.int16) // 聲明一個整型變量5 z = tf.add(x,y) // z = x + y init = tf.global_variables_initializer() // 初始化變量的操作 with tf.Session() as sess: sess.run(init) // 在Session中初始化變量 print(sess.run(z)) // 輸出計算出的z值
樣例
Github上有一個比較好的Demo合集,有注釋有源代碼還蠻好的,但今天我們不講上面的代碼,我們講如何用TF實現線性回歸模型。
所謂線性回歸模型就是y = W * x + b的形式的表達式擬合的模型。
我們如果想通過深度學習擬合一條直線 y = 3 * x 應該怎么做呢?咱不講虛的先展示下代碼!然后我們在逐步分析。
#coding=utf-8 import tensorflow as tf x = tf.placeholder(tf.float32) W = tf.Variable(tf.zeros([1])) b = tf.Variable(tf.zeros([1])) y_ = tf.placeholder(tf.float32) y = W * x + b lost = tf.reduce_mean(tf.square(y_-y)) optimizer = tf.train.GradientDescentOptimizer(0.0000001) train_step = optimizer.minimize(lost) sess = tf.Session() init = tf.global_variables_initializer() sess.run(init) steps = 1000 for i in range(steps): xs = [i] ys = [3 * i] feed = { x: xs, y_: ys } sess.run(train_step, feed_dict=feed) if i % 100 == 0 : print("After %d iteration:" % i) print("W: %f" % sess.run(W)) print("b: %f" % sess.run(b)) print("lost: %f" % sess.run(lost, feed_dict=feed))
1.先導入需要使用的python庫。
#coding=utf-8 import tensorflow as tf
畢竟是基於TensorFlow的,那我們肯定要導入TensorFlow滴,導入之后取個別名tf,之后用起來方便些。
2.定義需要的變量,我們看看y = W * x + b中都有哪些變量。
x = tf.placeholder(tf.float32) W = tf.Variable(tf.zeros([1])) b = tf.Variable(tf.zeros([1])) y_ = tf.placeholder(tf.float32)
x:我們訓練時需要輸入的真實數據x W: 我們需要訓練的W,這里我們定義了一個1維的變量(其實吧,就是一個普普通通的數,直接用tf.float32也行)並將其初值賦為0 b : 我們需要訓練的b,定義一個1維變量,並將其初值賦為0 y_ :我們訓練時需要輸入的x對應的y
3.定義線性模型
y = W * x + b
4.定義損失函數和優化方法
lost = tf.reduce_mean(tf.square(y_-y)) optimizer = tf.train.GradientDescentOptimizer(0.0000001) train_step = optimizer.minimize(lost)
lost = tf.reducemean(tf.square(y- y))
損失函數(Lost Function)是用來評估我們預測的值和真實的值之間的差距是多少,損失函數有很多種寫法,我們這里使用(y預測-y真實)^2再取平均數來作為我們的損失函數(用這個函數是有原因的,因為我們用的是梯度下降法進行學習)損失函數的值越小越好,有些教程也叫Cost Function
optimizer = tf.train.GradientDescentOptimizer(0.0000001)
優化函數代表我們要通過什么方式去優化我們需要學習的值,這個例子里指的是W和b,優化函數的種類有很多,大家到官網查閱,平時我們用的比較多的是GradientDescentOptimizer和AdamOptimizer等,這里我們選用最常用也是最最基本的GradientDescentOptimizer(梯度下降),后面傳入的值是學習效率。一般是一個小於1的數。越小收斂越慢,但並不是越大收斂越快哈,取值太大甚至可能不收斂了。。。
我們簡單介紹下什么是梯度下降,梯度顧名思義就是函數某一點的導數,也就是該點的變化率。梯度下降則顧名思義就是沿梯度下降的方向求解極小值。
詳細解釋大家可以自行谷歌一下~當然可以可以看這篇文章,當然由於性能的原因梯度下降有很多種變種,例如隨機梯度下降 (Stochastic Gradient Descent),小批梯度下降 (Mini-Batch Gradient Descent)。本文樣例采用的是SGD,每次只輸入一個數據。
train_step = optimizer.minimize(lost)
這個代表我們每次訓練迭代的目的,本例我們的目的就是盡量減小lost的值,也就是讓損失函數的值盡量變小
5.變量初始化
sess = tf.Session() init = tf.global_variables_initializer() sess.run(init)
這個之前有所介紹了,我們需要在Session中真正運行下global_variables_initializer才會真正初始化變量。
6.開始訓練
steps = 1000 for i in range(steps): xs = [i] ys = [3 * i] feed = { x: xs, y_: ys } sess.run(train_step, feed_dict=feed) if i % 100 == 0 : print("After %d iteration:" % i) print("W: %f" % sess.run(W)) print("b: %f" % sess.run(b)) print("lost: %f" % sess.run(lost, feed_dict=feed))
我們定義一個訓練迭代次數1000次。
這里我們圖方便,每次迭代都直接將i作為x,3*i作為y直接當成訓練數據。
我們所有通過placeholder定義的值,在訓練時我們都需要通過feed_dict來傳入數據。
然后我們每隔100次迭代,輸出一次訓練結果,看看效果如何~
After 0 iteration: W: 0.000000 b: 0.000000 lost: 0.000000 After 100 iteration: W: 0.196407 b: 0.002951 lost: 78599.671875 After 200 iteration: W: 1.249361 b: 0.009867 lost: 122582.625000 After 300 iteration: W: 2.513344 b: 0.015055 lost: 21310.636719 After 400 iteration: W: 2.960238 b: 0.016392 lost: 252.449890 After 500 iteration: W: 2.999347 b: 0.016484 lost: 0.096061 After 600 iteration: W: 2.999971 b: 0.016485 lost: 0.000001 After 700 iteration: W: 2.999975 b: 0.016485 lost: 0.000001 After 800 iteration: W: 2.999978 b: 0.016485 lost: 0.000001 After 900 iteration: W: 2.999981 b: 0.016485 lost: 0.000000
可以看到在迭代了500次之后效果就很好了,w已經達到2.999347很接近3了,b也達到了0.016484也比較接近0了,因為這里學習率選擇的比較小,所以收斂的比較慢,各位也可以嘗試調大學習率,看看收斂的速度有何變化。
參考2:
https://mp.weixin.qq.com/s?__biz=MzA3MzI4MjgzMw==&mid=2650718466&idx=1&sn=016f111001e8354d49dd4ce279d283cd#rd
深度 | 機器學習敲門磚:任何人都能看懂的TensorFlow介紹
本文是日本東京 TensorFlow 聚會聯合組織者 Hin Khor 所寫的 TensorFlow 系列介紹文章的前兩部分,自稱給出了關於 TensorFlow 的 gentlest 的介紹。這兩部分談到單一特征問題的線性回歸問題以及訓練(training)的含義,機器之心將繼續關注本系列文章的后續更新。
第一部分
引言
我們要解決的是一個過於簡單且不現實的問題,但其好的一面是便於我們了解機器學習和 TensorFlow 的概念。我們要預測一個基於單一特征(房間面積/平方米)的單標量輸出(房價/美元)。這樣做消除了處理多維數據的需要,使我們能夠在 TensorFlow 中只專注於確定、實現以及訓練模型。
機器學習簡介
我們從一組收集到的數據點開始(見下圖),每個數據點代表兩個值之間的關系——輸出(房價)與影響因素(房子面積)。
然而我們無法預測沒有數據點的特征的值(見下圖)。
我們可以使用機器學習來挖掘它們之間的關系(見下圖的「最佳擬合預測曲線」),即給定一個不屬於數據點的特征值,我們可以准確地預測出輸出(特征值和預測線的交點)。
步驟一:選擇一個模型
1.模型種類
為了使用機器學習來做預測,我們需要選擇一個能夠擬合收集到的數據的最佳模型。
我們可以選擇一個線性(直線)模型,並通過改變其陡度/梯度和位置對其進行調整,從而匹配數據點。
我們也可以選擇一個指數(曲線)模型,並通過改變其曲率(curvature)和位置對其進行調整,從而匹配同一數據點集。
2.成本函數
為了比較哪個模型擬合得更嚴密,數學上我們將最佳擬合定義為一個需要被最小化的成本函數。 成本函數的一個簡單樣例是每個數據點所代表的實際輸出與預測輸出之間偏差的絕對值總和(實際結果到最佳擬合曲線的垂直投影)。用圖表表示,成本函數被描述為下表中藍色線段的長度和。
注意:更准確地說,成本函數往往是實際輸出和預測輸出之間的方差,因為差值有時是負數;這也稱為最小二乘法。
3.線性模型簡介
秉持簡潔精神,我們將使用線性模型來對數據點進行建模。線性模型的數學表示是:
y = W.x + b
Where:
x: house size, in sqm
y: predicted house price, in $
為了調整模型來更好地擬合數據點,我們可以這樣做:
-
調整 W 來改變線性模型的梯度
-
調整 b 來改變線性模型的位置
通過使用許多個 W、b 的值,最終我們可以找到一個最佳擬合線性模型,能夠將成本函數降到最小。
除了隨機嘗試不同的值,有沒有一個更好的方法來快速找到 W、b 的值?
4.梯度下降
如果你試圖從山上下降到最低點,你的視角就是這個樣子。
下降趨勢並不明顯!其最佳方式是執行梯度下降:
-
在當前位置以最陡的下降梯度確定方向
-
在該方向上采取步長 X
-
重復 & 刷新;這就是訓練過程
最小化成本函數是類似的,因為成本函數就像是起伏的山,我們想要找到其中的最低點,我們可以通過梯度下降類似地實現。
現在我們有了線性模型、成本函數和梯度下降的概念,可以開始使用 TensorFlow 了。
步驟二:在TensorFlow 中建立模型
1.TensorFlow 中的線性模型
TensorFlow 的2個基本組件是:
-
占位符(Placeholder):表示執行梯度下降時將實際數據值輸入到模型中的一個入口點。例如房子面積 (x) 和房價 (y_)。
-
變量:表示我們試圖尋找的能夠使成本函數降到最小的「good」值的變量,例如 W 和 b。
然后 TensorFlow 中的線性模型 (y = W.x + b) 就是:
2.TensorFlow 中的成本函數
與將數據點的實際房價 (y_) 輸入模型類似,我們創建一個占位符。
成本函數的最小方差就是:
3.數據
由於沒有房價(y_) 和房子面積 (x) 的實際數據點,我們就生成它們。
簡單起見,我們將房價 (ys) 設置成永遠是房子面積 (xs) 的 2 倍。
4.梯度下降
有了線性模型、成本函數和數據,我們就可以開始執行梯度下降從而最小化代價函數,以獲得 W、b 的「good」值。
0.00001 是我們每次進行訓練時在最陡的梯度方向上所采取的「步」長;它也被稱作學習率(learning rate)。
步驟三:訓練模型
訓練包含以預先確定好的次數執行梯度下降,或者是直到成本函數低於某個預先確定的臨界值為止。
1.TensorFlow 的怪異
所有變量都需要在訓練開始時進行初始化,否則它們可能會帶有之前執行過程中的殘余值。
2.TensorFlow 會話
雖然 TensorFlow 是一個 Python 庫,Python 是一種解釋性的語言,但是默認情況下不把 TensorFlow 運算用作解釋性能的原因,因此不執行上面的 init 。相反 TensorFlow 是在一個會話中進行;創建一個會話 (sess) 然后使用 sess.run() 去執行。
類似地我們在一個循環中調用 withinsess.run() 來執行上面的 train_step。
你需要將由 x, y_ 所組成的實際數據輸入再提供給輸入,因為 TensorFlow 將 train_step 分解為它的從屬項:
從屬項的底部是占位符 x,y_;而且正如我們之前提到的,tf.placeholders 是用來表示所要提供的實際數據點值房價 (y_) 和房子面積 (x) 的位置。
結果
循環中的 print 語句將顯示 TensorFlow 如何在每次迭代中學習 W 和 b 的「good」值。
小結
我們已經以最簡單的形式學習了機器學習;從一個單一特征預測結果。(為簡單起見)我們選擇了一個線性模型來擬合我們的數據點,定義一個成本函數來表示最佳擬合,並通過反復調整其梯度變量 W 與位置變量 b 來訓練我們的模型,使成本函數降到最小。
第二部分
簡單回顧
在上一部分,我們使用 TensorFlow 構建並學習了一個帶有單一特征的線性回歸模型——給定一個特征值(房屋面積/平方米),我們可以預測輸出(房價/美元)。
下面是一些總結:
-
我們有一些房屋面積和房價的數據(灰色點)
-
我們使用線性回歸對這些數據進行了建模(紅色虛線)
-
我們通過訓練該線性回歸模型的 W(權重)和 b(偏置)找到了最小化「成本」(豎直藍色實線的長度總和,這些藍線代表了預測和實際輸出之間的差異)的「最好」模型
-
給定任意房屋面積,我們可以使用該線性模型預測房價(帶箭頭的藍色虛線)
一張圖解釋線性回歸
在機器學習文獻中,我們常常看到「訓練(training)」這個詞。在這一部分,我們將在 TensorFlow 中理解「訓練」的含義。
線性回歸建模
Linear Model (in TF notation): y = tf.matmul(x,W) + b
線性回歸的目標是尋找 W 和 b,這樣對於給定的任意特征值 x,我們可以通過將 W、b 和 x 的值代入到模型中得到預測 y。
但是為了找到能准確做出預測的 W 和 b 的值,我們需要使用可用的數據(許多實際特征 x 和實際輸出 y_ 的配對,注意下划線)來「訓練」該模型。
解釋「訓練」
為了找到最佳的 W 和 b 值,我們可以從任意的 W 和 b 值開始。我們也需要定義一個成本函數,該函數可以衡量對於一個給定特征值 x 預測輸出 y 和實際輸出 y_ 之間差異。為了簡單起見,我們使用最簡單的最小均方誤差(MSE:minimum squared error)作為我們的成本函數。
Cost function (in TF notation): tf.reduce_mean(tf.square(y_ - y))
通過最小化成本函數,我們可以得到很好的 W 和 b 值。
我們的訓練代碼實際上非常簡單,並且用 [A, B, C, D] 進行了注釋,后面我們還會談到這些代碼。完整代碼請訪問:https://github.com/nethsix/gentle_tensorflow/blob/master/code/linear_regression_one_feature_using_mini_batch_with_tensorboard.py
# ... (省略) 變量/常量聲明 ...
# [A] TensorFlow圖
y = tf.matmul(x,W) + b
cost = tf.reduce_mean(tf.square(y_-y))
# [B] 用固定「學習率(learn_rate)」訓練
learn_rate = 0.1
train_step =
tf.train.GradientDescentOptimizer(learn_rate).minimize(cost)
for i in range(steps):
# [C] 准備數據點
# ... (省略) 准備作為x和y的數據點的代碼 ...
# [D] 在每個步驟/epoch將數據送入'train_step'
feed = { x: xs, y_: ys }
sess.run(train_step, feed_dict=feed)
我們的線性模型和成本函數[A]可以表示成下面的 TensorFlow 圖:
創造一個帶有模型和成本函數的 TensorFlow 圖,並使用一些值初始化 W 和 b
接下來,我們選擇一個數據點 (x, y_) [C],然后將其送入[D] TensorFlow 圖,從而得到預測 y 和相應的成本。
使用單個數據點計算預測 y 和成本
為了得到更好的 W 和 b,我們使用TensorFlow 的 tf.train.GradientDescentOptimizer [B]執行梯度下降以降低成本。用非技術的術語來說:給定當前成本,並基於成本歲其它變量(即 W 和 b)的變化方式,優化器(optimizer)將對 W 和 b 執行一些小調整(遞增或遞減)以使我們的預測更好地契合那個單個數據點。
基於當前的成本,決定如何調整 W 和 b 以提升預測 y 和降低成本
訓練周期中的最后步驟是在調整 W 和 b 對它們進行更新。注意這里的「周期」用機器學習的術語來說是「epoch」。
在下一訓練 epoch 的迭代前,通過調整 W 和 b 對它們進行更新
在下一訓練 epoch 中,重復這些步驟,但使用一個不同的數據點!
使用不同的數據點進行訓練
使用各種數據點泛化(generalize)我們的模型,即學習可被用於預測任何特征值的 W 和 b 值。注意:
-
在大部分情況下,數據點越多,模型的學習和泛化就越好
-
如果你訓練的 epoch 比數據點還多,你可以重復使用數據點,這不成問題。梯度下降優化總是會同時使用數據點及其成本(根據該 epoch 的 W 和 b 值從數據點中計算得到)來對 W 和 b 值進行調整;該優化器也許之前已經見過了這個數據點,但成本並不一樣,因此它還是可以學到新的東西,並以不同的方式調整 W 和 b 值。
你可以用固定數量的 epoch 訓練一個模型,直到其達到令人滿意的成本閾值。
訓練變量
1.隨機、mini-batch、batch
在上面的訓練中,我們在每個 epoch 送入單個數據點。這被稱為隨機梯度下降(stochastic gradient descent)。我們也可以在每個 epoch 送入一堆數據點,這被稱為 mini-batch 梯度下降,或者甚至在一個 epoch 一次性送入所有的數據點,這被稱為 batch 梯度下降。請看下圖的比較,注意這 3 張圖的 2 處不同:
-
每個 epoch 送入 TensorFlow 圖(TF.Graph)的數據點的數量(圖右上方)
-
梯度下降優化在調整 W 和 b 值時所考慮的數據點的數量(圖右下方)
隨機梯度下降
mini-batch 梯度下降
batch 梯度下降
每張圖中的數據點的數量有 2 個含義。當數據點更多時:
-
計算成本和執行梯度下降所需的計算資源(減法、平方、加法)會增加
-
模型的學習和泛化的速度增加
選擇隨機、mini-batch、batch 梯度下降的優缺點總結在下圖中:
選擇隨機、mini-batch、batch 梯度下降的優缺點
要在隨機/mini-batch/batch 梯度下降之間切換,我們只需要在將數據點送入訓練步驟[D]之前將這些數據點分成不同的 batch 大小,即為 [C] 使用如下的代碼片段:
# * all_xs: 所有的特征值
# * all_ys: 所有的輸出值
# datapoint_size: all_xs/all_ys 中點/項的數量
# batch_size: 配置如下:
# 1: 隨機模型
# integer < datapoint_size: mini-batch模式
# datapoint_size: batch模式
# i: 當前epoch數量
if datapoint_size == batch_size:
# Batch 模式,所以選擇所有數據點從 index 0 開始
batch_start_idx = 0
elif datapoint_size < batch_size:
# 不可能
raise ValueError(“datapoint_size: %d, must be greater than
batch_size: %d” % (datapoint_size, batch_size))
else:
# 隨機/mini-batch模式: 從所有可能的數據點中分批選擇數據點
batch_start_idx = (i * batch_size) % (datapoint_size — batch_size)
batch_end_idx = batch_start_idx + batch_size
batch_xs = all_xs[batch_start_idx:batch_end_idx]
batch_ys = all_ys[batch_start_idx:batch_end_idx]
# 將分批的數據點定義為xs, ys, 它們會被送入 'train_step'訓練步驟
xs = np.array(batch_xs)
ys = np.array(batch_ys)
2.學習率變化
學習率(learn rate)是指梯度下降調整 W 和 b 遞增或遞減的速度。學習率較小時,處理過程會更慢,但肯定能得到更小成本;而當學習率更大時,我們可以更快地得到最小成本,但有「沖過頭」的風險,導致我們沒法找到最小成本。
為了克服這一問題,許多機器學習實踐者選擇開始時使用較大的學習率(假設開始時的成本離最小成本還很遠),然后隨每個 epoch 而逐漸降低學習率。
TensorFlow 提供了 2 種方法可以做到這一點,詳細解釋可參考:http://stackoverflow.com/questions/33919948/how-to-set-adaptive-learning-rate-for-gradientdescentoptimizer;但這里進行了總結。
-
使用梯度下降優化的變體
TensorFlow 帶有多種支持學習率變化的梯度下降優化器,例如 tf.train.AdagradientOptimizer 和 tf.train.AdamOptimizer.
-
使用 tf.placeholder 調整學習率
如同前面所看到的,如果我們在這個例子中聲明了 tf.placeholder 來設置學習率,然后在 tf.train.GradientDescentOptimizer 中使用它,我們可以在每個訓練 epoch 向其送入一個不同的值,這很像我們給 x 和 y_ 送入不同的數據點,這也是每個 epoch 的 tf.placeholders.
我們需要 2 個小修改:
# 修改 [B] ,將 'learn_rate' 設置為'tf.placeholder'
# 並將其提供給'learning_rate'參數名tf.train.GradientDescentOptimizer
learn_rate = tf.placeholder(tf.float32, shape=[])
train_step = tf.train.GradientDescentOptimizer(
learning_rate=learn_rate).minimize(cost)
# 修改[D],包含送入一個'learn_rate'值,
# 即 'initial_learn_rate'(初始學習率)除以'i' (當前epoch數)
# 注: 這是過於簡化的,僅用作示例
feed = { x: xs, y_: ys, learn_rate: initial_learn_rate/i }
sess.run(train_step, feed_dict=feed)
小結
我們解釋了機器學習中「訓練(training)」的含義,以及在 TensorFlow 中通過模型和成本定義、然后循環通過訓練步驟(將數據點送入梯度下降優化器)來進行訓練的方式。我們還討論了訓練中的常見變量,即改變模型學習時每個 epoch 所用的數據點的大小和改變梯度下降優化器的學習率