TensorFlow從0到1 - 5 - TensorFlow輕松搞定線性回歸

TensorFlow從0到1系列回顧

上一篇 第一個(gè)機(jī)器學(xué)習(xí)問(wèn)題 其實(shí)是一個(gè)線性回歸問(wèn)題(Linear Regression)假消,呈現(xiàn)了用數(shù)據(jù)來(lái)訓(xùn)練模型的具體方式嚷往。本篇從平行世界返回扮超,利用TensorFlow,重新解決一遍該問(wèn)題苍凛。

TensorFlow的API有低級(jí)和高級(jí)之分壁拉。

底層的API基于TensorFlow內(nèi)核,它主要用于研究或需要對(duì)模型進(jìn)行完全控制的場(chǎng)合汤功。如果你想使用TF來(lái)輔助實(shí)現(xiàn)某個(gè)特定算法物邑、呈現(xiàn)和控制算法的每個(gè)細(xì)節(jié),那么就該使用低級(jí)的API冤竹。

高級(jí)API基于TensorFlow內(nèi)核構(gòu)建拂封,屏蔽了繁雜的細(xì)節(jié),適合大多數(shù)場(chǎng)景下使用鹦蠕。如果你有一個(gè)想法要驗(yàn)證并快速獲得結(jié)果冒签,那么TF的高級(jí)API就是高效的構(gòu)建工具。

本篇使用TF的低級(jí)API來(lái)呈現(xiàn)線性回歸的每一個(gè)步驟钟病。

線性回歸

第一個(gè)機(jī)器學(xué)習(xí)的TF實(shí)現(xiàn)

TensorFlow的計(jì)算分為兩個(gè)階段:

  • 構(gòu)建計(jì)算圖萧恕;
  • 執(zhí)行計(jì)算圖刚梭。

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

import tensorflow as tf

# model parameters
a = tf.Variable([-1.], tf.float32)
b = tf.Variable([50.], tf.float32)

# model input and output
x = tf.placeholder(tf.float32)
linear_model = a * x + b
y = tf.placeholder(tf.float32)

# loss
loss = tf.reduce_sum(tf.square(linear_model - y)) / 8

# training data
x_train = [22, 25, 28, 30]
y_train = [18, 15, 12, 10]

# training loop
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)  # 1st

print("loss: %s" % (sess.run(loss, {x: x_train, y: y_train})))

# 2nd
fixa = tf.assign(a, [-1.])
fixb = tf.assign(b, [40.])
sess.run([fixa, fixb])

print("loss: %s" % (sess.run(loss, {x: x_train, y: y_train})))

程序輸出

loss: 50.0
loss: 0.0

下載 tf_5_manual.py

上面的python代碼利用了在2 TensorFlow內(nèi)核基礎(chǔ) 介紹的基本API實(shí)現(xiàn)了“第一個(gè)機(jī)器學(xué)習(xí)問(wèn)題”。代碼通過(guò)一步步構(gòu)造計(jì)算圖走趋,最后得到了loss節(jié)點(diǎn)衅金。loss即4 第一個(gè)機(jī)器學(xué)習(xí)問(wèn)題中定義過(guò)的損失函數(shù),這里再次給出其定義:

B-P-F-1 損失函數(shù)

構(gòu)建好計(jì)算圖簿煌,接下來(lái)開(kāi)始執(zhí)行氮唯。執(zhí)行l(wèi)oss節(jié)點(diǎn)(同時(shí)提供基于tf.placeholder的訓(xùn)練數(shù)據(jù)),得到loss的值為50姨伟。然后開(kāi)始第二次訓(xùn)練惩琉,修改基于tf.Variable的a和b的值,再次執(zhí)行l(wèi)oss節(jié)點(diǎn)夺荒,loss的值為0瞒渠,降到了最低。此時(shí)的a和b就是最佳的模型參數(shù)了技扼。

還記得那個(gè)神秘力量嗎伍玖?到底是什么讓機(jī)器在第二次訓(xùn)練中將模型參數(shù)(a, b)的值從初始的隨機(jī)值(-1, 50)遷移到最優(yōu)的(-1, 40)?如果不靠運(yùn)氣的話淮摔,機(jī)器如何能自動(dòng)的找到最優(yōu)解呢私沮?

梯度下降算法

在此之前始赎,或許你已經(jīng)想到了隨機(jī)窮舉的辦法和橙,因?yàn)闄C(jī)器不怕累。這的確是個(gè)辦法造垛,但面臨的挑戰(zhàn)也不可接受:不可控魔招。因?yàn)榧幢闶侵挥?個(gè)參數(shù)的模型訓(xùn)練,其枚舉域也是無(wú)限大的五辽,這和靠運(yùn)氣沒(méi)有分別办斑。運(yùn)氣差的話,等個(gè)幾百年也說(shuō)不定杆逗。

不繞圈子乡翅,那個(gè)神秘力量就是:梯度下降算法(gradient descent)。雖然它也是讓機(jī)器一小步一小步的去嘗試不同的(a, b)的組合罪郊,但是它能指導(dǎo)每次前進(jìn)的方向蠕蚜,使得每嘗試一組新的值,loss就能變小一點(diǎn)點(diǎn)悔橄,直到趨于穩(wěn)定靶累。

而這一切TF已經(jīng)把它封裝好了腺毫。 本篇先把它當(dāng)個(gè)黑盒子使用。

tf.train API

import tensorflow as tf

# model parameters
a = tf.Variable([-1.], tf.float32)
b = tf.Variable([50.], tf.float32)

# model input and output
x = tf.placeholder(tf.float32)
linear_model = a * x + b
y = tf.placeholder(tf.float32)

# loss
loss = tf.reduce_sum(tf.square(linear_model - y)) / 8   # sum of the squares

# training data
x_train = [22, 25, 28, 30]
y_train = [18, 15, 12, 10]

# optimizer
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)

# training loop
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
for i in range(1000):
    sess.run(train, {x: x_train, y: y_train})

# evaluate training accuracy
curr_a, curr_b, curr_loss = sess.run([a, b, loss], {x: x_train, y: y_train})
print("a: %s b: %s loss: %s" % (curr_a, curr_b, curr_loss))

代碼幾乎和TensorFlow Get Started官方代碼一致挣柬,主要區(qū)別在于訓(xùn)練數(shù)據(jù)不同潮酒,以及初始值不同。

  • TF官方的訓(xùn)練數(shù)據(jù)是x_train = [1, 2, 3, 4]邪蛔,y_train = [0, -1, -2, -3]急黎,而我們的訓(xùn)練數(shù)據(jù)是“平行世界”的觀察記錄x_train = [22, 25, 28, 30],y_train = [18, 15, 12, 10]侧到。
  • TF官方的(a, b)初始值是(.3, -.3), 我們的是(-1., 50.)叁熔。
  • 或許你還發(fā)現(xiàn)在官方版本的loss函數(shù)末尾沒(méi)有/ 8,是因?yàn)槲沂褂镁讲畹木壒剩?由4x2得到(4個(gè)訓(xùn)練數(shù)據(jù))床牧。

重點(diǎn)說(shuō)下tf.train API荣回。tf.train.GradientDescentOptimizer即封裝了梯度下降算法。梯度下降在數(shù)學(xué)上屬于最優(yōu)化領(lǐng)域戈咳,從其名字Optimizater也可體現(xiàn)出心软。其參數(shù)就是“學(xué)習(xí)率”(learning rate),先記住這個(gè)名詞著蛙,暫不展開(kāi)删铃,其基本的效用是決定待調(diào)整參數(shù)的調(diào)整幅度。學(xué)習(xí)率越大踏堡,調(diào)整幅度越大猎唁,學(xué)習(xí)的越快。反之亦然顷蟆〗胗纾可也并不是越大越好,是相對(duì)來(lái)說(shuō)的帐偎。先取0.01逐纬。

另一個(gè)需要輸入給梯度下降算法的就是loss,它是求最優(yōu)化解的主體削樊,通過(guò)optimizer.minimize(loss)傳入豁生,并返回train節(jié)點(diǎn)。接下來(lái)在循環(huán)中執(zhí)行train節(jié)點(diǎn)即可漫贞,循環(huán)的次數(shù)甸箱,即訓(xùn)練的步數(shù)。

執(zhí)行計(jì)算圖迅脐,程序輸出:

a: [ nan] b: [-inf] loss: nan

這個(gè)結(jié)果令人崩潰芍殖,僅僅換了下TF官方get started中例子中模型的訓(xùn)練數(shù)據(jù)和初始值,它就不工作了仪际。

先來(lái)看看問(wèn)題在哪围小。一個(gè)調(diào)試的小技巧就是打印每次訓(xùn)練的情況昵骤,并調(diào)整loop的次數(shù)。

for i in range(49):
    sess.run(train, {x: x_train, y: y_train})
    curr_a, curr_b, curr_loss = sess.run([a, b, loss], {x: x_train, y: y_train})
    print("a: %s b: %s loss: %s" % (curr_a, curr_b, curr_loss))

程序輸出:

overflow

TF實(shí)際是工作的肯适,并沒(méi)有撂挑子变秦。只是它訓(xùn)練時(shí)每次調(diào)整(a, b)都幅度很大,接下來(lái)又矯枉過(guò)正且幅度越來(lái)越大框舔,導(dǎo)致最終承載a和b的tf.float32溢出而產(chǎn)生了nan蹦玫。這不是TF的一個(gè)bug,而是算法本身刘绣、訓(xùn)練數(shù)據(jù)樱溉、學(xué)習(xí)率、訓(xùn)練次數(shù)共同導(dǎo)致的(它們有個(gè)共同的名字:超參數(shù)纬凤。)福贞。可見(jiàn)停士,訓(xùn)練是一門藝術(shù)挖帘。

直覺(jué)上,初始值或許有優(yōu)劣之分恋技,或許是離最優(yōu)值越近的初始值越容易找到拇舀。可是訓(xùn)練數(shù)據(jù)則應(yīng)該是無(wú)差別的吧蜻底?實(shí)則不然骄崩。但是現(xiàn)在我還不打算把它解釋清楚,等后面分析完梯度下降算法后再回來(lái)看這個(gè)問(wèn)題薄辅。

遇到該問(wèn)題的也不再少數(shù)要拂,Stack Overflow上已經(jīng)很好的回答了。我們先通過(guò)調(diào)整學(xué)習(xí)率和訓(xùn)練次數(shù)來(lái)得到一個(gè)完美的Ending长搀。

把學(xué)習(xí)率從0.01調(diào)制0.0028宇弛,然后將訓(xùn)練次數(shù)從1000調(diào)整至70000鸡典。

程序輸出:

a: [-1.02855277] b: [ 40.75948715] loss: 0.00379487

最終代碼如下:

import tensorflow as tf

# model parameters
a = tf.Variable([-1.], tf.float32)
b = tf.Variable([50.], tf.float32)

# model input and output
x = tf.placeholder(tf.float32)
linear_model = a * x + b
y = tf.placeholder(tf.float32)

# loss
loss = tf.reduce_sum(tf.square(linear_model - y)) / 8   # sum of the squares

# training data
x_train = [22, 25, 28, 30]
y_train = [18, 15, 12, 10]

# optimizer
optimizer = tf.train.GradientDescentOptimizer(0.0028)
train = optimizer.minimize(loss)

# training loop
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
for i in range(70000):
    sess.run(train, {x: x_train, y: y_train})

# evaluate training accuracy
curr_a, curr_b, curr_loss = sess.run([a, b, loss], {x: x_train, y: y_train})
print("a: %s b: %s loss: %s" % (curr_a, curr_b, curr_loss))

下載 tf_5_tf.train.py

TensorBoard

TF的另一個(gè)強(qiáng)大之處就是可視化算法的TensorBoard源请,把構(gòu)造的計(jì)算圖顯示出來(lái)。圖中顯示彻况,每一個(gè)基本運(yùn)算都被獨(dú)立成了一個(gè)節(jié)點(diǎn)谁尸。除了圖中我標(biāo)注的Rank節(jié)點(diǎn)、range節(jié)點(diǎn)纽甘,start節(jié)點(diǎn)良蛮、delta節(jié)點(diǎn)外,其他節(jié)點(diǎn)都是由所寫代碼構(gòu)建出來(lái)的悍赢。

TensorBoard

詞匯表

  • derivative决瞳; 導(dǎo)數(shù)货徙;
  • estimator: 估計(jì);
  • gradient descent: 梯度下降皮胡;
  • inference: 推理痴颊;
  • linear regression:線性回歸;
  • loss function: 損失函數(shù)屡贺;
  • magnitude: 量蠢棱;
  • optimal: 最優(yōu)的;
  • optimizers: 優(yōu)化器甩栈;

上一篇 4 第一個(gè)機(jī)器學(xué)習(xí)問(wèn)題
下一篇 6 解鎖梯度下降算法


共享協(xié)議:署名-非商業(yè)性使用-禁止演繹(CC BY-NC-ND 3.0 CN)
轉(zhuǎn)載請(qǐng)注明:作者黑猿大叔(簡(jiǎn)書)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末泻仙,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子量没,更是在濱河造成了極大的恐慌玉转,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件殴蹄,死亡現(xiàn)場(chǎng)離奇詭異冤吨,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)饶套,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門漩蟆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人妓蛮,你說(shuō)我怎么就攤上這事怠李。” “怎么了蛤克?”我有些...
    開(kāi)封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵捺癞,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我构挤,道長(zhǎng)髓介,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任筋现,我火速辦了婚禮唐础,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘矾飞。我一直安慰自己一膨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布洒沦。 她就那樣靜靜地躺著豹绪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪申眼。 梳的紋絲不亂的頭發(fā)上瞒津,一...
    開(kāi)封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天蝉衣,我揣著相機(jī)與錄音,去河邊找鬼巷蚪。 笑死买乃,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的钓辆。 我是一名探鬼主播剪验,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼前联!你這毒婦竟也來(lái)了功戚?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤似嗤,失蹤者是張志新(化名)和其女友劉穎啸臀,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體烁落,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乘粒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了伤塌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灯萍。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖每聪,靈堂內(nèi)的尸體忽然破棺而出旦棉,到底是詐尸還是另有隱情,我是刑警寧澤药薯,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布绑洛,位于F島的核電站,受9級(jí)特大地震影響童本,放射性物質(zhì)發(fā)生泄漏真屯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一穷娱、第九天 我趴在偏房一處隱蔽的房頂上張望绑蔫。 院中可真熱鬧,春花似錦鄙煤、人聲如沸晾匠。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至薪寓,卻和暖如春亡资,著一層夾襖步出監(jiān)牢的瞬間澜共,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工锥腻, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嗦董,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓瘦黑,卻偏偏與公主長(zhǎng)得像京革,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子幸斥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容