如何開始我的第一個人工智慧模型(tensorflow)
- 安裝tensorflow
大家都知道tensorflow是google開發的一款開源的深度學習程式設計框架,是當今最流行的深度學習開發框架,因此對有志於深度學習研究的小夥伴來說,tensorflow是當仁不讓的第一選擇。
首先看看tensorflow的安裝,其實非常簡單,在python環境安裝好的前提下,直接執行:
pip install tensorflow就可以了。
筆者用的是python3.5環境,tensorflow是1.4版本。
【問題1】如何加快pip安裝速率
在預設pip安裝的時候,國內的網路下經常會報超時,這時有個很好的解決辦法就是將pip的目標庫改到國內的網址,怎麼改呢?只要設定
[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、使用圖(graphs)來表示計算任務,用於搭建神經網路的計算過程,但其只搭建網路,不計算
2、在被稱之為會話(Session)的上下文(context)中執行圖
3、使用張量(tensor)表示資料,用“階”表示張量的維度。關於這一點需要展開一下
0階張量稱為標量,表示單獨的一個數
1階張量稱為向量, 表示一個一維陣列
2階張量稱為矩陣,表示一個二維陣列
……
張量是幾階的可以通過張量右邊的方括號數來判斷。例如 t = [ [ [ ] ] ],顯然這個為3階。
4、通過變數(Variable)維護狀態
5、使用feed和fetch可以為任意的操作賦值或者從其中獲取資料
tensorflow是一個程式設計系統,使用圖(graphs)來表示計算任務,圖(graphs)中的節點稱之為op(operation),一個op獲得0個或者多個tensor,執行計算,產生0個或多個tensor,tensor看作是一個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 * b。tensorflow對乘法等基礎運算都預設內嵌了對應的反向求導函式。
變數是用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中執行。
- 求導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中,ys和xs都是tensor。
更進一步,tf.gradients()接受求導值ys和xs不僅可以是tensor,還可以是list,形如[tensor1, tensor2, …, tensorn]。當ys和xs都是list時,它們的求導關係返回值是一個list,list的長度等於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_ys1的shape與xs的shape相同。
例如:
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)]
- stop_gradients
stop_gradients也是一個list,list中的元素是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])
- 線性模型
真正的機器學習過程中,我們當然是不知道變數的,我們真正的目的就是去習得這些變數,以達到模型能夠儘可能準確預測樣本的期望,也就是所謂的損失(loss)最小化。
機器學習的4部曲:
(1)定義輸入變數和輸出變數
(2)定義神經網路的結構
(3)定義損失函式和優化函式
(4)將輸入輸出資料代入到神經網路進行訓練,生成神經網路的權重引數。
Tensorflow提供了優化器(optimizers)來做這個工作。最簡單的優化器演算法叫梯度下降,這是線上性模型中最常用的一種優化演算法。優化器底層會呼叫Tensorflow Core中的tf.gradients方法來實現梯度下降。
線性模型是機器學習中最簡單的模型,通俗的說就是用線性方程去擬合一些資料,這個方程要滿足的條件就是這些資料到這個方程的距離要最小。
在上面的座標圖上,分佈著一些點,怎麼才能找出一條線(這條線可以是直線,也可是曲線)使這些點到這條線的距離的和最短,這就是線性模型學習的過程。本文主要是講述怎麼用tensorflow去實現線性模型,因此,更多線性模型的知識留給讀者去了解。
優化器的作用是不斷迭代模型直到模型的損失函式達到最小。有好幾種優化器,比如Adam、GradientDescent等。各種優化器的不同點主要在於步長選擇的方式不一樣,有固定步長,有隨著迭代次數增加步長逐漸減少。
線性模型主要是推導公式Y =w*X+b中的權重引數w和偏置引數b。輸入已知的X和Y,定義好損失函式loss,通過優化器的訓練之後得出w和b
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的入門磚,怎麼樣,是不是看起