1. 程式人生 > >如何開始我的第一個人工智慧模型(tensorflow)

如何開始我的第一個人工智慧模型(tensorflow)

  1. 安裝tensorflow

大家都知道tensorflowgoogle開發的一款開源的深度學習程式設計框架,是當今最流行的深度學習開發框架,因此對有志於深度學習研究的小夥伴來說,tensorflow是當仁不讓的第一選擇。

首先看看tensorflow的安裝,其實非常簡單,在python環境安裝好的前提下,直接執行:

pip install tensorflow就可以了。

筆者用的是python3.5環境,tensorflow1.4版本。

【問題1】如何加快pip安裝速率

在預設pip安裝的時候,國內的網路下經常會報超時,這時有個很好的解決辦法就是將pip的目標庫改到國內的網址,怎麼改呢?只要設定

pip.ini檔案就可以了,筆者的pip.ini檔案內容是這樣的:

[global]
timeout = 60000
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
use-mirrors = true
mirrors = https://pypi.tuna.tsinghua.edu.cn
 

這是連到清華的網站上了,然後將pip.ini放到C:\使用者\當前賬號\pip\目錄下就可以了。下面用pip install tensorflow,速度飛快啊!

  1. 基本使用

1、使用圖(graphs)來表示計算任務,用於搭建神經網路的計算過程,但其只搭建網路,不計算

2、在被稱之為會話(Session)的上下文(context)中執行圖

3、使用張量(tensor)表示資料,用表示張量的維度。關於這一點需要展開一下

            0階張量稱為標量,表示單獨的一個數

            1階張量稱為向量, 表示一個一維陣列

            2階張量稱為矩陣,表示一個二維陣列

            ……

張量是幾階的可以通過張量右邊的方括號數來判斷。例如 t = [ [ [    ] ] ],顯然這個為3階。

4、通過變數(Variable)維護狀態

5、使用feedfetch可以為任意的操作賦值或者從其中獲取資料

tensorflow是一個程式設計系統,使用圖(graphs)來表示計算任務,圖(graphs)中的節點稱之為opoperation),一個op獲得0個或者多個tensor,執行計算,產生0個或多個tensortensor看作是一個n維的陣列或列表。圖必須在會話(session)裡被啟動。

最簡單的例子:

import tensorflow as tf     # 簡寫方便一點
 
# 建立兩個常量(constant)
m1=tf.constant([[3,3]])     #一行兩列的矩陣,這裡是矩陣乘法,所以是二維陣列,注意書寫格式以及矩陣乘法規則
m2=tf.constant([[2],[3]])   #兩行一列的矩陣

# 建立一個矩陣乘法(matmul)的op
product=tf.matmul(m1,m2)
print(product)

tf.constant定義一個常量

tf.matmul是乘法運算,也可以寫成a * btensorflow對乘法等基礎運算都預設內嵌了對應的反向求導函式。

變數是用tf.Variable()表示。列印變數不能直接用print方法,要用:print(sess.run(variable1))來列印。

import tensorflow as tf
 
 x=tf.Variable([1,2])    # 定義一個變數,這裡是張量的加減法,所以一維陣列即可
 a=tf.constant([3,3])    # 定義一個常量
 
 sub=tf.subtract(x,a)    # 增加一個減法op
 add=tf.add(x,sub)       # 增加一個加法op
 
 init=tf.global_variables_initializer()   # 在tensorflow中使用變數要初始化,此條語句也可以初始化多個變數
 
 with tf.Session() as sess:
     sess.run(init)                       # 變數初始化,也要放在會話中,才能執行
     print(sess.run(sub))
     print(sess.run(add))

  執行將得到結果

[-2 -1]
[-1  1]

 值得一提的是,在列印常量和變數時,不能像python中的直接print(a),而是需要放在sess.run()中。

定義變數時可先不輸入具體數值,先佔位,在會話中呼叫op時,再輸入具體值,這就是placeholder佔位符的含義了。

import tensorflow as tf
input1 = tf.placeholder(tf.float32)      # 使用placeholder()佔位,需要提供型別
input2 = tf.placeholder(tf.float32)
output = tf.multiply(input1,input2)
with tf.Session() as sess:
    print(sess.run(output,feed_dict={input1:8.0,input2:2.0}))  # 以字典形式輸入feed_dict

執行結果為:16.0

總結:常量、變數、佔位符都必須在sess.run中執行。

  1. 求導gradients

tf.gradients()

tensorflow中,tf.gradients()的引數如下:

tf.gradients(ys, xs, 
             grad_ys=None, 
             name='gradients',
             colocate_gradients_with_ops=False,
             gate_gradients=False,
             aggregation_method=None,
             stop_gradients=None)

先不給出引數的意義。對求導函式而言,其主要功能即求導公式:∂ys/∂xs。在tensorflow中,ysxs都是tensor

更進一步,tf.gradients()接受求導值ysxs不僅可以是tensor,還可以是list,形如[tensor1, tensor2, , tensorn]。當ysxs都是list時,它們的求導關係返回值是一個listlist的長度等於len(xs)

假設返回值是[grad1, grad2, grad3]ys=[y1, y2]xs=[x1, x2, x3]。則,真實的計算過程為:

grad1=y1/x1+y2/x1
grad2=y1/x2+y2/x2
grad3=y1/x3+y2/x3

grad_ys也是一個list,其長度等於len(ys)。這個引數的意義在於對xs中的每個元素的求導加權種。

假設grad_ys=[grad_ys1, grad_ys2, grad_ys3]xs=[x1, x2, x3],則list中每個元素,如grad_ys1shapexsshape相同。

例如:

z1 = 3 * w1 + 2 * w2+ w3
z2 = -1 * w3 + w4
grads = tf.gradients([z1, z2], [w1, w2, w3, w4], grad_ys=[[-2.0, -3.0, -5.0], [-2.0, -3.0, 4.0]])

xs=[w1,w2,w3,w4],所以會返回4個元素。

1個元素對w1求導,計算過程:[z1]中的3*w1擴充套件成3*[-2.0,-3.0,-5.0][z2]沒有對w1的導數,因此返回[-6,-9,-15]

2個元素對w2求導,計算過程:[z1]中的2*w2擴充套件成2*[-2.0,-3.0,-5.0][z2]沒有對w2的導數,因此返回[-4,-6,-10]

3個元素對w3求導,計算過程:[z1]中的w3擴充套件成1*[-2.0,-3.0,-5.0][z2]中的w3擴充套件成-1*[-2.0,-3.0,4.0],因此最後的結果是[1*-2+(-1*-2) , 1*-3+-1*-3 , 1*-5+-1*4]=[0,0,-9]

4個元素對w4求導,計算過程:[z1]中的w4沒有,所以沒梯度;[z2]中的w4擴充套件成1*[-2.0,-3.0,4.0],因此最後的結果是[-2.0,-3.0,4.0]

因此最終的列印結果是:

[array([ -6.,  -9., -15.], dtype=float32), 
array([-4., -6., -10.], dtype=float32), 
array([ 0.,  0., -9.], dtype=float32), 
array([-2., -3.,  4.], dtype=float32)] 
  1. stop_gradients

stop_gradients也是一個listlist中的元素是tensorflow graph中的op,一旦進入這個list,將不會被計算梯度,更重要的是,在該op之後的BP計算都不會執行。

例如:

a = tf.constant(0.)
b = 2 * a
c = a + b
g = tf.gradients(c, [a, b])
計算得g = [3.0, 1.0]。
但如果凍結operator a和b的梯度計算:
a = tf.constant(0.)
b = 2 * a
g = tf.gradients(a + b, [a, b], stop_gradients=[a, b])

計算得g=[1.0, 1.0]

上面的程式碼也等效於:

a = tf.stop_gradient(tf.constant(0.))
b = tf.stop_gradient(2 * a)
g = tf.gradients(a + b, [a, b])
  1. 線性模型

真正的機器學習過程中,我們當然是不知道變數的,我們真正的目的就是去習得這些變數,以達到模型能夠儘可能準確預測樣本的期望,也就是所謂的損失(loss)最小化。

機器學習的4部曲:

1)定義輸入變數和輸出變數

2)定義神經網路的結構

3)定義損失函式和優化函式

4)將輸入輸出資料代入到神經網路進行訓練,生成神經網路的權重引數。

Tensorflow提供了優化器(optimizers)來做這個工作。最簡單的優化器演算法叫梯度下降,這是線上性模型中最常用的一種優化演算法。優化器底層會呼叫Tensorflow Core中的tf.gradients方法來實現梯度下降。

線性模型是機器學習中最簡單的模型,通俗的說就是用線性方程去擬合一些資料,這個方程要滿足的條件就是這些資料到這個方程的距離要最小。

 

在上面的座標圖上,分佈著一些點,怎麼才能找出一條線(這條線可以是直線,也可是曲線)使這些點到這條線的距離的和最短,這就是線性模型學習的過程。本文主要是講述怎麼用tensorflow去實現線性模型,因此,更多線性模型的知識留給讀者去了解。

優化器的作用是不斷迭代模型直到模型的損失函式達到最小。有好幾種優化器,比如AdamGradientDescent等。各種優化器的不同點主要在於步長選擇的方式不一樣,有固定步長,有隨著迭代次數增加步長逐漸減少。

線性模型主要是推導公式Y =w*X+b中的權重引數w和偏置引數b。輸入已知的XY,定義好損失函式loss,通過優化器的訓練之後得出wb

import tensorflow as tf 
# y = Wx + b, 初始化的時候隨便定義一個初始值 
#(1)定義輸入輸出變數
W = tf.Variable([.3], dtype=tf.float32) 
b = tf.Variable([-.3], dtype=tf.float32) 
x = tf.placeholder(tf.float32) 
y = tf.placeholder(tf.float32) 

# (2)定義神經網路模型 
linear_model = W*x + b 

# 損失loss函式,線性模型中以歐式距離來衡量損失值 
loss = tf.reduce_sum(tf.square(linear_model - y)) 

# 定義優化器optimizer 
optimizer = tf.train.GradientDescentOptimizer(0.01) 
train = optimizer.minimize(loss) 

# 訓練資料 
x_train = [1.01, 1.99, 3.02, 4.01] 
y_train = [0, -1.05, -2.03, -3.04] 

# 初始化Session 
init = tf.global_variables_initializer() 
sess = tf.Session() 
sess.run(init) 

# 迴圈1000次,訓練模型 
for i in range(1000): 
	sess.run(train, {x: x_train, y: y_train}) 

# 評估準確率 
curr_W, curr_b, curr_loss = sess.run([W, b, loss], {x: x_train, y: y_train}) 
print("W: %s b: %s loss: %s"%(curr_W, curr_b, curr_loss))

輸出結果:

W: [-1.0067805] b: [0.99450076] loss: 0.0024434922

這就是Tensorflow中線性模型的訓練方式,線性模型是tensorflow的入門磚,怎麼樣,是不是看起