深度學習入門實戰(二)- 用 TensorFlow 訓練線性迴歸

騰訊雲加社群發表於2017-04-21

騰訊雲技術社群-掘金主頁持續為大家呈現雲端計算技術文章,歡迎大家關注!


作者 :董超

上一篇文章我們介紹了 MxNet 的安裝,但 MxNet 有個缺點,那就是文件不太全,用起來可能是要看原始碼才能理解某個方法的含義,所以今天我們就介紹一下 TensorFlow,這個由谷歌爸爸出品的深度學習框架,文件比較全~以後的我們也都使用這個框架~

0x00 概要

TensorFlow是谷歌爸爸出的一個開源機器學習框架,目前已被廣泛應用,谷歌爸爸出品即使效能不是最強的(其實效能也不錯),但絕對是用起來最方便的,畢竟谷歌有Jeff Dean坐鎮,這波穩。

0x01 TensorFlow安裝

官方有一個Mac上TensorFlow的安裝指南,點這裡
我們現在就照著這個安裝指南操作一把,官方推薦在virtualenv中安裝TF,我們就在virtualenv安裝吧,大家也可以直接安裝。前幾天TF釋出1.0版了,我們就安裝1.0版吧~

1.先安裝下pip和six

$ sudo easy_install --upgrade pip
$ sudo easy_install --upgrade six複製程式碼

2.安裝下virtualenv

$ sudo pip install --upgrade virtualenv

3.接下來, 建立一個全新的 virtualenv 環境。這裡將環境建在 ~/tensorflow目錄下, 執行:

$ virtualenv --system-site-packages ~/tensorflow
$ cd ~/tensorflow複製程式碼

4.然後, 啟用 virtualenv:

$ source bin/activate  # 如果使用 bash
$ source bin/activate.csh  # 如果使用 csh複製程式碼

(tensorflow)$ # 終端提示符應該發生變化
如果要退出虛擬環境可以執行

(tensorflow)$ deactivate

也可以直接在shell裡執行下面的程式碼啟用

source ~/tensorflow/bin/activate

5.在 virtualenv 內, 安裝 TensorFlow:
因為我用的是Python 2.x所以執行

$ sudo pip install --upgrade https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-1.0.0-py2-none-any.whl

要是使用Python3可以執行

$ pip3 install --upgrade https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-1.0.0-py3-none-any.whl

當然也可以執行下面這個命令直接安裝最新版

pip install --upgrade tensorflow

等命令執行完TF就安裝好了

安裝完成後可以在python中執行以下程式碼

import tensorflow as tf
hello = tf.constant('Hello, TensorFlow!')
sess = tf.Session()
print(sess.run(hello))複製程式碼

如果輸出

Hello, TensorFlow!

就說明安裝成功啦

PS:執行指令碼的時候會提示不支援SSE xxx指令集的提示,這是因為我們是通過pip直接安裝的編譯好的版本導致的,如果想針對機器優化,可以直接從GitHub上的原始碼編譯安裝。但這樣會複雜些,而且我覺得其實提升不大,用CPU都很慢。。。不如直接上GPU效能提升快。

PS2:如果想安裝GPU版會複雜些,首先要有一塊支援CUDA的N卡,再安裝CUDA驅動啥的,各位看官可以谷歌一下查詢相關資料。如果不想搜尋,也可以看本系列後續文章,以後也會介紹如何在Mac下安裝GPU版。

0x02 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值複製程式碼

0x03 樣例

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了,因為這裡學習率選擇的比較小,所以收斂的比較慢,各位也可以嘗試調大學習率,看看收斂的速度有何變化。

相關推薦

深度學習入門實戰(一)-像Prisma一樣演算法生成梵高風格畫像
深度學習入門實戰(三)-圖片分類中的邏輯迴歸
用TensorFlow進行手寫數字識別


此文已由作者授權騰訊雲技術社群釋出,轉載請註明文章出處
原文連結:www.qcloud.com/community/a…
獲取更多騰訊海量技術實踐乾貨,歡迎大家前往騰訊雲技術社群

【騰訊雲的1001種玩法】徵文活動火熱進行中,歡迎你來撰寫騰訊雲相關技術文章喲,Apple Watch、iPad Mini 等你來拿! 點選檢視詳情

相關文章