[譯] 系列教程:如何將程式碼遷移至 TensorFlow 1.0

LeviDing發表於2019-01-28

本文出自 掘金翻譯計劃 正在組織翻譯的 TensorFlow 官方文件。如果您有興趣,歡迎 申請成為譯者,學習完譯者教程後,參與到文章和文件的翻譯和及對當中。我們也正在招募 TensorFlow 譯者,歡迎積極參加。


TensorFlow 1.0 中 API 的改動不再完全向後相容。因此,執行於 TensorFlow 0.n 版本的 TensorFlow 應用可能不能在 TensorFlow 1.0 版本中正常執行。在此版本中,我們對 API 進行了一些修改,確保了其內部一致性;在接下來的整個 1.N 版本週期中都不會進行任何斷代式變更。

本指南將引導您瞭解新版 API 的主要變更,以及如何將您的程式自動升級至 TensorFlow 1.0。除了幫助您完成程式的修改之外,本指南也解釋了我們為何要做出這些變更。

如何升級

如果您希望自動將程式碼遷移至 1.0 版本,可以嘗試使用我們的 tf_upgrade.py 指令碼。此指令碼能處理大多數情況,但有時還是需要您進行手動修改。
您可以在我們的 GitHub 中獲取此指令碼。

如要將單個的 0.n 版 TensorFlow 原始檔轉換為 1.0 版本,請輸入如下格式的命令:

$ python tf_upgrade.py --infile InputFile --outfile OutputFile

例如,以下命令會將一個名為 test.py 的 0.n 版 TensorFlow 程式轉換為名為 test_1.0.py 的 1.0 版 TensorFlow 程式:

$ python tf_upgrade.py --infile test.py --outfile test_1.0.py

tf_upgrade.py 指令碼還會生成一個名為 report.txt 的檔案,記錄了其在升級過程中做的所有修改,並給出了一些可能需要您手動修改的建議。

如要將整個目錄的 0.n 版 TensorFlow 程式升級為 1.0 版本,請輸入如下格式的命令:

$ python tf_upgrade.py --intree InputDir --outtree OutputDir

例如,以下命令會將 /home/user/cool 中的所有 0.n 版 TensorFlow 程式轉換為 1.0 版並放入新建的 /home/user/cool_1.0 目錄中:

$ python tf_upgrade.py --intree /home/user/cool --outtree /home/user/cool_1.0

限制

在使用指令碼進行升級時,有幾點注意事項。尤其是:

  • 你需要手動修復所有 tf.reverse() 例項。
    tf_upgrade.py 指令碼也會在螢幕輸出以及 report.txt 檔案中警告您關於 tf.reverse() 的資訊。

  • 如果遇上一些需要重排序的引數,tf_upgrade.py 將會試著最小化地格式化您的程式碼,但不能自動地改變實際的引數順序。因此 tf_upgrade.py 將使用關鍵字引數,讓函式引數與順序無關。

  • tf.get_variable_scope().reuse_variables() 之類的構造器將失效。我們建議刪除它們用以下方法代替:

    with tf.variable_scope(tf.get_variable_scope(), reuse=True):
      ...
    
  • tf.packtf.unpack 類似,我們將 TensorArray.pack 以及 TensorArray.unpack 重新命名為 TensorArray.stackTensorArray.unstack。但是,TensorArray.packTensorArray.unpack 並不直接關聯 tf 名稱空間,因而無法通過詞法直接檢測出來,例如 foo = tf.TensorArray(); foo.unpack()。因此需要手動修改它們。

手動升級您的程式碼

您也可以不使用 tf_upgrade.py,手動升級程式碼。本文件剩餘部分提供了完整的 TensorFlow 1.0 非向後相容變更列表。

變數(Variables)

現在 Variable 函式更具一致性,減少了誤解。

  • tf.VARIABLES
    • 需要重新命名為 tf.GLOBAL_VARIABLES
  • tf.all_variables
    • 需要重新命名為 tf.global_variables
  • tf.initialize_all_variables
    • 需要重新命名為 tf.global_variables_initializer
  • tf.initialize_local_variables
    • 需要重新命名為 tf.local_variables_initializer
  • tf.initialize_variables
    • 需要重新命名為 tf.variables_initializer

聚合函式

現在所有的聚合函式(Summary function)都被統一放置於 tf.summary 名稱空間中。

  • tf.audio_summary
    • 需要重新命名為 tf.summary.audio
  • tf.contrib.deprecated.histogram_summary
    • 需要重新命名為 tf.summary.histogram
  • tf.contrib.deprecated.scalar_summary
    • 需要重新命名為 tf.summary.scalar
  • tf.histogram_summary
    • 需要重新命名為 tf.summary.histogram
  • tf.image_summary
    • 需要重新命名為 tf.summary.image
  • tf.merge_all_summaries
    • 需要重新命名為 tf.summary.merge_all
  • tf.merge_summary
    • 需要重新命名為 tf.summary.merge
  • tf.scalar_summary
    • 需要重新命名為 tf.summary.scalar
  • tf.train.SummaryWriter
    • 需要重新命名為 tf.summary.FileWriter

數值差異

整數除法以及 tf.floordiv 將使用向下取整(floor)語義。這樣就能使 np.dividenp.mod 的結果與 tf.dividetf.mod 的結果保持一致。另外,我們修改了 tf.round 使用的取整演算法,使其與 NumPy 保持一致。

  • tf.div

    • 除法 tf.divide 的語義現在已經修改與 Python 語義保持一致,即 Python 3 中的 / 符號以及 Python 2 future 模組的 division 將始終得到浮點數、// 將進行求整除法。此外,tf.div 將只進行求整除法。如需使用 C 語言強制截斷風格的除法運算,可以使用 tf.truncatediv

    • 請儘量將你的程式碼 tf.div 改為 tf.divide,它將遵循 Python 的語義。

  • tf.mod

    • 求餘 tf.mod 的語義現在已經修改與 Python 語義保持一致。另外,對於整數的運算將使用向下取整(floor)語義。如需使用 C 語言強制截斷風格的求餘運算,可以使用 tf.truncatemod

新版和舊版的除法操作對比總結如下表所示:

表示式 TF 0.11 (py2) TF 0.11 (py3) TF 1.0 (py2) TF 1.0 (py3)
tf.div(3,4) 0 0 0 0
tf.div(-3,4) 0 0 -1 -1
tf.mod(-3,4) -3 -3 1 1
-3/4 0 -0.75 -1 -0.75
-3/4tf.divide(-3,4) N/A N/A -0.75 -1

新版和舊版的取整操作對比總結如下表所示:

輸入 Python NumPy C++ round() TensorFlow 0.11(floor(x+.5)) TensorFlow 1.0
-3.5 -4 -4 -4 -3 -4
-2.5 -2 -2 -3 -2 -2
-1.5 -2 -2 -2 -1 -2
-0.5 0 0 -1 0 0
0.5 0 0 1 1 0
1.5 2 2 2 2 2
2.5 2 2 3 3 2
3.5 4 4 4 4 4

匹配 NumPy 命名

新版本對許多函式進行了重新命名以匹配 NumPy。這麼做旨在使得 NumPy 與 TensorFlow 之間的轉換儘量簡便。雖然我們已經排除了一些常見的不一致情況,但現在還有一些函式未能完全匹配。

  • tf.inv
    • 需要重新命名為 tf.reciprocal
    • 這麼做是為了防止其與 NumPy 的矩陣求逆函式 np.inv 混淆
  • tf.list_diff
    • 需要重新命名為 tf.setdiff1d
  • tf.listdiff
    • 需要重新命名為 tf.setdiff1d
  • tf.mul
    • 需要重新命名為 tf.multiply
  • tf.neg
    • 需要重新命名為 tf.negative
  • tf.select
    • 需要重新命名為 tf.where
    • tf.where 現在與 np.where 一樣,需要傳入 3 個或 1 個引數
  • tf.sub
    • 需要重新命名為 tf.subtract

匹配 NumPy 引數

一些 TensorFlow 1.0 方法的引數現在與 NumPy 的方法相匹配了。為了實現這一點,TensorFlow 1.0 對一些關鍵字引數進行了修改,並對一些引數進行了重排序。需要注意的是,TensorFlow 1.0 現在不再使用 dimension 而轉為使用 axis。TensorFlow 1.0 在修改張量的操作中將保持張量引數始終在第一位。(參見 tf.concat 的改動)。

  • tf.argmax
    • 關鍵字引數 dimension 需要重新命名為 axis
  • tf.argmin
    • 關鍵字引數 dimension 需要重新命名為 axis
  • tf.concat
    • 關鍵字引數 concat_dim 需要重新命名為 axis
    • 輸入引數重排序為 tf.concat(values, axis, name=`concat`).
  • tf.count_nonzero
    • 關鍵字引數 reduction_indices 需要重新命名為 axis
  • tf.expand_dims
    • 關鍵字引數 dim 需要重新命名為 axis
  • tf.reduce_all
    • 關鍵字引數 reduction_indices 需要重新命名為 axis
  • tf.reduce_any
    • 關鍵字引數 reduction_indices 需要重新命名為 axis
  • tf.reduce_join
    • 關鍵字引數 reduction_indices 需要重新命名為 axis
  • tf.reduce_logsumexp
    • 關鍵字引數 reduction_indices 需要重新命名為 axis
  • tf.reduce_max
    • 關鍵字引數 reduction_indices 需要重新命名為 axis
  • tf.reduce_mean
    • 關鍵字引數 reduction_indices 需要重新命名為 axis
  • tf.reduce_min
    • 關鍵字引數 reduction_indices 需要重新命名為 axis
  • tf.reduce_prod
    • 關鍵字引數 reduction_indices 需要重新命名為 axis
  • tf.reduce_sum
    • 關鍵字引數 reduction_indices 需要重新命名為 axis
  • tf.reverse
    • tf.reverse 之前需要傳入 1 維 bool 型張量用以控制維度的順序調換,現在使用一組軸的索引進行控制。
    • 例如 tf.reverse(a, [True, False, True]) 現在需改為 tf.reverse(a, [0, 2])
  • tf.reverse_sequence
    • 關鍵字引數 batch_dim 需要重新命名為 batch_axis
    • 關鍵字引數 seq_dim 需要重新命名為 seq_axis
  • tf.sparse_concat
    • 關鍵字引數 concat_dim 需要重新命名為 axis
  • tf.sparse_reduce_sum
    • 關鍵字引數 reduction_axes 需要重新命名為 axis
  • tf.sparse_reduce_sum_sparse
    • 關鍵字引數 reduction_axes 需要重新命名為 axis
  • tf.sparse_split
    • 關鍵字引數 split_dim 需要重新命名為 axis
    • 輸入引數重排序為 tf.sparse_split(keyword_required=KeywordRequired(), sp_input=None, num_split=None, axis=None, name=None, split_dim=None).
  • tf.split
    • 關鍵字引數 split_dim 需要重新命名為 axis
    • 關鍵字引數 num_split 需要重新命名為 num_or_size_splits
    • 輸入引數重排序為 tf.split(value, num_or_size_splits, axis=0, num=None, name=`split`).
  • tf.squeeze
    • 關鍵字引數 squeeze_dims 需要重新命名為 axis
  • tf.svd
    • 輸入引數重排序為 tf.svd(tensor, full_matrices=False, compute_uv=True, name=None).

簡化數學變換

批量版數學運算操作已被移除。現在非批量版的函式已經包含了批量運算的功能。例如,tf.complex_abs 的功能已遷移至 tf.abs

  • tf.batch_band_part
    • 需要重新命名為 tf.band_part
  • tf.batch_cholesky
    • 需要重新命名為 tf.cholesky
  • tf.batch_cholesky_solve
    • 需要重新命名為 tf.cholesky_solve
  • tf.batch_fft
    • 需要重新命名為 tf.fft
  • tf.batch_fft3d
    • 需要重新命名為 tf.fft3d
  • tf.batch_ifft
    • 需要重新命名為 tf.ifft
  • tf.batch_ifft2d
    • 需要重新命名為 tf.ifft2d
  • tf.batch_ifft3d
    • 需要重新命名為 tf.ifft3d
  • tf.batch_matmul
    • 需要重新命名為 tf.matmul
  • tf.batch_matrix_determinant
    • 需要重新命名為 tf.matrix_determinant
  • tf.batch_matrix_diag
    • 需要重新命名為 tf.matrix_diag
  • tf.batch_matrix_inverse
    • 需要重新命名為 tf.matrix_inverse
  • tf.batch_matrix_solve
    • 需要重新命名為 tf.matrix_solve
  • tf.batch_matrix_solve_ls
    • 需要重新命名為 tf.matrix_solve_ls
  • tf.batch_matrix_transpose
    • 需要重新命名為 tf.matrix_transpose
  • tf.batch_matrix_triangular_solve
    • 需要重新命名為 tf.matrix_triangular_solve
  • tf.batch_self_adjoint_eig
    • 需要重新命名為 tf.self_adjoint_eig
  • tf.batch_self_adjoint_eigvals
    • 需要重新命名為 tf.self_adjoint_eigvals
  • tf.batch_set_diag
    • 需要重新命名為 tf.set_diag
  • tf.batch_svd
    • 需要重新命名為 tf.svd
  • tf.complex_abs
    • 需要重新命名為 tf.abs

其它改動

除上文所述的改動外,還有以下一些變化:

  • tf.image.per_image_whitening
    • 需要重新命名為 tf.image.per_image_standardization
  • tf.nn.sigmoid_cross_entropy_with_logits
    • 輸入引數重排序為 tf.nn.sigmoid_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, name=None).
  • tf.nn.softmax_cross_entropy_with_logits
    • 輸入引數重排序為 tf.nn.softmax_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, dim=-1, name=None).
  • tf.nn.sparse_softmax_cross_entropy_with_logits
    • 輸入引數重排序為 tf.nn.sparse_softmax_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, name=None).
  • tf.ones_initializer
    • 需要修改成函式呼叫,例如 tf.ones_initializer()
  • tf.pack
    • 需要重新命名為 tf.stack
  • tf.round
    • tf.round 的語義現在與銀行家舍入法(Banker`s rounding)相同。
  • tf.unpack
    • 需要重新命名為 tf.unstack
  • tf.zeros_initializer
    • 需要修改成函式呼叫,例如 tf.zeros_initializer()

掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章