TensorFlow 跟 Keras 最大的差異是,TensorFlow 必須要自行設計張量(矩陣)運算。
計算圖 Computational Graph
TensorFlow 設計核心是計算圖 Computational Graph,可分兩個部分:建立計算圖,及執行計算圖。
建立計算圖
透過 TensorFlow 的模組,建立計算圖。
執行計算圖
建立計算圖後,可產生 Session 執行計算圖。Session 的作用是在用戶端與執行裝置之間建立連結,有了連結,就可在不同裝置中,執行計算圖,後續任何跟裝置間的資料傳遞,都必須透過 Session 才能進行。
import tensorflow as tf
# 建立 tensorflow 常數, 常數值為 2, 名稱為 ts_c
ts_c = tf.constant(2,name='ts_c')
# 建立 tensorflow 變數,數值為剛剛的常數 + 5, 名稱為 ts_x
ts_x = tf.Variable(ts_c+5,name='ts_x')
print(ts_c)
## Tensor("ts_c:0", shape=(), dtype=int32)
## Tensor 就是 tensorflow 張量
## shape=() 代表這是 0 維的 tensor,也就是數值
## dtype=int32 張量資料型別為 int32
print(ts_x)
## <tf.Variable 'ts_x:0' shape=() dtype=int32_ref>
#######
# 建立 Session 執行 計算圖
# 產生 session
sess=tf.Session()
# 初始化所有 tensorflow global 變數
init = tf.global_variables_initializer()
sess.run(init)
# 透過 sess.run 執行計算圖,並列印執行結果
print('ts_c=',sess.run(ts_c))
print('ts_x=',sess.run(ts_x))
# 使用 eval,顯示 tensorflow 常數
print('ts_c=',ts_c.eval(session=sess))
print('ts_x=',ts_x.eval(session=sess))
# 不需要再使用 session 時,必須用 close 關閉 session
sess.close()
執行結果
ts_c= 2
ts_x= 7
ts_c= 2
ts_x= 7
可改用 With 語法,就不需要寫 sess.close(),會自動關閉,可解決可能沒有關閉 session 的問題,發生的原因,可能是程式忘了寫,或是中途發生錯誤。
import tensorflow as tf
# 建立 tensorflow 常數, 常數值為 2, 名稱為 ts_c
ts_c = tf.constant(2,name='ts_c')
# 建立 tensorflow 變數,數值為剛剛的常數 + 5, 名稱為 ts_x
ts_x = tf.Variable(ts_c+5,name='ts_x')
print(ts_c)
## Tensor("ts_c:0", shape=(), dtype=int32)
## Tensor 就是 tensorflow 張量
## shape=() 代表這是 0 維的 tensor,也就是數值
## dtype=int32 張量資料型別為 int32
print(ts_x)
## <tf.Variable 'ts_x:0' shape=() dtype=int32_ref>
#######
# 建立 Session 執行 計算圖
with tf.Session() as sess:
# 初始化所有 tensorflow global 變數
init = tf.global_variables_initializer()
sess.run(init)
# 透過 sess.run 執行計算圖,並列印執行結果
print('ts_c=',sess.run(ts_c))
print('ts_x=',sess.run(ts_x))
placeholder
剛剛建立計算圖時,常數與變數都是在建立計算圖的階段,就設定好了。但如果我們希望能在執行計算圖的階段,再設定數值,就必須使用 placeholder。
import tensorflow as tf
# 建立兩個 placeholder,然後用 multiply 相乘,結果存入 area
width = tf.placeholder("int32")
height = tf.placeholder("int32")
area=tf.multiply(width,height)
#######
# 建立 Session 執行 計算圖
# 在 sess.run 傳入 feed_dict 參數 {width: 6, height: 8}
with tf.Session() as sess:
init = tf.global_variables_initializer()
sess.run(init)
print('area=',sess.run(area, feed_dict={width: 6, height: 8}))
# area= 48
deprecated -> 改為tf.compat.v1.
import tensorflow as tf
# 建立兩個 placeholder,然後用 multiply 相乘,結果存入 area
width = tf.compat.v1.placeholder("int32")
height = tf.compat.v1.placeholder("int32")
area=tf.math.multiply(width,height)
#######
# 建立 Session 執行 計算圖
# 在 sess.run 傳入 feed_dict 參數 {width: 6, height: 8}
with tf.compat.v1.Session() as sess:
init = tf.compat.v1.global_variables_initializer()
sess.run(init)
print('area=',sess.run(area, feed_dict={width: 6, height: 8}))
# area= 48
tensorflow 數值運算方法
ref: https://www.tensorflow.org/api_docs/python/tf/math
先建立計算圖,然後用 session.run 執行
常用的數值運算
tensorflow 數值運算 | 說明 |
---|---|
tf.add(x, y, name=None) | 加法 |
tf.substract(x, y, name=None) | 減法 |
tf.multiply(x, y, name=None) | 乘法 |
tf.divide(x, y, name=None) | 除法 |
tf.mod(x, y, name=None) | 餘數 |
tf.sqrt(x, name=None) | 平方 |
tf.abs(x, name=None) | 絕對值 |
TensorBoard
可用視覺化的方式,查看計算圖
- 在建立 placeholder 與 mul 時,加上 name 參數
- 將 TensorBoard 的資料寫入 log file
import tensorflow as tf
# 建立兩個 placeholder,然後用 multiply 相乘,結果存入 area
width = tf.compat.v1.placeholder("int32", name="width")
height = tf.compat.v1.placeholder("int32", name="height")
area=tf.math.multiply(width,height, name="area")
#######
# 建立 Session 執行 計算圖
# 在 sess.run 傳入 feed_dict 參數 {width: 6, height: 8}
with tf.compat.v1.Session() as sess:
init = tf.compat.v1.global_variables_initializer()
sess.run(init)
print('area=',sess.run(area, feed_dict={width: 6, height: 8}))
# area= 48
# 收集所有 TensorBoard 的資料
tf.compat.v1.summary.merge_all()
# 寫入 log file 到 log/area 目錄中
train_writer = tf.compat.v1.summary.FileWriter("log/area", sess.graph)
啟動 tensorboard
> tensorboard --logdir=~/tensorflow/log/area TensorBoard 1.14.0 at http://b39a314348ef:6006/ (Press CTRL+C to quit)
用 browser 瀏覽該網址,點 GRAPHS
建立 1 維與2 維張量
剛剛的例子都是0維的張量,也就是數值純量,接下來是 1 維張量 -> 向量,與2為以上的張量 -> 矩陣
dim 1 or 2 tensor
import tensorflow as tf
# 透過 tf.Variables 傳入 list 用以產生 dim 1 tensor
ts_X = tf.Variable([0.4,0.2,0.4])
# 傳入 2 維的 list 產生 dim 2 tensor
ts2_X = tf.Variable([[0.4,0.2,0.4]])
# dim 2 tensor,有三筆資料,每一筆資料有 2 個數值
W = tf.Variable([[-0.5,-0.2 ],
[-0.3, 0.4 ],
[-0.5, 0.2 ]])
with tf.compat.v1.Session() as sess:
init = tf.compat.v1.global_variables_initializer()
print("dim 1 tensor")
sess.run(init)
X=sess.run(ts_X)
print(X)
# [0.4 0.2 0.4]
print("shape:", X.shape)
# shape: (3,)
print("")
print("dim 2 tensor")
X2=sess.run(ts2_X)
print(X2)
# [[0.4 0.2 0.4]]
print("shape:", X2.shape)
# shape: (1, 3)
print("")
print("dim 2 tensor")
X3=sess.run(W)
print(X3)
print("shape:", X3.shape)
# [[-0.5 -0.2]
# [-0.3 0.4]
# [-0.5 0.2]]
# shape: (3, 2)
矩陣基本運算
浮點運算有近似的結果
import tensorflow as tf
# matrix multiply 矩陣乘法
X = tf.Variable([[1.,1.,1.]])
W = tf.Variable([[-0.5,-0.2 ],
[-0.3, 0.4 ],
[-0.5, 0.2 ]])
XW = tf.matmul(X,W )
# sum 加法
b1 = tf.Variable([[ 0.1,0.2]])
b2 = tf.Variable([[-1.3,0.4]])
Sum = b1+b2
# Y=X*W+b
X3 = tf.Variable([[1.,1.,1.]])
W3 = tf.Variable([[-0.5,-0.2 ],
[-0.3, 0.4 ],
[-0.5, 0.2 ]])
b3 = tf.Variable([[0.1,0.2]])
XWb =tf.matmul(X3,W3)+b3
with tf.compat.v1.Session() as sess:
init = tf.compat.v1.global_variables_initializer()
print("matrix multiply")
sess.run(init)
print(sess.run(XW ))
# [[-1.3 0.4]]
print("")
print('Sum:')
print(sess.run(Sum ))
# [[-1.1999999 0.6 ]]
print("")
print('XWb:')
print(sess.run(XWb ))
# [[-1.1999999 0.6 ]]
以矩陣運算模擬神經網路的訊息傳導
以數學公式模擬,輸出、接收神經元的運作
\(y_1 = actication(x_1*w_{11} + x_2 * w_{21} + x_3*w_{31}+b_1)\)
\(y_2 = actication(x_1*w_{12} + x_2 * w_{22} + x_3*w_{32}+b_2)\)
合併為矩陣運算
\( \begin{bmatrix} y_1 & y_2 \end{bmatrix} = activation(\begin{bmatrix} x_1 & x_2 & x_3 \end{bmatrix} * \begin{bmatrix} w_{11} & w_{12} \\ w_{21} & w_{22} \\ w_{31} & w_{32} \end{bmatrix} + \begin{bmatrix} b_1 & b_2 \end{bmatrix} ) \)
也可表示為
\(Y = activation(X*W + b)\)
\(輸出 = 激活函數(輸入*權重 + 偏差)\)
輸入 X
有三個輸入神經元 \(x_1, x_2, x_3\),接收外部輸入
輸出 y
有兩個輸出神經元 \(y_1, y_2\)
權重 W (weight)
權重模擬神經元的軸突,連接輸入與接收(輸出)神經元,負責傳送訊息,因為要完全連接輸入與接收神經元,共需要 3(輸入) * 2(輸出) = 6 個軸突
\(w_{11}, w_{21}, w_{31}\) 負責將 \(x_1, x_2, x_3\) 傳送訊息給 \(y_1\)
\(w_{12}, w_{22}, w_{32}\) 負責將 \(x_1, x_2, x_3\) 傳送訊息給 \(y_2\)
偏差 bias
bias 模擬突觸瘩結構,代表接收神經元被活化的程度,偏差值越高,越容易被活化並傳遞訊息
激活函數 activation function
當接收神經元 \(y_1\) 接受刺激的總和 \(x_1*w_{11} + x_2 * w_{21} + x_3*w_{31}+b_1\) ,經過激活函數的運算,大於臨界值就會傳遞給下一個神經元
import tensorflow as tf
import numpy as np
X = tf.Variable([[0.4,0.2,0.4]])
W = tf.Variable([[-0.5,-0.2 ],
[-0.3, 0.4 ],
[-0.5, 0.2 ]])
b = tf.Variable([[0.1,0.2]])
XWb =tf.matmul(X,W)+b
# using relu actication function
# y = relu ( (X * W ) + b )
y=tf.nn.relu(tf.matmul(X,W)+b)
# using sigmoid activation function
# y = sigmoid ( (X * W ) + b )
y2=tf.nn.sigmoid(tf.matmul(X,W)+b)
with tf.compat.v1.Session() as sess:
init = tf.compat.v1.global_variables_initializer()
sess.run(init)
print('X*W+b =')
print(sess.run(XWb ))
print('y =')
print(sess.run(y ))
print('y2 =')
print(sess.run(y2 ))
# X*W+b =
# [[-0.35999998 0.28 ]]
# y =
# [[0. 0.28]]
# y2 =
# [[0.41095957 0.5695462 ]]
深度學習模型中,會以 Back Propagation 反向傳播演算法進行訓練, 訓練前要先建立多層感知模型,必須以亂數初始化模型的權重 weight 與 bias, tensorflow 提供 tf.random.normal 產生常態分佈的亂數矩陣
import tensorflow as tf
import numpy as np
W = tf.Variable(tf.random.normal([3, 2]))
b = tf.Variable(tf.random.normal([1, 2]))
X = tf.Variable([[0.4,0.2,0.4]])
y=tf.nn.relu(tf.matmul(X,W)+b)
with tf.compat.v1.Session() as sess:
init = tf.compat.v1.global_variables_initializer()
sess.run(init)
print('b:')
print(sess.run(b ))
print('W:')
print(sess.run(W ))
print('y:')
print(sess.run(y ))
print('')
# 用另一種寫法,一次取得三個 tensorflow 變數
(b2,W2,y2)=sess.run((b,W,y))
print('b2:')
print(b2)
print('W2:')
print(W2)
print('y2:')
print(y2)
# b:
# [[0.7700923 0.02076844]]
# W:
# [[ 0.9547881 -0.0228505 ]
# [ 0.36570853 0.81177294]
# [ 0.0829528 0.48070174]]
# y:
# [[1.2583303 0.3662635]]
# b2:
# [[0.7700923 0.02076844]]
# W2:
# [[ 0.9547881 -0.0228505 ]
# [ 0.36570853 0.81177294]
# [ 0.0829528 0.48070174]]
# y2:
# [[1.2583303 0.3662635]]
normal distribution 的亂數
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
ts_norm = tf.random.normal([1000])
with tf.compat.v1.Session() as session:
norm_data=ts_norm.eval()
print(len(norm_data))
print(norm_data[:30])
# [-0.28433087 1.4285065 -0.68437344 0.9676483 -0.80954283 -0.43311018
# 1.0973732 -1.5478781 -0.6180961 -0.9083597 -1.0577513 -0.43310425
# 0.8295066 0.80313313 -0.42189175 0.9471654 -0.00253101 -0.1117873
# 0.621246 -1.3487787 -0.79825306 -0.563185 0.50175935 0.6651971
# 1.1502678 0.2756175 0.19782086 -1.2379066 0.04300968 -1.3048639 ]
plt.hist(norm_data)
plt.savefig('normal.png')
以 placeholder 傳入 X
import tensorflow as tf
import numpy as np
W = tf.Variable(tf.random.normal([3, 2]))
b = tf.Variable(tf.random.normal([1, 2]))
X = tf.compat.v1.placeholder("float", [None,3])
y=tf.nn.relu(tf.matmul(X,W)+b)
with tf.compat.v1.Session() as sess:
init = tf.compat.v1.global_variables_initializer()
sess.run(init)
X_array = np.array([[0.4,0.2,0.4]])
(b,W,X,y)=sess.run((b,W,X,y),feed_dict={X:X_array})
print('b:')
print(b)
print('W:')
print(W)
print('X:')
print(X)
print('y:')
print(y)
# b:
# [[0.8461168 0.24919121]]
# W:
# [[ 0.10001858 0.20677406]
# [-0.56588995 2.555638 ]
# [-1.5147928 -0.43572944]]
# X:
# [[0.4 0.2 0.4]]
# y:
# [[0.16702908 0.6687367 ]]
X = tf.compat.v1.placeholder("float", [None,3])
第1維設定為 None,是因為傳入的 X 筆數佈限數量,第 2 維是每一筆的數字個數,因為每一筆有三個數字,所以設定為 3
將 X 改為 3x3 矩陣
import tensorflow as tf
import numpy as np
W = tf.Variable(tf.random.normal([3, 2]))
b = tf.Variable(tf.random.normal([1, 2]))
X = tf.compat.v1.placeholder("float", [None,3])
y=tf.nn.relu(tf.matmul(X,W)+b)
with tf.compat.v1.Session() as sess:
init = tf.compat.v1.global_variables_initializer()
sess.run(init)
X_array = np.array([[0.4,0.2 ,0.4],
[0.3,0.4 ,0.5],
[0.3,-0.4,0.5]])
(b,W,X,y)=sess.run((b,W,X,y),feed_dict={X:X_array})
print('b:')
print(b)
print('W:')
print(W)
print('X:')
print(X)
print('y:')
print(y)
# b:
# [[0.6340158 0.5301216]]
# W:
# [[ 1.1625407 0.37071773]
# [-0.7906474 -0.9622891 ]
# [ 0.30319506 -0.04197265]]
# X:
# [[ 0.4 0.2 0.4]
# [ 0.3 0.4 0.5]
# [ 0.3 -0.4 0.5]]
# y:
# [[1.0621806 0.46916184]
# [0.81811655 0.23543498]
# [1.4506345 1.0052663 ]]
layer 函數
以相同的方式,透過 layer 函數,建立多層感知器 Multilayer perception
import tensorflow as tf
import numpy as np
# layer 函數 可用來建立 多層神經網路
# output_dim: 輸出的神經元數量
# input_dim: 輸入的神經元數量
# inputs: 輸入的 2 維陣列 placeholder
# activation: 傳入 activation function
def layer(output_dim,input_dim,inputs, activation=None):
# 以常態分佈的亂數,建立並初始化 W weight 及 bias
W = tf.Variable(tf.random.normal([input_dim, output_dim]))
# 產生 (1, output_dim) 的常態分佈亂數矩陣
b = tf.Variable(tf.random.normal([1, output_dim]))
# 矩陣運算 XWb = (inputs * W) + b
XWb = tf.matmul(inputs, W) + b
# activation function
if activation is None:
outputs = XWb
else:
outputs = activation(XWb)
return outputs
# 輸入 1x4, 第1維 因為筆數不固定,設定為 None
X = tf.placeholder("float", [None,4])
# 隱藏層 1x3
# 隱藏神經元 3 個,輸入神經元 4 個,activation function 為 relu
h = layer(output_dim=3,input_dim=4,inputs=X,
activation=tf.nn.relu)
# 輸出 1x2
# 輸出神經元 2 個,輸入神經元 3 個,傳入 h
y = layer(output_dim=2,input_dim=3,inputs=h)
with tf.compat.v1.Session() as sess:
init = tf.compat.v1.global_variables_initializer()
sess.run(init)
X_array = np.array([[0.4,0.2 ,0.4,0.5]])
(layer_X,layer_h,layer_y)= sess.run((X,h,y),feed_dict={X:X_array})
print('input Layer X:')
print(layer_X)
print('hidden Layer h:')
print(layer_h)
print('output Layer y:')
print(layer_y)
# input Layer X:
# [[0.4 0.2 0.4 0.5]]
# hidden Layer h:
# [[0.9163495 0. 0. ]]
# output Layer y:
# [[ 0.07022524 -2.128551 ]]
跟上面的程式功能一樣,但再加上 W, b 的 debug 資訊
import tensorflow as tf
import numpy as np
# layer 函數 可用來建立 多層神經網路
# output_dim: 輸出的神經元數量
# input_dim: 輸入的神經元數量
# inputs: 輸入的 2 維陣列 placeholder
# activation: 傳入 activation function
def layer_debug(output_dim,input_dim,inputs, activation=None):
# 以常態分佈的亂數,建立並初始化 W weight 及 bias
W = tf.Variable(tf.random.normal([input_dim, output_dim]))
# 產生 (1, output_dim) 的常態分佈亂數矩陣
b = tf.Variable(tf.random.normal([1, output_dim]))
# 矩陣運算 XWb = (inputs * W) + b
XWb = tf.matmul(inputs, W) + b
# activation function
if activation is None:
outputs = XWb
else:
outputs = activation(XWb)
return outputs, W, b
# 輸入 1x4, 第1維 因為筆數不固定,設定為 None
X = tf.placeholder("float", [None,4])
# 隱藏層 1x3
# 隱藏神經元 3 個,輸入神經元 4 個,activation function 為 relu
h,W1,b1=layer_debug(output_dim=3,input_dim=4,inputs=X,
activation=tf.nn.relu)
# 輸出 1x2
# 輸出神經元 2 個,輸入神經元 3 個,傳入 h
y,W2,b2=layer_debug(output_dim=2,input_dim=3,inputs=h)
with tf.compat.v1.Session() as sess:
init = tf.compat.v1.global_variables_initializer()
sess.run(init)
X_array = np.array([[0.4,0.2 ,0.4,0.5]])
(layer_X,layer_h,layer_y)= sess.run((X,h,y),feed_dict={X:X_array})
print('input Layer X:')
print(layer_X)
print('W1:')
print(W1)
print('b1:')
print(b1)
print('hidden Layer h:')
print(layer_h)
print('W2:')
print(W2)
print('b2:')
print(b2)
print('output Layer y:')
print(layer_y)
# input Layer X:
# [[0.4 0.2 0.4 0.5]]
# W1:
# <tf.Variable 'Variable:0' shape=(4, 3) dtype=float32_ref>
# b1:
# <tf.Variable 'Variable_1:0' shape=(1, 3) dtype=float32_ref>
# hidden Layer h:
# [[0. 0. 0.5992681]]
# W2:
# <tf.Variable 'Variable_2:0' shape=(3, 2) dtype=float32_ref>
# b2:
# <tf.Variable 'Variable_3:0' shape=(1, 2) dtype=float32_ref>
# output Layer y:
# [[0.68112874 0.5387946 ]]
沒有留言:
張貼留言