TensorFlow初步(3)

TensorFlow初步(3)

大家好我是zyy,本人是機器學習和深度學習的初學愛好者,想跟大家一起分享我的學習經驗,大家一起交流。我寫的東西不一定全對,但肯定是我一步一步走出來的坑,嚼爛了的經驗,可以供大家直接「吸收」

我的文章主要會涉及各種機器學習和深度學習演算法的推導和輪子的實現,以及一些小的應用demo,偶爾還會有一些論文的演算法實現。

文中出現的所有代碼都可以在我的GitHub上找到。

[GitHub](github.com/YuyangZhangF)

線性回歸

今天我們來講最簡單的一個模型,一元線性回歸模型。

我會提供普通python版和TensorFlow版供大家對比學習。

假設我們有數據自變數x_i和自變數y_i,其中,i=1,2,3,..,n,滿足

y = wx+b+epsilon,其中epsilonsim N(0,sigma^2)

其中 wb是我們需要估計的參數。

我們定義回歸的誤差為E=frac{1}{2}{(hat{y_i}-y_i)}^2,i=1,2,3,..,n,其中hat{y_i}=hat{w}x_i+hat{b}hat{w}hat{b}是我們對參數的估計值。

有人會問,誤差函數為什麼是這個樣子,後面會解釋。

插一句題外話

在此插一句我理解的機器學習的過程(或者框架?筆者此處詞窮...)。最近在看《understanding machine learning: theory algorithms》,等我看完,會給出一個我理解的機器學習的定義。

個人認為,一個機器學習的過程就是:

  1. 找出一個對現實現象的抽象模型
  2. 定義一個可以衡量的誤差函數
  3. 通過各種方法來找出合理的權重(或者函數或者分布)來最小化這個誤差

以此達到通過數學模型在一定誤差範圍內來預測未來或者描述現實的目的。

求解方法

剛才說了,要通過各種方法來最小化這個誤差,我們可以把誤差函數寫為

E=frac{1}{2}{(hat{w}x+hat{b}-y)}^2

那麼最小化這個誤差函數我們,我們有什麼辦法?

  1. 無約束問題,求導,令偏導為0,然後就可以得極值點
  2. 用數值方法,如各種梯度下降的方法,不斷逼近極值點

對於這個問題,這兩種方法都很好,但是一般情況下,我們的誤差函數不可能這麼簡單,很多時候有可能無法直接求導得到最優解,所以我們多半採用第二種方法。

採用第二種方法時,我們就可以揭秘一下這個誤差函數這麼設計的秘密。

首先hat{y}-y是誤差,我們一般取絕對值或者平方,這樣來使估計值與真實值儘可能接近。

其次前面的frac{1}{2}則是為了求梯度求導後計算的方便,該誤差函數的導數為:

nfrac{partial E}{partial w}=(wx_i+b-y)x_i,i=1,2,3,...,n

nfrac{partial E}{partial b}=(wx_i+b-y),i=1,2,3,...,n

(數學不好的同學請把求導做3遍...)

然後用梯度下降法,逐步求解最優的參數估計值。通用框架可以寫作:

theta^{(g+1)}=theta^{(g)}-alphanabla Fn

其中alpha稱為學習率(learning rate)。

Python普通版

import numpy as npnimport matplotlib.pyplot as pltnimport tensorflow as tfnn# initial datanplt.ion()nn_observations = 100nfig, ax = plt.subplots(1, 1)nxs = np.linspace(-3, 3, n_observations)nw = 5nb = 1nys = w*xs + b + np.random.normal(0, 1, n_observations)nax.scatter(xs, ys)nfig.show()nplt.draw()nplt.waitforbuttonpress()n

先生成一些數據。預設的w=5,b=1,然後我們生成我們所用的數據xs和ys。

n_epochs = 1000neta = 0.01nnndef error(y, y_hat):n return 1/2*sum((y-y_hat)**2) / (n_observations - 1)nnndef gradient_w(x, y, y_hat):n return sum((y-y_hat) * (-x)) / (n_observations - 1)nnndef gradient_b(x, y, y_hat):n return sum((y-y_hat) * (-1)) / (n_observations - 1)nnw_hat1 = np.random.uniform(0, 10, 1)nb_hat1 = np.random.uniform(0, 10, 1)nnfor i_epoch in range(n_epochs):n y_hat1 = w_hat1 * xs + b_hat1n w_hat1 -= eta * gradient_w(xs, ys, y_hat1)n b_hat1 -= eta * gradient_b(xs, ys, y_hat1)nn if i_epoch % 20 == 0:n print(i_epoch, error(ys, y_hat1))n ax.plot(xs, y_hat1,n k, alpha=i_epoch / n_epochs)n fig.show()n plt.draw()nnprint(w_hat1, b_hat1)nfig.show()nplt.waitforbuttonpress()n

梯度下降迭代次數為1000次,學習率0.1,定義的三個函數依次為誤差函數,w的梯度和b的梯度。初始化wb後,一步一步迭代,求得最優解。

TensorFlow版

寫了這麼長,終於寫到主角了。

說了這麼多,還是為了更好地學習TensorFlow。

n_epochs = 1000neta = 0.01nnX = tf.placeholder(tf.float32)nY = tf.placeholder(tf.float32)nw_hat2 = tf.Variable(tf.random_normal([1]), name=weight)nb_hat2 = tf.Variable(tf.random_normal([1]), name=bias)ny_hat2 = tf.add(tf.mul(X, w_hat2), b_hat2)ncost = tf.reduce_sum(tf.pow(y_hat2 - Y, 2)) / (n_observations - 1)noptimizer = tf.train.GradientDescentOptimizer(eta).minimize(cost)nnwith tf.Session() as sess:n sess.run(tf.global_variables_initializer())n prev_training_cost = 0.0n for i_epoch in range(n_epochs):n for (x, y) in zip(xs, ys):n sess.run(optimizer, feed_dict={X: x, Y: y})nn if i_epoch % 20 == 0:n training_cost = sess.run(cost, feed_dict={X: xs, Y: ys})n print(training_cost)n # ax.plot(xs, y_hat2.eval(feed_dict={x: xs}, session=sess), r, alpha=i_epoch / n_epochs) # something wrong with this function, //TODOn fig.show()n plt.draw()nn print(sess.run(w_hat2), sess.run(b_hat2))nfig.show()nplt.waitforbuttonpress()n

TensorFlow的一個優點就是定義好cost之後,可以選擇優化器來優化(迭代求最小值)這個目標函數,不用自己來做梯度下降。

之後迭代步驟只是反覆run優化器,來一步一步優化。

小節

說點真的題外話,感覺跟第一篇比較,這篇寫得十分匆忙,表達也十分隨意,一點也不嚴謹,好像失去了去好好寫專欄的動力。對能堅持寫專欄和GitHub的前輩們致敬,他們真的很厲害,很多事只有親身去做了,才覺得無比困難。

最近遇到了一些志同道合的朋友,能和他們一起努力真的十分快樂。希望自己能夠繼續寫下去,努力做一個優秀的人。與大家共勉。


推薦閱讀:

Python資料庫起航篇|零基礎起步
Sublime Text 3中怎麼更換python的版本?
詳解Python元類
第十六章 API例子:用Python驅動Firefox採集網頁數據
初學python--認識裝飾器

TAG:TensorFlow | Python | 机器学习 |