複製鏈接
請複製以下鏈接發送給好友

TensorFlow

(符號數學系統)

鎖定
TensorFlow™是一個基於數據流編程(dataflow programming)的符號數學系統,被廣泛應用於各類機器學習(machine learning)算法的編程實現,其前身是谷歌的神經網絡算法庫DistBelief [1] 
Tensorflow擁有多層級結構,可部署於各類服務器、PC終端和網頁並支持GPUTPU高性能數值計算,被廣泛應用於谷歌內部的產品開發和各領域的科學研究 [1-2] 
TensorFlow由谷歌人工智能團隊谷歌大腦(Google Brain)開發和維護,擁有包括TensorFlow Hub、TensorFlow Lite、TensorFlow Research Cloud在內的多個項目以及各類應用程序接口(Application Programming Interface, API) [2]  。自2015年11月9日起,TensorFlow依據阿帕奇授權協議(Apache 2.0 open source license)開放源代碼 [2] 
外文名
TensorFlow
開發者
谷歌大腦
初始版本
beta/2015年11月9日
穩定版本
1.12.0/2018年10月9日
編程語言
Python,C++,CUDA
平    台
Linux,macOS,Windows
類    型
機器學習庫
許可協議
Apache 2.0 open source license

TensorFlow背景

谷歌大腦自2011年成立起開展了面向科學研究和谷歌產品開發的大規模深度學習應用研究,其早期工作即是TensorFlow的前身DistBelief [1]  。DistBelief的功能是構建各尺度下的神經網絡分佈式學習和交互系統,也被稱為“第一代機器學習系統” [1]  。DistBelief在谷歌和Alphabet旗下其它公司的產品開發中被改進和廣泛使用 [3-4]  。2015年11月,在DistBelief的基礎上,谷歌大腦完成了對“第二代機器學習系統”TensorFlow的開發並對代碼開源。相比於前作,TensorFlow在性能上有顯著改進、構架靈活性和可移植性也得到增強 [1]  。此後TensorFlow快速發展,截至穩定API版本1.12,已擁有包含各類開發和研究項目的完整生態系統。在2018年4月的TensorFlow開發者峯會中,有21個TensorFlow有關主題得到展示 [2] 

TensorFlow安裝

TensorFlow語言與系統支持

TensorFlow支持多種客户端語言下的安裝和運行。截至版本1.12.0,綁定完成並支持版本兼容運行的語言為CPython,其它(試驗性)綁定完成的語言為JavaScriptC++JavaGoSwift,依然處於開發階段的包括C#HaskellJuliaRuby、Rust和Scala [5] 
Python
TensorFlow提供Python語言下的四個不同版本:CPU版本(tensorflow)、包含GPU加速的版本(tensorflow-gpu),以及它們的每日編譯版本(tf-nightly、tf-nightly-gpu)。TensorFlow的Python版本支持Ubuntu 16.04、Windows 7macOS 10.12.6 Sierra、Raspbian 9.0及對應的更高版本,其中macOS版不包含GPU加速 [6]  。安裝Python版TensorFlow可以使用模塊管理工具pip/pip3 [7] anaconda並在終端直接運行。
pip install tensorflow
conda install -c conda-forge tensorflow
此外Python版TensorFlow也可以使用Docker安裝 [8] 
docker pull tensorflow/tensorflow:latest
# 可用的tag包括latest、nightly、version等
# docker鏡像文件:https://hub.docker.com/r/tensorflow/tensorflow/tags/
docker run -it -p 8888:8888 tensorflow/tensorflow:latest
# dock下運行jupyter notebook
docker run -it tensorflow/tensorflow bash
# 啓用編譯了tensorflow的bash環境
C
TensorFlow提供C語言下的API用於構建其它語言的API,支持x86-64下的Linux類系統和macOS 10.12.6 Sierra或其更高版本,macOS版不包含GPU加速 [9]  。安裝過程如下 [9] 
下載TensorFlow預編譯的C文件到本地系統路徑(通常為/usr/local/lib)並解壓縮。
sudo tar -xz libtensorflow.tar.gz -C /usr/local
使用ldconfig編譯鏈接
sudo ldconfig
此外用户也可在其它路徑解壓文件並手動編譯鏈接。
# Linux
export LIBRARY_PATH=$LIBRARY_PATH:~/mydir/lib
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/mydir/lib
# MacOS
export LIBRARY_PATH=$LIBRARY_PATH:~/mydir/lib
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:~/mydir/lib
編譯C接口時需確保本地的C編譯器(例如gcc)能夠訪問TensorFlow庫 [9] 
配置GPU
TensorFlow支持在Linux和Window系統下使用統一計算架構(Compute Unified Device Architecture, CUDA)高於3.5的NVIDIA GPU [10-11]  和ROCm [79-80]  。配置GPU時要求系統有NVIDIA GPU驅動384.x及以上版本、CUDA Toolkit和CUPTI(CUDA Profiling Tools Interface)9.0版本、cuDNN SDK7.2以上版本。可選配置包括NCCL 2.2用於多GPU支持、TensorRT 4.0用於TensorFlow模型優化 [10] 
在Linux下配置GPU時,將CUDA Toolkit和CUPTI的路徑加入$LD_LIBRARY_PATH環境變量即可。對於CUDA為3.0或其它版本的NVIDIA程序,需要從源文件編譯TensorFlow [10]  。對Windows下的GPU配置,需要將CUDA、CUPTI和cuDNN的安裝路徑加入%PATH%環境變量,在DOS終端有如下操作 [10] 
C:\> SET PATH=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\bin;%PATH%
C:\> SET PATH=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\extras\CUPTI\libx64;%PATH%
C:\> SET PATH=C:\tools\cuda\bin;%PATH%
Linux系統下使用docker安裝的Python版TensorFlow也可配置GPU加速且無需CUDA Toolkit [8] 
# 確認GPU狀態
lspci | grep -i nvidia
# 導入GPU加速的TensorFlow鏡像文件
docker pull tensorflow/tensorflow:latest-gpu
# 驗證安裝
docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi
# 啓用bash環境
docker run --runtime=nvidia -it tensorflow/tensorflow:latest-gpu bash

TensorFlow版本兼容性

TensorFlow的公共API版本號使用語義化版本2.0標準 [12]  ,包括主版本號.次版本號.修訂號,其中主版本號的更改不是向下兼容的,已保存的TensorFlow工作可能需遷移到新的版本; 次版本號的更改包含向下兼容的性能提升;修訂號的更改是向下兼容的問題修正 [5] 
TensorFlow支持版本兼容的部分包括協議緩衝區文件、所有的C接口、Python接口中的tensorflow模塊以及除tf.contrib和其它私有函數外的所有子模塊、Python函數和類 [5]  。更新不支持版本兼容的部分為:包含“試驗性(experimental)”字段的組件、使用除C和Python外其它語言開發的TensorFlow API、以GraphDef形式保存的工作、浮點數值特定位的計算精度、隨機數、錯誤和錯誤消息 [5]  。其中GraphDef擁有與TensorFlow相獨立的版本號,當TensorFlow的更新放棄對某一GraphDef版本的支持後,可能有相關工具幫助用户將GraphDef轉化為受支持的版本 [5]  。需要指出,儘管 GraphDef的版本機制與TensorFlow相獨立,但對GraphDef的更改仍受限於語義版本控制,即只能在TensorFlow主版本號之間移除或更改功能。此外,修訂版本之間實施GraphDef的向前兼容 [5] 

TensorFlow組件與工作原理

TensorFlow核心組件

TensorFlow的代碼結構 TensorFlow的代碼結構 [13]
分佈式TensorFlow的核心組件(core runtime)包括:分發中心(distributed master)、執行器(dataflow executor/worker service)、內核應用(kernel implementation)和最底端的設備層(device layer)/網絡層(networking layer) [13] 
分發中心從輸入的數據流圖中剪取子圖(subgraph),將其劃分為操作片段並啓動執行器。分發中心處理數據流圖時會進行預設定的操作優化,包括公共子表達式消去(common subexpression elimination)、常量摺疊(constant folding)等 [13] 
執行器負責圖操作(graph operation)在進程和設備中的運行、收發其它執行器的結果。分佈式TensorFlow擁有參數器(parameter server)以彙總和更新其它執行器返回的模型參數。執行器在調度本地設備時會選擇進行並行計算和GPU加速 [13] 
內核應用負責單一的圖操作,包括數學計算、數組操作(array manipulation)、控制流(control flow)和狀態管理操作(state management operations)。內核應用使用Eigen執行張量的並行計算、cuDNN庫等執行GPU加速、gemmlowp執行低數值精度計算,此外用户可以在內核應用中註冊註冊額外的內核(fused kernels)以提升基礎操作,例如激勵函數和其梯度計算的運行效率 [13] 
單進程版本的TensorFlow沒有分發中心和執行器,而是使用特殊的會話應用(Session implementation)聯繫本地設備。TensorFlow的C語言API是核心組件和用户代碼的分界,其它組件/API均通過C語言API與核心組件進行交互 [13] 

TensorFlow低階API

張量(tf.Tensor)
張量是TensorFlow的核心數據單位,在本質上是一個任意維的數組。可用的張量類型包括常數、變量、張量佔位符和稀疏張量 [14-15]  。這裏提供一個對各類張量進行定義的例子:
import numpy as np
import tensorflow as tf
# tf.constant(value, dtype=None, name='Const', verify_shape=False)
tf.constant([0, 1, 2], dtype=tf.float32) # 定義常數
# tf.placeholder(dtype, shape=None, name=None)
tf.placeholder(shape=(None, 2), dtype=tf.float32) # 定義張量佔位符
#tf.Variable(<initial-value>, name=<optional-name>)
tf.Variable(np.random.rand(1, 3), name='random_var', dtype=tf.float32) # 定義變量
# tf.SparseTensor(indices, values, dense_shape)
tf.SparseTensor(indices=[[0, 0], [1, 2]], values=[1, 2], dense_shape=[3, 4]) # 定義稀疏張量
# tf.sparse_placeholder(dtype, shape=None, name=None)
tf.sparse_placeholder(dtype=tf.float32)
張量的秩是它的維數,而它的形狀是一個整數元組,指定了數組中每個維度的長度 [14]  。張量按NumPy數組的方式進行切片和重構 [14]  。這裏提供一個進行張量操作的例子:
# 定義二階常數張量
a = tf.constant([[0, 1, 2, 3], [4, 5, 6, 7]], dtype=tf.float32)
a_rank = tf.rank(a) # 獲取張量的秩
a_shape = tf.shape(a) # 獲取張量的形狀
b = tf.reshape(a, [4, 2]) # 對張量進行重構
# 運行會話以顯示結果
with tf.Session() as sess:
   print('constant tensor: {}'.format(sess.run(a)))
   print('the rank of tensor: {}'.format(sess.run(a_rank)))
   print('the shape of tensor: {}'.format(sess.run(a_shape)))
   print('reshaped tensor: {}'.format(sess.run(b)))
   # 對張量進行切片
   print("tensor's first column: {}".format(sess.run(a[:, 0])))
張量有23種數據類型,包括4類浮點實數、2類浮點複數、13類整數、邏輯、字符串和兩個特殊類型,數據類型之間可以互相轉換 [16]  。TensorFlow中的張量是數據流圖中的單位,可以不具有值,但在圖構建完畢後可以獲取其中任意張量的值,該過程被稱為“評估(evaluate) [16]  ”:
constant = tf.constant([1, 2, 3]) # 定義常數張量
square = constant*constant # 操作(平方)
# 運行會話
with tf.Session() as sess:
   print(square.eval()) # “評估”操作所得常數張量的值
TensorFlow無法直接評估在函數內部或控制流結構內部定義的張量。如果張量取決於隊列中的值,那麼只有在某個項加入隊列後才能評估。
變量(tf.Variable)
變量是可以通過操作改變取值的特殊張量 [17-18]  。變量必須先初始化後才可使用,低階API中定義的變量必須明確初始化,高階API例如Keras會自動對變量進行初始化。TensorFlow可以在tf.Session開始時一次性初始化所有變量,對自行初始化變量,在tf.Variable上運行的tf.get_variable可以在定義變量的同時指定初始化器 [19]  。這裏提供兩個變量初始化的例子:
# 例1:使用TensorFlow的全局隨機初始化器
a = tf.get_variable(name='var5', shape=[1, 2])
init = tf.global_variables_initializer()
with tf.Session() as sess:
   sess.run(init)
   print(a.eval())
# 例2:自行定義初始化器
# tf.get_variable(name, shape=None, dtype=None, initializer=None, trainable=None, ...)
var1 = tf.get_variable(name="zero_var", shape=[1, 2, 3], dtype=tf.float32,
 initializer=tf.zeros_initializer) # 定義全零初始化的三維變量
var2 = tf.get_variable(name="user_var", initializer=tf.constant([1, 2, 3],  dtype=tf.float32)) 
# 使用常數初始化變量,此時不指定形狀shape
Tensorflow提供變量集合以儲存不同類型的變量,默認的變量集合包括 [20] 
  • 本地變量:tf.GraphKeys.LOCAL_VARIABLES
  • 全局變量:tf.GraphKeys.GLOBAL_VARIABLES
  • 訓練梯度變量:tf.GraphKeys.TRAINABLE_VARIABLES
用户也可以自行定義變量集合:
var3 = tf.get_variable(name="local_var", shape=(), collections=[tf.GraphKeys.LOCAL_VARIABLES])
在對變量進行共享時,可以直接引用tf.Variables,也可以使用 tf.variable_scope [21]  進行封裝:
def toy_model():
   定義包含變量的操作
   var1 = tf.get_variable(name="user_var5", initializer=tf.constant([1, 2, 3], dtype=tf.float32))
   var2 = tf.get_variable(name="user_var6", initializer=tf.constant([1, 1, 1], dtype=tf.float32))
   return var1+var2
with tf.variable_scope("model") as scope:
   output1 = toy_model()
   # reuse語句後二次利用變量
   scope.reuse_variables()
   output2 = toy_model()
# 在variable_scope程序塊內啓用reuse
with tf.variable_scope(scope, reuse=True):
   output3 = toy_model()
數據流圖(tf.Graph)和會話(tf.Session)
一個前饋神經網絡的拓撲結構(左)和TensorFlow數據流圖(右) 一個前饋神經網絡的拓撲結構(左)和TensorFlow數據流圖(右) [22]
TensorFlow在數據流編程下運行,具體地,使用數據流圖(tf.Graph)表示計算指令間的依賴關係,隨後依據圖創建會話(tf.Session)並運行圖的各個部分 [23]  。tf.Graph包含了圖結構與圖集合兩類相關信息,其中圖結構包含圖的節點(tf.Operation)和邊緣(張量)對象,表示各個操作組合在一起的方式,但不規定它們的使用方式,類似於彙編代碼;圖集合是在tf.Graph中存儲元數據集合的通用機制,即對象列表與鍵(tf.GraphKeys)的關聯 [24]  。例如當用户創建變量時,系統將其加入變量集合,並在後續操作中使用變量集合作為默認參數 [23] 
構建tf.Graph時將節點和邊緣對象加入圖中不會觸發計算,圖構建完成後將計算部分分流給tf.Session實現計算。tf.Session擁有物理資源,通常與Python的with代碼塊中使用,在離開代碼塊後釋放資源 [11]  [23]  。在不使用with代碼塊的情況下創建tf.Session,應在完成會話時明確調用tf.Session.close結束進程。調用Session.run創建的中間張量會在調用結束時或結束之前釋放。tf.Session.run是運行節點對象和評估張量的主要方式,tf.Session.run需要指定fetch並提供供給數據(feed)字典,用户也可以指定其它選項以監督會話的運行 [23]  [25]  。這裏使用低階API以批量梯度下降的線性迴歸為例展示tf.Graph的構建和tf.Session的運行:
# 導入模塊
import numpy as np
import tensorflow as tf
# 準備學習數據
train_X = np.random.normal(1, 5, 200) # 輸入特徵
train_Y = 0.5*train_X+2+np.random.normal(0, 1, 200) # 學習目標
L = len(train_X) # 樣本量
# 定義學習超參數
epoch = 200 # 紀元數(使用所有學習數據一次為1紀元)
learn_rate = 0.005 # 學習速度
# 定義數據流圖
temp_graph = tf.Graph()
with temp_graph.as_default():
   X = tf.placeholder(tf.float32) # 定義張量佔位符
   Y = tf.placeholder(tf.float32)
   k = tf.Variable(np.random.randn(), dtype=tf.float32)
   b = tf.Variable(0, dtype=tf.float32) # 定義變量
   linear_model = k*X+b # 線性模型
   cost = tf.reduce_mean(tf.square(linear_model - Y)) # 代價函數
   optimizer = tf.train.GradientDescentOptimizer(learning_rate=learn_rate) # 梯度下降算法
   train_step = optimizer.minimize(cost) # 最小化代價函數
   init = tf.global_variables_initializer() # 使用變量全局初始化選項
train_curve = [] # 定義列表存儲學習曲線
with tf.Session(graph=temp_graph) as sess:
   sess.run(init) # 變量初始化
   for i in range(epoch):
       sess.run(train_step, feed_dict={X: train_X, Y: train_Y}) # 運行“最小化代價函數”
       temp_cost = sess.run(cost, feed_dict={X: train_X, Y: train_Y}) # 代價函數
       train_curve.append(temp_cost) # 學習曲線
   kt_k = sess.run(k); kt_b = sess.run(b) # 運行“模型參數”
   Y_pred = sess.run(linear_model, feed_dict={X: train_X}) # 運行“模型”得到學習結果
# 繪製學習結果
ax1 = plt.subplot(1, 2, 1); ax1.set_title('Linear model fit');
ax1.plot(train_X, train_Y, 'b.'); ax1.plot(train_X, Y_pred, 'r-')
ax2 = plt.subplot(1, 2, 2); ax2.set_title('Training curve');
ax2.plot(train_curve, 'r--')
保存和恢復
TensorFlow的低階API可以保存模型和學習得到的變量,對其進行恢復後可以無需初始化直接使用。對張量的保存和恢復使用tf.train.Saver [26-27]  。裏提供一個應用於變量的例子:
import tensorflow as tf
# 保存變量
var = tf.get_variable("var_name", [5], initializer = tf.zeros_initializer) # 定義
saver = tf.train.Saver({"var_name": var}) # 不指定變量字典時保存所有變量
with tf.Session() as sess:
   var.initializer.run() # 變量初始化
   # 在當前路徑保存變量
   saver.save(sess, "./model.ckpt")
# 讀取變量
tf.reset_default_graph() # 清空所有變量
var = tf.get_variable("var_name", [5], initializer = tf.zeros_initializer)
saver = tf.train.Saver({"var_name": var}) # 使用相同的變量名
with tf.Session() as sess:
   # 讀取變量(無需初始化)
   saver.restore(sess, "./model.ckpt")
使用檢查點工具tf.python.tools.inspect_checkpoint可以查看文件中保存的張量,這裏提供一個例子 [27] 
from tensorflow.python.tools import inspect_checkpoint as chkp
# 顯示所有張量(指定tensor_name=''可檢索特定張量)
chkp.print_tensors_in_checkpoint_file("./model.ckpt", tensor_name='', all_tensors=True)
TensorFlow保存的模型使用SavedModel文件包,該文件包含是一種獨立於語言(language-neutral)且可恢復的序列化格式,使較高級別的系統和工具可以創建、使用和轉換 TensorFlow模型為SavedModel [27]  。tf.saved_model API可以直接與SavedModel進行交互,tf.saved_model.simple_save用於保存模型,tf.saved_model.loader.load用於導入模型 [28]  。其一般用法如下:
from tensorflow.python.saved_model import tag_constants
export_dir = '' # 定義保存路徑
# ...(略去)定義圖...
with tf.Session(graph=tf.Graph()) as sess:
   # ...(略去)運行圖...
   # 保存圖
   tf.saved_model.simple_save(sess, export_dir, inputs={"x": x, "y": y}, outputs={"z": z})
   tf.saved_model.loader.load(sess, [tag_constants.TRAINING], export_dir) # tag默認為SERVING
上述保存方法適用於大部分圖和會話,但具體地,用户也可使用構建器(builder API)手動構建SavedModel。

TensorFlow高階API

Estimators
Estimators是TensorFlow自帶的高階神經網絡API [29]  。Estimators封裝了神經網絡的訓練、評估、預測、導出等操作。Estimators的特點是具有完整的可移植性,即同一個模型可以在各類終端、服務中運行並使用GPU或TPU加速而無需重新編碼 [29]  。Estimators模型提供分佈式訓練循環,包括構建圖、初始化變量、加載數據、處理異常、創建檢查點(checkpoint)並從故障中恢復、保存TensorBoard的摘要等。Estimators包含了預創建模型,其工作流程如下 [29] 
  • 建立數據集導入函數:可以使用TensorFlow的數據導入工具tf.data.Dataset或從NumPy數組創建數據集導入函數。
  • 定義特徵列:特徵列(tf.feature_column)包含了訓練數據的特徵名稱、特徵類型和輸入預處理操作。
  • 調出預創建的Estimator模型:可用的模型包括基礎統計學(baseline)、梯度提升決策樹(boosting desicion tree)和深度神經網絡的迴歸、分類器。調出模型後需提供輸入特徵列、檢查點路徑和有關模型參數(例如神經網絡的隱含層結構)。
  • 訓練和評估模型:所有預創建模型都包含train和evaluate接口用於學習和評估。
這裏提供一個使用Estimator預創建的深度神經網絡分類器對MNIST數據進行學習的例子:
import numpy as np
import tensorflow as tf
from tensorflow import keras
# 讀取google fashion圖像分類數據
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
# 轉化像素值為浮點數
train_images = train_images / 255.0
test_images = test_images / 255.0
# 使用NumPy數組構建數據集導入函數
train_input_fn = tf.estimator.inputs.numpy_input_fn(
   x={"pixels": train_images}, y=train_labels.astype(np.int32), shuffle=True)
test_input_fn = tf.estimator.inputs.numpy_input_fn(
   x={"pixels": test_images}, y=test_labels.astype(np.int32), shuffle=False)
# 定義特徵列(numeric_column為數值型)
feature_columns = [tf.feature_column.numeric_column("pixels", shape=[28, 28])]
# 定義深度學習神經網絡分類器,新建文件夾estimator_test保存檢查點
classifier = tf.estimator.DNNClassifier(
    feature_columns=feature_columns, hidden_units=[128, 128], 
    optimizer=tf.train.AdamOptimizer(1e-4), n_classes=10, model_dir = './estimator_test')
classifier.train(input_fn=train_input_fn, steps=20000) # 學習
model_eval = classifier.evaluate(input_fn=test_input_fn) # 評估
Estimator提供“層函數(tf.layer) [30]  ”和其它有關工具以支持用户自定義新模型,這些工具也被視為“中層API”。由於自定義完整模型過程繁瑣,因此可首先使用預構建模型並完成一次訓練循環,在分析結果之後嘗試自定義模型 [31]  。這裏提供一個自定義神經網絡分類器的例子:
# 導入模塊和數據集的步驟與前一程序示例相同
def my_model(features, labels, mode, params):
   # 仿DNNClassifier構建的自定義分類器
   # 定義輸入層-隱含層-輸出層
   net = tf.feature_column.input_layer(features, params['feature_columns'])
   for units in params['hidden_units']:
       net = tf.layers.dense(net, units=units, activation=tf.nn.relu)
   logits = tf.layers.dense(net, params['n_classes'], activation=None)
   # argmax函數轉化輸出結果
   predicted_classes = tf.argmax(logits, 1)
   # (學習完畢後的)預測模式
   if mode == tf.estimator.ModeKeys.PREDICT:
       predictions = {'class_ids': predicted_classes[:, tf.newaxis]}
       return tf.estimator.EstimatorSpec(mode, predictions=predictions)
   # 定義損失函數
   loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)
   # 計算評估指標(以分類精度為例)
   accuracy = tf.metrics.accuracy(labels=labels, predictions=predicted_classes, name='acc_op')
   metrics = {'accuracy': accuracy}
   tf.summary.scalar('accuracy', accuracy[1])
   if mode == tf.estimator.ModeKeys.EVAL:
       # 評估模式
       return tf.estimator.EstimatorSpec(mode, loss=loss, eval_metric_ops=metrics)
   else:
       # 學習模式
       assert mode == tf.estimator.ModeKeys.TRAIN
       optimizer = tf.train.AdagradOptimizer(learning_rate=0.1) # 定義優化器
       train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step()) # 優化損失函數
       return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)
# 調用自定義模型,使用前一程序示例中的 1.構建數據集導入函數 和 2. 特徵列
classifier = tf.estimator.Estimator(model_fn=my_model, params={
   'feature_columns': feature_columns,
   'hidden_units': [64, 64],
   'n_classes': 10})
# 學習(後續的評估/預測步驟與先前相同)
classifier.train(input_fn=train_input_fn, steps=20000)
Estimators的模型參數無需另外保存,在使用模型時提供檢查點的路徑即可調出上次學習獲得的參數重新初始化模型 [32]  。Estimators也支持用户自定義檢查點規則。這裏提供一個例子 [32] 
# 每20分鐘保存一次檢查點/保留最新的10個檢查點
my_checkpoint = tf.estimator.RunConfig(save_checkpoints_secs = 20*60, keep_checkpoint_max = 10)
# 使用新的檢查點規則重新編譯先前模型(保持模型結構不變)
classifier = tf.estimator.DNNClassifier(
    feature_columns=feature_columns, hidden_units=[128, 128], 
    model_dir = './estimator_test', config=my_checkpoint)
除使用檢查點作為對模型進行自動保存的工具外,用户也可使用低階API將模型保存至SavedModel文件。
Keras是一個支持TensorFlow、Thenao和Microsoft-CNTK的第三方高階神經網絡API [33]  。Keras以TensorFlow的Python API為基礎提供了神經網絡、尤其是深度網絡的構築模塊,並將神經網絡開發、訓練、測試的各項操作進行封裝以提升可擴展性和簡化使用難度 [33]  。在TensorFlow下可以直接導出Keras模塊使用 [34]  。這裏提供一個使用tensorflow.keras構建深度神經網絡分類器對MNIST數據進行學習的例子:
import tensorflow as tf
from tensorflow import keras
# 讀取google fashion圖像分類數據
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
# 轉化像素值為浮點數
train_images = train_images / 255.0
test_images = test_images / 255.0
# 構建輸入層-隱含層-輸出層
model = keras.Sequential([
   keras.layers.Flatten(input_shape=(28, 28)),
   keras.layers.Dense(128, activation=tf.nn.relu),
   keras.layers.Dense(10, activation=tf.nn.softmax)
])
# 設定優化算法、損失函數
model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.001),
                       loss='sparse_categorical_crossentropy',
                       metrics=['accuracy'])
# 開始學習(epochs=5)
model.fit(train_images, train_labels, epochs=5)
# 模型評估
test_loss, test_acc = model.evaluate(test_images, test_labels)
print('Test accuracy:', test_acc)
# 預測
predictions = model.predict(test_images)
# 保存模式和模式參數
model.save_weights('./keras_test') # 在當前路徑新建文件夾
model.save('my_model.h5')
Keras可以將模型導入Estimators以利用其完善的分佈式訓練循環,對上述例子,導入方式如下:
# 從文件恢復模型和學習參數
model = keras.models.load_model('my_model.h5')
model.load_weights('./keras_test')
# 新建文件夾存放Estimtor檢查點
est_model = tf.keras.estimator.model_to_estimator(keras_model=model, model_dir='./estimtor_test')
使用tensorflow.keras可以運行所有兼容Keras的代碼而不損失速度,但在Python的模塊管理工具中,tensorflow.keras的最新版本可能落後於Keras的官方版本 [34]  。tensorflow.keras使用HDF5文件保存神經網絡的權重係數 [34] 
Eager Execution
Eager Execution是基於TensorFlow Python API的命令式編程環境,幫助用户跳過數據流編程的圖操作,直接獲取結果,便於TensorFlow的入門學習和模型調試,在機器學習應用中可以用於快速迭代小模型和小型數據集 [35]  。Eager Execution環境只能在程序的開始,即導入tensorflow模塊時啓用 [35]  :
import tensorflow as tf
tf.enable_eager_execution()
Eager Execution使用Python控制流,支持標準的Python調試工具,狀態對象的生命週期也由其對應的Python對象的生命週期,而不是tf.Session決定 [35]  。Eager Execution支持大多數TensorFlow操作和GPU加速,但可能會使某些操作的開銷增加 [35] 
Data
TensorFlow輸入管道的設備佔用策略 TensorFlow輸入管道的設備佔用策略 [36]
tf.data是TensorFlow中進行數據管理的高階API [37]  。在圖像處理問題中,tf.data可以對輸入圖像進行組合或疊加隨機擾動,增大神經網絡的訓練收益;在文字處理問題中,tf.data負責字符提取和嵌入(embedding),後者將文字轉化為高維向量,是進行機器學習的重要步驟 [38]  。tf.data包含兩個類:tf.data.Dataset和tf.data.Iterator,Dataset自身是一系列由張量構成的組元,幷包含緩存(cache)、交錯讀取(interleave)、預讀取(prefetch)、洗牌(shuffle)、投影(map)、重複(repeat)等數據預處理方法、Iterator類似於Python的循環器,是從Dataset中提取組元的有效方式 [39]  。tf.data支持從NumPy數組和TFRecord中導入數據,在字符數據處理時時,tf.data.TextLineDataset可以直接輸入ASCII編碼文件 [37]  [40] 
tf.data可用於構建和優化大規機器學習的輸入管道(input pipline),提升TensorFlow性能。一個典型的輸入管道包含三個部分 [36] 
  • 提取(Extract):從本地或雲端的數據存儲點讀取原始數據
  • 轉化(Transform):使用計算設備(通常為CPU)對數據進行解析和後處理,例如解壓縮、洗牌(shuffling)、打包(batching)等
  • 加載(Load):在運行機器學習算法的高性能計算設備(GPU和TPU)加載經過後處理的數據
在本地的同步操作下,當GPU/TPU進行算法迭代時,CPU處於閒置狀態,而當CPU分發數據時,GPU/TPU處於閒置狀態。tf.data.Dataset.prefetch在轉化和加載數據時提供了預讀取技術,可以實現輸入管道下算法迭代和數據分發同時進行,在當前學習迭代完成時能更快地提供下一個迭代的輸入數據。tf.data.Dataset.prefetch的buffer_size參數通常為預讀取值的個數 [36] 
tf.data支持輸入管道的並行,tf.contrib.data.parallel_interleave可以並行提取數據 [41]  ;映射函數tf.data.Dataset.map能夠並行處理用户的指定操作 [42]  。對於跨CPU並行,用户可以通過num_parallel_calls接口指定並行操作的等級。一般而言,並行等級與設備的CPU核心數相同,即在四核處理器上可定義num_parallel_calls=4 [36]  。在大數據問題中,可使用tf.contrib.data.map_and_batch並行處理用户操作和分批操作 [43]  。這裏提供一個構建和優化輸入管道的例子:
import tensorflow as tf
# 使用FLAG統一管理輸入管道參數
FLAGS = tf.app.flags.FLAGS
tf.app.flags.DEFINE_integer('num_parallel_readers', 0, 'doc info')
tf.app.flags.DEFINE_integer('shuffle_buffer_size', 0, 'doc info')
tf.app.flags.DEFINE_integer('batch_size', 0, 'doc info')
tf.app.flags.DEFINE_integer('num_parallel_calls', 0, 'doc info')
tf.app.flags.DEFINE_integer('prefetch_buffer_size', 0, 'doc info')
# 自定義操作(map)
def map_fn(example):
   # 定義數據格式(圖像、分類標籤)
   example_fmt = {"image": tf.FixedLenFeature((), tf.string, ""),
                  "label": tf.FixedLenFeature((), tf.int64, -1)}
   # 按格式解析數據
   parsed = tf.parse_single_example(example, example_fmt)
   image = tf.image.decode_image(parsed["image"]) # 圖像解碼操作
   return image, parsed["label"]
# 輸入函數
def input_fn(argv):
   # 列出路徑的所有TFRData文件(修改路徑後)
   files = tf.data.Dataset.list_files("/path/TFRData*")
   # 並行交叉讀取數據
   dataset = files.apply(
      tf.contrib.data.parallel_interleave(
         tf.data.TFRecordDataset, cycle_length=FLAGS.num_parallel_readers))
   dataset = dataset.shuffle(buffer_size=FLAGS.shuffle_buffer_size) # 數據洗牌
   # map和batch的並行操作
   dataset = dataset.apply(
       tf.contrib.data.map_and_batch(map_func=map_fn,
                                     batch_size=FLAGS.batch_size,
                                     num_parallel_calls=FLAGS.num_parallel_calls))
   dataset = dataset.prefetch(buffer_size=FLAGS.prefetch_buffer_size) # 數據預讀取設置
   return dataset
# argv的第一個字符串為説明
tf.app.run(input_fn, argv=['pipline_params',
                       '--num_parallel_readers', '2',
                       '--shuffle_buffer_size', '50',
                       '--batch_size', '50',
                       '--num_parallel_calls, 4'
                       '--prefetch_buffer_size', '50'])
在輸入管道的各項操作中,交叉讀取、 預讀取和洗牌能降低內存佔用,因此具有高優先級。數據的洗牌應在重複操作前完成,為此可使用兩者的組合方法tf.contrib.data.shuffle_and_repeat [36]  [44] 

TensorFlow加速器

CPU和GPU設備
TensorFlow支持CPU和GPU運行,在程序中設備使用字符串進行表示。CPU表示為"/cpu:0";第一個GPU表示為"/device:GPU:0";第二個GPU表示為"/device:GPU:1",以此類推 [45]  。如果TensorFlow指令中兼有CPU和GPU實現,當該指令分配到設備時,GPU設備有優先權。TensorFlow僅使用計算能力高於3.5的GPU設備 [11] 
在啓用會話時打開log_device_placement配置選項,可以在終端查看會話中所有操作和張量所分配的設備,這裏提供一個例子:
# 構建數據流圖.
a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')
b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')
c = tf.matmul(a, b)
# 啓用會話並設定log_device_placement=True.
with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess:
   print(sess.run(c))
# 終端中可見信息:MatMul: (MatMul): /job:localhost/replica:0/task:0/device:CPU:0…
默認地,TensorFlow會盡可能地使用GPU內存,最理想的情況是進程只分配可用內存的一個子集,或者僅根據進程需要增加內存使用量,為此,啓用會話時可通過兩個編譯選項來進行GPU進程管理 [45-46] 
  • 內存動態分配選項allow_growth可以根據需要分配GPU內存,該選項在開啓時會少量分配內存,並隨着會話的運行對佔用內存區域進行擴展。TensorFlow會話默認不釋放內存,以避免內存碎片問題。
  • per_process_gpu_memory_fraction 選項決定每個進程所允許的GPU內存最大比例。
這裏提供一個在會話中編譯GPU進程選項的例子 [45] 
config = tf.ConfigProto()
config.gpu_options.allow_growth = True # 開啓GPU內存動態分配
config.gpu_options.per_process_gpu_memory_fraction = 0.4 # 內存最大佔用比例為40%
with tf.Session(config=config) as sess:
   # ...(略去)會話內容 ...
TPU設備
張量處理器(Tensor Processing Unit, TPU)是谷歌為TensorFlow定製的專用芯片。TPU部署於谷歌的雲計算平台,並作為機器學習產品開放研究和商業使用 [47]  。TensorFlow的神經網絡API Estimator擁有支持TPU下可運行的版本TPUEstimator [48]  。TPUEstimator可以在本地進行學習/調試,並上傳谷歌雲計算平台進行計算。
使用雲計算TPU設備需要快速向TPU供給數據,為此可使用tf.data.Dataset API從谷歌雲存儲分區中構建輸入管道。小數據集可使用tf.data.Dataset.cache完全加載到內存中 [42]  ,大數據可轉化為TFRecord格式並使用tf.data.TFRecordDataset進行讀取 [36] 
設備管理(tf.device)
TensorFlow使用tf.device對設備進行管理,tf.device的設備規範具有以下形式 [23] 
/job:<JOB_NAME>/task:<TASK_INDEX>/device:<DEVICE_TYPE>:<DEVICE_INDEX>
其中<JOB_NAME> 是一個字母數字字符串,並且不以數字開頭。<DEVICE_TYPE> 是一種註冊設備類型(例如 GPU 或 CPU)。<TASK_INDEX> 是一個非負整數,表示名為 <JOB_NAME> 的作業中的任務的索引。<DEVICE_INDEX> 是一個非負整數,表示設備索引,例如用於區分同一進程中使用的不同GPU設備 [10]  [23] 
定義變量時可以使用tf.device指定設備名稱 [49]  ,tf.train.replica_device_setter可以對變量的設備進行自動分配,這裏提供一個在不同設備定義變量和操作的例子 [50] 
# 手動分配
with tf.device("/device:GPU:1"):
 var = tf.get_variable("var", [1])
# 自動分配
cluster_spec = {
   "ps": ["ps0:2222", "ps1:2222"],
   "worker": ["worker0:2222", "worker1:2222", "worker2:2222"]}
with tf.device(tf.train.replica_device_setter(cluster=cluster_spec)):
 v = tf.get_variable("var", shape=[20, 20])
根據tf.device對變量的分配,在單一GPU的系統中,與變量有關的操作會被固定到CPU或GPU上;在多GPU的系統中,操作會在偏好設備(或多個設備同時)運行 [45]  。多GPU並行處理圖的節點能加快會話的運行,這裏提供一個例子:
c = [] # 在GPU:1和GPU:2定義張量 (運行該例子要求系統存在對應GPU設備)
for d in ['/device:GPU:1', '/device:GPU:2']:
   with tf.device(d):
       a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3])
       b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2])
       c.append(tf.matmul(a, b))
# 在CPU定義相加運算
with tf.device('/cpu:0'):
   my_sum = tf.add_n(c)
# 啓用會話
with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess:
   print(sess.run(my_sum))

TensorFlow優化器

模型優化工具
Tensorflow提供了模型優化工具(Model Optimization Toolkit)對模型的尺度、響應時間和計算開銷進行優化 [51]  。模型優化工具可以減少模型參數的使用量(pruning)、對模型精度進行量化(quantization)和改進模型的拓撲結構,適用於將模型部署到終端設備,或在有硬件侷限時運行模型,因此有很多優化方案是TensorFlow Lite項目的一部分。其中量化能夠在最小化精度損失的情況下顯著減小模型尺度和縮短響應時間,並是優化深度學習模型的重要手段。這裏提供一個使用使用模型優化工具的例子 [52] 
import tensorflow as tf
converter = tf.contrib.lite.TocoConverter.from_saved_model(path) # 從路徑導入模型
converter.post_training_quantize = True # 開啓學習後量化
tflite_quantized_model = converter.convert() # 輸出量化後的模型
open("quantized_model.tflite", "wb").write(tflite_quantized_model) # 寫入新文件
XLA
XLA工作流程 XLA工作流程 [53]
線性代數加速器(Accelerated Linear Algebra, XLA)是一個特殊的編譯器,用於優化TensorFlow中的線性代數計算,其目標是優化內存使用,提升TensorFlow的運行速度和跨平台,尤其是移動終端的可移植性 [53] 
XLA工作的前端輸入為“高層優化器(High Level Optimizer, HLO)”定義的數據流圖,隨後XLA使用多種獨立於計算設備的算法優化方案對圖進行分析,並將HLO計算送入後端。後端會進一步進行基於特定設備,例如GPU的優化 [53]  。截至TensorFlow的1.12版本,XLA依然處於早期開發狀態,暫不能提供顯著的性能優化,其硬件支持包括JITAOT編譯的x86-64 CPU、NVIDIA GPU [53] 

TensorFlow可視化工具

TensorFlow擁有自帶的可視化工具TensorBoard,TensorBoard具有展示數據流圖、繪製分析圖、顯示附加數據等功能 [54]  。開源安裝的TensorFlow會自行配置TensorBoard。啓動TensorBoard前需要建立模型檔案,低階API使用tf.summary構建檔案,Keras包含callback方法、Estimator會自行建立檔案。這裏提供兩個例子:
# 為低層API構建檔案
my_graph = tf.Graph()
with my_graph.as_default():
   # 構建數據流圖
with tf.Session(graph=my_graph) as sess:
   # 會話操作   
    file_writer = tf.summary.FileWriter('/user_log_path', sess.graph) # 輸出文件
# 為Keras模型構建檔案
import tensorflow.keras as keras
tensorboard = keras.callbacks.TensorBoard(log_dir='./logs')
# … (略去)用户自定義模型 ...
model.fit(callbacks=[tensorboard]) # 調用fit時加載callback
檔案建立完畢後在終端可依據檔案路徑運行TensorBoard主程序:
tensorboard --logdir=/user_log_path
當終端顯示TensorBoard 1.12.0 at http://your_pc_name:6006 (Press CTRL+C to quit)時,跳轉至localhost:6006可使用TensorFlow界面。

TensorFlow調試程序

由於通用調試程序,例如Python的pdb很難對TensorFlow代碼進行調試,因此TensorFlow團隊開發了專用的調試模塊TFDBG,該模塊可以在學習和預測時查看會話中數據流圖的內部結構和狀態 [55]  。TFDBG在運行時期間會攔截指令生成的錯誤,並向用户顯示錯誤信息和調試説明。TFDBG使用文本交互系統curses,在不支持curses的Windows操作系統,可以下載非官方的Windows curses軟件包或使用readline作為代替。使用TFDBG調試會話時,可以直接將會話進行封裝,具體有如下例子 [55] 
from tensorflow.python import debug as tf_debug
with tf.Session() as sess:
   sess = tf_debug.LocalCLIDebugWrapperSession(sess)
   print(sess.run(c))
封裝容器與會話具有相同界面,因此調試時無需修改代碼。封裝容器在會話開始時調出命令行界面(Command Line Interface, CLI),CLI包含超過60條指令,用户可以在使用指令控制會話、檢查數據流圖、打印及保存張量 [55] 
TFDBG可以調試神經網絡API Estimator和Keras,對Estimator,TFDBG創建調試掛鈎(LocalCLIDebugHook)作為Estimator中的fit和evaluate方法下monitor的參數。對Keras,TFDBG提供Keras後端會話的封裝對象,這裏提供一些調試例子 [55] 
# 調試Estimator
Import tensorflow as tf
from tensorflow.python import debug as tf_debug
hooks = [tf_debug.LocalCLIDebugHook()] # 創建調試掛鈎
# classifier = tf.estimator. … 調用Estimator模型
classifier.fit(x, y, steps, monitors=hooks) # 調試fit
classifier.evaluate(x, y, hooks=hooks) # 調試evaluate
# 調試Keras
from keras import backend as keras_backend
# 在程序開始時打開後端會話封裝
keras_backend.set_session(tf_debug.LocalCLIDebugWrapperSession(tf.Session()))
# 構建Keras模型
model.fit(...)  # 使用模型學習時進入調試界面(CLI)
TFDBG支持遠程和離線會話調試,可應用於在沒有終端訪問權限的遠程機器(例如雲計算)運行Tensorflow的場合。除CLI外,TFDBG在TensorBoard擁有擁有圖形界面的調試程序插件,該插件提供了計算圖檢查、張量實時可視化、張量連續性和條件性斷點以及將張量關聯到圖源代碼等功能 [55] 

TensorFlow部署

TensorFlow支持在一個或多個系統下使用多個設備並部署分佈式服務器(distributed server)和服務器集羣(cluster)。tf.train.Server.create_local_server可在本地構建簡單的分佈式服務器 [56]  。這裏提供一個例子 [57] 
import tensorflow as tf
c = tf.constant("Hello, distributed TensorFlow!")
# 建立服務器
server = tf.train.Server.create_local_server()
# 在服務器運行會話
with tf.Session(server.target) as sess  
   sess.run(c)
TensorFlow服務器集羣是分佈運行的數據流圖中的“任務(task)”集合,每個任務都會被分配至一個TensorFlow服務,其中包含一個“主幹(master)”以啓動會話和一個“工作點(worker)”執行圖的操作。服務器集羣可以被分割為“工作(job)”,每個工作包含一或多個任務 [57] 
部署服務器集羣時,通常每個任務分配一台機器,但也可在一台機器的不同設備運行多個任務。每個任務都包含tf.train.ClusterSpec方法以描述該服務器集羣的全部任務(每個任務的ClusterSpec是相同的)和tf.train.Server方法按工作名提取本地任務。tf.train.ClusterSpec要求輸入一個包含所有工作名和地址的字典;而tf.train.Server對象包含一系列本地設備、與tf.train.ClusterSpec中其它任務的鏈接和一個使用鏈接進行分佈式計算的會話 [57]  。每個任務都是一個特定工作名的成員,並有一個任務編號(task index)。任務可以通過編號與其它任務相聯繫。這裏提供一個部署兩個任務於兩台服務器的例子 [57] 
# 假設有局域網內服務器localhost:2222和localhost:2223
# 在第一台機器建立任務
cluster = tf.train.ClusterSpec({"local": ["localhost:2222", "localhost:2223"]})
server = tf.train.Server(cluster, job_name="local", task_index=0)
# 在第二台機器建立任務
cluster = tf.train.ClusterSpec({"local": ["localhost:2222", "localhost:2223"]})
server = tf.train.Server(cluster, job_name="local", task_index=1)
分佈式TensorFlow支持亞馬遜簡易存儲服務(Amazon Simple Storage Service, S3) [58]  和開源的Hadoop分佈式文件系統(Hadoop Distributed File System, HDFS) [59] 

TensorFlow安全性

TensorFlow的模型文件是代碼,在執行數據流圖計算時可能的操作包括讀寫文件、從網絡發送和接收數據、生成子進程,這些過程對系統會造成影響 [60]  。在運行由未知第三方提供的TensorFlow模型、 計算流圖(GraphDef和SavedModel)和檢查點文件時,一個推薦的做法是使用沙盒(sand box)以監測其行為 [60]  。安全的TensorFlow模型在引入未知輸入數據時,也可能觸發TensorFlow內部或系統的錯誤。
TensorFlow的分佈式計算平台和服務器接口(tf.train.Server)不包含授權協議和信息加密選項,任何具有網絡權限的訪問者都可以運行tf.train.Server上的任何代碼,因此TensorFlow不適用於不信任的網絡。在局域網或雲計算平台部署TensorFlow計算集羣時,需要為其配備獨立網絡(isolated networks) [60] 
TensorFlow作為一個使用大量第三方庫(NumPy、libjpeg-turbo等)的複雜系統,容易出現漏洞。用户可以使用電子郵件向TensorFlow團隊報告漏洞和可疑行為,對於高度敏感的漏洞,其GitHub頁面提供了郵件的SSH密鑰 [60]  。以下列出截至2018年7月12日的已知漏洞 [61] 
編號
內容
版本
報告方
TFSA-2018-006
惡意構造編譯文件引起非法內存訪問
1.7及以下
Tencent Blade Team
TFSA-2018-005
(原文)“Old Snappy Library Usage Resulting in Memcpy Parameter Overlap
1.7及以下
Tencent Blade Team
TFSA-2018-004
檢查點源文件越界讀取
1.7及以下
Tencent Blade Team
TFSA-2018-003
TensorFlow Lite TOCO FlatBuffer庫解析漏洞
1.7及以下
Tencent Blade Team
TFSA-2018-002
(原文)“GIF File Parsing Null Pointer Dereference Error
1.5及以下
Tencent Blade Team
TFSA-2018-001
BMP文件解析越界讀取
1.6及以下
Tencent Blade Team

TensorFlow生態系統

TensorFlow社區

TensorFlow位於GitHub的三個代碼庫負責處理事件和提供技術支持,一般性的求助也可發送至StackOverflow的TensorFlow板塊 [62]  。TensorFlow使用公共郵箱發佈主要版本和重要公告 [63]  ,其官方網站的“路線圖”頁面彙總了其近期的開發計劃 [64]  。TensorFlow團隊擁有推特賬户和博客以發佈項目的新聞和動態。TensorFlow的YouTube頻道介紹了TensorFlow在機器學習和人工智能領域的應用,並定期推送節目,包括“TensorFlow Meets”、“Ask TensorFlow”和“Coding TensorFlow” [65] 

TensorFlow項目

TensorFlow Hub
TensorFlow Hub是一個允許用户發佈、共享和使用TensorFlow模塊的庫開發項目。用户可以將TensorFlow數據流圖或其部分使用Hub進行封裝並移植到其它問題中再次利用 [66]  。TensorFlow Hub頁面列出了由谷歌和DeepMind提供的封裝模型,其主題包括字符嵌入、視頻分類和圖像處理 [67] 
TensorFlow Extended (TFX)
TFX是谷歌基於TensorFlow開發的產品級機器學習平台,其目標是是對產品開發中的模型實現、分析驗證和業務化操作進行整合,在實時數據下完成機器學習產品的標準化生產 [68]  。TFX包含三個算法庫:TensorFlow Data Validation對機器學習數據進行統計描述和驗證、TensorFlow Transform對模型數據進行預處理、TensorFlow Model Analysis對機器學習模型進行分析,提供表現評分。另有TensorFlow Serving作為模型業務化的高性能系統,提供模型接口和管理 [69] 
TensorFlow Probability (TFP)
TFP是在TensorFlow Python API基礎上開發的統計學算法庫,其目標是方便用户將概率模型和深度學習模型相結合使用 [70]  。TFP包含大量概率分佈的生成器、支持構建深度網絡的概率層(probabilistic layers)、提供變分貝葉斯推斷(Variational inference)和馬爾可夫鏈蒙特卡羅方法(Markov chain Monte Carlo)和一些特殊的優化器,包括Nelder-Mead方案、BFGS算法(Broyden-Fletcher-Goldfarb-Shanno algorithm)和SGLD(Stochastic Gradient Langevin Dynamics) [70] 

TensorFlow應用開發

TensorFlow.js
TensorFlow.js是TensorFlow的JavaScript API,主要用於網頁端的機器學習應用開發。TensorFlow.js可以在瀏覽器和Node.js下轉化和運行TensorFlow構建的機器學習模型,並使用網頁端數據對模型進行訓練 [71]  。截至2018年9月18日,TensorFlow.js的版本號為0.13 [72] 
TensorFlow Lite
TensorFlow Lite是為移動和嵌入式設備運行機器學習代碼的問題提供解決方案。TensorFlow Lite包含優化算法以提升Android、iOS等系統下機器學習模型的響應時間並降低文件大小。谷歌內部的許多移動端產品,包括谷歌相冊、谷歌郵箱客户端、谷歌鍵盤等都使用TensorFlow Lite部署了人工智能算法 [73] 
Swift for TensorFlow
Swift for TensorFlow是開源版Swift的TensorFlow API開發項目。Swift for TensorFlow類似於Eager Execution可以直接執行數據流圖且性能更高 [74]  。截至10月13日,Swift for TensorFlow處於早期開發狀態。

TensorFlow研究

TensorFlow Research Cloud
谷歌雲計算服務中的TPU計算集羣 谷歌雲計算服務中的TPU計算集羣 [75]
TensorFlow Research Cloud是面向科學研究的機器學習TPU雲計算平台。該項目擁有1000個雲TPU和總計180千萬億次計算力,每個TPU擁有64 GB的高帶寬內存 [75-76]  。TensorFlow Research Cloud項目在2018年2月進入Beta版,可以申請使用,在官方聲明中,其發起目的是“為確保全世界優秀的研究人員擁有足夠的計算資源以規劃、使用和發表下個機器學習浪潮的革命性突破”
(原文) [75] Our goal is to ensure that the most promising researchers in the world have access to enough compute power to imagine, implement, and publish the next wave of ML breakthroughs.
除面向研究的TPU服務外,谷歌也提供商用的Cloud TPU項目以支持企業的Tensorflow開發 [47] 
Magenta
Magenta是在藝術領域使用機器學習的研究項目,該項目使用深度學習網絡和強化學習算法學習生成音樂、繪畫和其它藝術作品,以幫助藝術人員拓展其創作過程 [77]  。Magenta項目的研究成果包括音樂創作工具NSynth和混音工具MusicVAE。
Nucleus
Nucleus是將TensorFlow應用於基因組文件,例如SAM和VCF格式文件的讀寫和分析的庫開發項目 [78]  。Nucleus使用Python和C++進行開發,截至2018年9月已發佈0.2.0版本 [78] 

TensorFlow版本

TensorFlow 2.8.0
2022年2月,TensorFlow 官方發佈了 2.8.0 正式版,提供了更多的 bug 修復和功能改進,還針對漏洞發佈了補丁。TensorFlow 2.8.0 主要功能和改進:
在 tf.lite 中,增加了 TFLite 內置 op 支持以下功能:
tf.raw_ops.Bucketize op 可在 CPU 上操作;
tf.where op 可用於數據類型 tf.int32、tf.uint32、tf.int8、tf.uint8、tf.int64;
tf.random.normal op 用於在 CPU 上輸出數據類型 tf.float32;
tf.random.uniform op 用於在 CPU 上輸出數據類型 tf.float32;
f.random.categorical op 用於在 CPU 上的輸出數據類型 tf.int64。
tensorflow.experimental.tensorrt:
Conversion_params 在 TrtGraphConverterV2 中被棄用,現在可以支持參數 max_workspace_size_bytes、precision_mode、minimum_segment_size、maximum_cached_engines、use_calibration 和 allow_build_at_runtime;
在 TrtGraphConverterV2 中的 .save () 函數中添加了一個名為 save_gpu_specific_engines 的新參數。當為 False 時,.save () 函數不會保存任何已構建的 TRT 引擎;如果為 True(默認),則保留原始行為;
TrtGraphConverterV2 提供了一個名為 .summary () 的新 API。它顯示了每個 TRTEngineOp 及其輸入和輸出的形狀和 dtype,並提供了詳細版本摘要。
tf.tpu.experimental.embedding:
tf.tpu.experimental.embedding.FeatureConfig 增加了一個額外的參數 output_shape,它可以指定特徵輸出激活的形狀;
tf.tpu.experimental.embedding.TPUEmbedding 現在具有與 tf.tpu.experimental.embedding.serving_embedding_lookup 相同的功能,它可以使用任意等級密集和稀疏的張量。對於不規則張量,儘管輸入張量仍然是 2 級,但現在可以通過在特徵配置中指定輸出形狀或通過 build 方法來激活 2 級或更高級別。
添加 tf.config.experimental.enable_op_determinism ,這使得 TensorFlow ops 以性能為代價可以確定性地運行。替換 TF_DETERMINISTIC_OPS 環境變量。
(自 TF 2.7 起)向 TensorFlow Profiler 添加 PluggableDevice 支持。
Bug 修復和其他改進
tf.data:
如果用户未禁用,現在優化 parallel_batch 現在成為默認值,這樣可以並行複製批處理元素;
添加了 TensorSliceDataset,用於識別和處理文件輸入。
tf.lite:
為 Java API 的序列化添加 GPU 委託支持,當 OpenCL 可用時,這將初始化時間提高了 90%;
棄用 Interpreter::SetNumThreads,支持 InterpreterBuilder::SetNumThreads。
tf.keras
tf.random.Generator 用於 keras 初始化和所有的 RNG 代碼;
TextVectorization 增加了額外的 standardize 和 split 模式:standardize="lower" 轉化為小寫字母輸入;standardize="string_punctuation" 刪除所有標點符號;Split ="character" 將對每個 unicode 字符進行拆分。
增加 GPU 實現:
(自 2.7 版本開始) tf.math.segment_mean
(自 2.7 版本開始) tf.math.segment_prod
(自 2.7 版本開始) tf.math.segment_sum
TensorFlow 已在適用於 GPU 和 CPU 的 Windows Subsystem for Linux 2(又名 WSL 2)上得到驗證。
此外,TensorFlow 2.8.0 在安全方面進行了一些修正,包括修正了執行卷積運算時浮點數被 0 除的問題:CVE-2022-21725;修正了 Dequantize 形狀推斷中的整數溢出問題:CVE-2022-21727;修正了 ConcatV2 形狀推斷中的類型混淆問題:CVE-2022-21731 等。 [81] 
參考資料
展開全部 收起