簡單入門機器學習與TensorFlow(1)

0.概念:

機器學習是什麼呢?機器學習就是不用編寫顯性的邏輯代碼就能解決問題。

這裡的「顯性」,很簡單,是指傳統的代碼

def function(param): a=0 b=0 # xxxx各種邏輯xxxx return ret

而不用「顯性的邏輯代碼」則是通過給一個恰當的模型(這個模型有很多參數,也像一個函數),然後讓機器來學習而使得這個模型達到一種穩定的狀態(就是參數「調對了」)也就是達到我們所希望的輸入與輸出。

更簡單點說就是:我們看不清這裡面的邏輯(所以很多人稱機器學習是玄學??)

這樣做有什麼好處呢

  1. 簡單(相比傳統的邏輯代碼),可以很好的解決目前人類在邏輯上有缺陷的問題,比如:圖像識別,語音識別,等等諸如此類。想想,如果不用機器學習,就用傳統代碼怎麼才能識別圖像呀
  2. 模型泛化能力好,能同時解決同類問題。譬如:AlphaGo Zero在圍棋界已經天下無敵,但它在其他棋類也是無敵的,試想下如果要傳統方式那得寫多少東西。

好處還有很多嗯,不過也有壞處

  1. 目前比較火的是深度學習和強化學習,深度學習的一個難點在於數據,要求是「有代表性的數據」和「大量數據」,並且需要人工打標籤。著實是個量很大的工作。強化學習的一個難點是搭建環境和制定規則,很容易漏東西。
  2. 選擇模型也是個難點,還有超參數的值的設定(不過現在網上有很多訓練的好的樣例,多看看就能很好決解)

最後總結下,機器學習目前解決很多曾經很頭疼的問題,而且這也是個趨勢,它講解決更多問題,反正現在互聯網時代,能解決生活問題才是王道。??還有賺

1.快速入門:

我們來用直線來擬合這一系列點:(1, 0)、(2, 2)、(3, 5)、(4, 12)、(5, 22);

如果用傳統方法,則要編寫最小二乘法來解決此類問題。

那麼用機器學習的方法如何做呢?

得到數據後我們要確定模型,我們用一元一次方程:y = w * x + b

在這裡我們模型的參數為w和b

然後確定損失函數(即預測與真實的差),我們用方差:sum[(y真實 - y估計)^2]

最後我們用梯度下降法訓練模型,而我們根據方差確定訓練方向(即參數變化趨勢)

多次訓練後,就能得到一個很好的模型。

在機器學習中,監督式學習(Supervised Learning)通過定義一個模型,並根據訓練集上的數據估計最優參數。梯度下降法(Gradient Descent)是一個廣泛被用來最小化模型誤差的參數優化演算法。梯度下降法通過多次迭代,並在每一步中最小化損失函數(loss function)來估計模型的參數(weights)。

具體代碼:

import tensorflow as tfimport numpy as npimport matplotlib.pyplot as pltsess = tf.Session() # tensorflow要求有一個會話,tf的運算步驟要在會話里完成,具體看代碼x_input = [1, 2, 3, 4, 5] # 輸入點的x坐標,在後面「喂」到x裡面y_true = [0, 2, 5, 12, 22] # 輸入點的y坐標steps = []loss_value = []x = tf.placeholder(dtype=tf.float32) # x為輸入佔位,到後面要用feed_dict拿數據「喂」給這個xw1 = tf.Variable([2], dtype=tf.float32) # 用於訓練的參數w,裡面的參數在開始可以隨便設# w2 = tf.Variable([2], dtype=tf.float32) # 二次函數擬合參數b = tf.Variable([3], dtype=tf.float32) # 用於訓練的參數by = x * w1 + b # 模型# y += tf.pow(x, 2) * w2 # 改為二次式target = tf.placeholder(dtype=tf.float32) # 目標,也就是真實的y值loss = tf.reduce_sum(tf.square(y - target)) # 損失函數:方差optimizer = tf.train.AdamOptimizer(0.001) # 優化器,核心演算法梯度下降,參數為學習率train = optimizer.minimize(loss) # 訓練 -> 減小損失函數sess.run(tf.global_variables_initializer()) # 必須寫,tf的初始化所有全局變數print(sess.run(y, {x: x_input}))desplay = 1000for i in range(20000): # 讓它進行20000次下降(越多越好,但是也更慢) # feed_dict就是把佔位的填充。這裡:讓x_input作為x,y_true作為target輸入 sess.run(train, feed_dict={x: x_input, target: y_true}) if i % desplay == 0: # 每1000步查看一次 l_value = sess.run(loss, feed_dict={x: x_input, target: y_true}) steps.append(i) loss_value.append(l_value) print("No." + str(i) + " : ", l_value)print(sess.run(y, feed_dict={x: x_input}))print("step:", steps)print("loss value:", loss_value)# 下面是繪圖,看最終效果plt.figure(num=1)plt.scatter(x_input, y_true, marker=x)x_pt = np.linspace(1, 5)plt.plot(x_pt, sess.run(y, feed_dict={x: x_pt}), linestylex=--, color=r)plt.figure(num=2)plt.plot(steps, loss_value)plt.xlabel(steps)plt.ylabel(loss)plt.show()

順便解釋下:超參數:人為地加入的參數,不可由機器學習而更新。比如學習率

學習率就是每次梯度下降演算法迭代更新參數的步長

學習率不可太高,可以先設為很低,然後慢慢提高。

一元一次函數擬合情況

差值

由上圖可看出擬合效果也還不錯,和傳統方法一樣好了。

當然如果您不太滿意,也可以用二次函數再擬合一次(代碼中注釋的)

把它變成y = w1*x + w2*x^2 + b就可以,改成三四五次的都可以,想怎麼用就怎麼用

(注意,參數多了容易發生過擬合)

最後上二次函數擬合的結果:

二次函數擬合結果

方差

果然二次函數擬合效果更好,那麼相比,一次函數不是那麼好,它就是「欠擬合」了。

下一節我們就建立一個單層的神經網路,直接上數字的手寫識別。

文中有不準確的歡迎大佬留言,我非常希望你們能幫上我。??

封面我最愛的Nevada


推薦閱讀:

Inside TF-Slim(2) arg_scope
機器學習 | 更進一步,用評估器給花卉分類
【博客存檔】TensorFlow之深入理解Neural Style
如何在 TensorFlow 中使用多個 Graph

TAG:機器學習 | TensorFlow | 入門指南 |