TensorFlow 版本相容性

本文件適用於需要跨不同 TensorFlow 版本 (程式碼或資料) 回溯相容性的使用者,以及想要在維護相容性的同時修改 TensorFlow 的開發人員。

語意化版本控制 2.0

TensorFlow 的公開 API 遵循語意化版本控制 2.0 (semver)。TensorFlow 的每個發行版本都採用 MAJOR.MINOR.PATCH 格式。例如,TensorFlow 1.2.3 版的主要版本號碼為 1,次要版本號碼為 2,修補程式版本號碼為 3。每個號碼的變更具有下列意義

  • MAJOR:可能不回溯相容的變更。先前主要版本可運作的程式碼和資料不一定能與新版本搭配運作。不過在某些情況下,現有的 TensorFlow 圖和檢查點可能會遷移至較新版本;如需資料相容性的詳細資訊,請參閱圖和檢查點的相容性

  • MINOR:回溯相容的功能、速度改進等。先前次要版本可運作,且僅仰賴非實驗性公開 API 的程式碼和資料,將繼續維持不變。如需公開 API 的涵蓋範圍詳細資訊,請參閱涵蓋範圍

  • PATCH:回溯相容的錯誤修正。

例如,1.0.0 版發行版從 0.12.1 版發行版導入不回溯相容的變更。不過,1.1.1 版發行版與 1.0.0 版發行版回溯相容。

涵蓋範圍

只有 TensorFlow 的公開 API 在次要版本和修補程式版本之間回溯相容。公開 API 包括:

  • tensorflow 模組及其子模組中所有已記錄的 Python 函式和類別,但下列項目除外:

    • 私人符號:名稱開頭為 _ 的任何函式、類別等
    • 實驗性和 tf.contrib 符號,詳細資訊請參閱下方

    請注意,examples/tools/ 目錄中的程式碼無法透過 tensorflow Python 模組存取,因此不在相容性保證的範圍內。

    如果符號可透過 tensorflow Python 模組或其子模組取得,但未記錄,則不會將其視為公開 API 的一部分。

  • 相容性 API (在 Python 中為 tf.compat 模組)。在主要版本中,我們可能會發行公用程式和額外的端點,以協助使用者轉換至新的主要版本。這些 API 符號已淘汰且不受支援 (也就是說,我們不會新增任何功能,且不會修正錯誤,但修正漏洞除外),但這些符號確實屬於我們的相容性保證範圍。

  • TensorFlow C API

  • 下列 Protocol Buffer 檔案

TensorFlow Lite 的個別版本號碼

目前 TensorFlow Lite 是以 TensorFlow 的一部分發行。不過,我們保留日後以不同於其他 TensorFlow API 的時程表,發行 TensorFlow Lite API 變更的權利,甚至將 TensorFlow Lite 移至與 TensorFlow 分開的來源發行版本和/或來源存放區。

因此,我們針對 TensorFlow Lite (tensorflow/lite/version.h 中的 TFLITE_VERSION_STRINGtensorflow/lite/c/c_api.h 中的 TfLiteVersion()) 使用的版本號碼,與 TensorFlow (tensorflow/core/public/version.h 中的 TF_VERSION_STRINGtensorflow/c/c_api.h 中的 TF_Version()) 使用的版本號碼不同。目前,這兩個版本號碼的值剛好相同。但在未來,這兩個版本號碼可能會有所不同;例如,我們可能會提高 TensorFlow Lite 的主要版本號碼,但不會提高 TensorFlow 的主要版本號碼,反之亦然。

TensorFlow Lite 版本號碼涵蓋的 API 介面包含下列公開 API:

實驗性符號不在涵蓋範圍內;詳細資訊請參閱下方

TensorFlow Lite 擴充功能 API 的個別版本號碼

TensorFlow Lite 提供 C API,用於透過「自訂運算元」(在圖表中提供使用者定義的運算) 或「委派」(允許將圖表 (或圖表子集) 的運算委派給自訂後端) 擴充 TensorFlow Lite 直譯器。這些 API 我們統稱為「TensorFlow Lite 擴充功能 API」,需要更密切地仰賴 TensorFlow Lite 實作的某些細節。

我們保留日後變更這些 API 的權利,可能包含不回溯相容的變更,且時程表可能與其他 TensorFlow Lite API 不同。因此,我們針對 TensorFlow Lite 擴充功能 API 使用的版本號碼,與 TensorFlow Lite 或 TensorFlow (在前一節中說明) 的版本號碼不同。我們在 TensorFlow Lite 2.15 版中導入一些新的 API,以取得 TensorFlow Lite 擴充功能 API 版本 (tensorflow/lite/version.h 中的 TFLITE_EXTENSION_APIS_VERSION_STRINGtensorflow/lite/c/c_api.h 中的 TfLiteExtensionApisVersion())。TensorFlow Lite 擴充功能 API 的版本號碼目前與 TensorFlow 和 TensorFlow Lite 的版本號碼相同。但在未來,這三個版本號碼可能會有所不同;例如,我們可能會提高 TensorFlow Lite 擴充功能 API 的主要版本號碼,但不會提高 TensorFlow Lite 的主要版本號碼,反之亦然。

TensorFlow Lite 擴充功能 API 版本號碼涵蓋的 API 介面包含下列公開 API:

同樣地,實驗性符號不在涵蓋範圍內;詳細資訊請參閱下方

未涵蓋範圍

TensorFlow 的某些部分隨時都可能以不回溯相容的方式變更。這些部分包括:

  • 實驗性 API:為了促進開發,我們將部分明確標示為實驗性的 API 符號排除在相容性保證之外。特別是,下列項目不在任何相容性保證的範圍內

    • tf.contrib 模組或其子模組中的任何符號;
    • 名稱包含 experimentalExperimental 的任何符號 (模組、函式、引數、屬性、類別、常數、類型、套件等);或
    • 完整限定名稱包含模組或類別或套件本身的任何符號,而該模組或類別或套件本身是實驗性的。這包括任何名為 experimental 的 Protocol Buffer 的欄位和子訊息。
  • 其他語言:Python 和 C 以外語言的 TensorFlow API,例如:

    以及 Java/Kotlin、C、Objective-C 和 Swift 以外語言的 TensorFlow Lite API,特別是:

  • 複合運算元的詳細資訊:Python 中的許多公開函式會擴充為圖表中的數個基本運算元,而這些詳細資訊將成為以 GraphDef 形式儲存至磁碟的任何圖表的一部分。這些詳細資訊可能會針對次要版本變更。特別是,檢查圖表之間是否完全相符的回歸測試可能會在次要版本之間中斷,即使圖表的行為應維持不變,且現有的檢查點仍可運作也一樣。

  • 浮點數值詳細資訊:運算元計算的特定浮點數值可能隨時變更。使用者應僅仰賴近似精確度和數值穩定性,而非仰賴計算出的特定位元。次要版本和修補程式版本中數值公式的變更應產生相當或更佳的精確度,但請注意,在機器學習中,特定公式精確度的提升可能會導致整體系統的精確度降低。

  • 隨機數字:計算出的特定隨機數字可能隨時變更。使用者應僅仰賴近似正確的分佈和統計強度,而非仰賴計算出的特定位元。如需詳細資訊,請參閱隨機數字產生指南。

  • 分散式 Tensorflow 中的版本偏差:不支援在單一叢集中執行兩個不同版本的 TensorFlow。不保證線路協定的回溯相容性。

  • 錯誤:如果目前實作顯然已損壞,也就是說,如果實作與文件相矛盾,或是由於錯誤而未正確實作眾所周知且明確定義的預期行為,我們保留進行不回溯相容行為 (但非 API) 變更的權利。例如,如果最佳化工具聲稱實作了眾所周知的最佳化演算法,但由於錯誤而與該演算法不符,則我們會修正最佳化工具。我們的修正可能會破壞仰賴錯誤行為以達成收斂的程式碼。我們會在版本資訊中註明這類變更。

  • 未使用的 API:我們保留對我們發現沒有記錄用途的 API 進行不回溯相容變更的權利 (透過 GitHub 搜尋執行 TensorFlow 用途稽核)。在進行任何這類變更之前,我們會在 announce@ 郵寄清單中公告我們進行變更的意圖,提供解決任何中斷問題的指示 (如果適用),並等待兩週,讓我們的社群有機會分享意見回饋。

  • 錯誤行為:我們可能會以非錯誤行為取代錯誤。例如,我們可能會變更函式以計算結果,而非引發錯誤,即使該錯誤已記錄也一樣。我們也保留變更錯誤訊息文字的權利。此外,除非文件中指定特定錯誤狀況的例外狀況類型,否則錯誤類型可能會變更。

SavedModel、圖表和檢查點的相容性

SavedModel 是 TensorFlow 程式中慣用的序列化格式。SavedModel 包含兩個部分:一個或多個以 GraphDef 編碼的圖表和一個檢查點。圖表描述要執行的運算元的資料流程,而檢查點包含圖表中變數的已儲存張量值。

許多 TensorFlow 使用者會建立 SavedModel,並使用較新版本的 TensorFlow 載入和執行這些 SavedModel。為了符合 semver,以某個版本的 TensorFlow 寫入的 SavedModel 可以使用相同主要版本的較新 TensorFlow 版本載入和評估。

我們針對受支援的 SavedModel 提供額外保證。我們將在 TensorFlow 主要版本 N 中僅使用非淘汰、非實驗性、非相容性 API 建立的 SavedModel 稱為版本 N 中受支援的 SavedModel。任何在 TensorFlow 主要版本 N 中受支援的 SavedModel 都可以使用 TensorFlow 主要版本 N+1 載入和執行。不過,建構或修改這類模型所需的功能可能不再提供,因此此保證僅適用於未修改的 SavedModel。

我們將盡力盡可能長時間地維持回溯相容性,以便序列化檔案在長時間內都可使用。

GraphDef 相容性

圖表透過 GraphDef Protocol Buffer 序列化。為了促進圖表的不回溯相容變更,每個 GraphDef 都有一個與 TensorFlow 版本分開的版本號碼。例如,GraphDef 17 版已淘汰 inv 運算元,改用 reciprocal。語意如下:

  • 每個版本的 TensorFlow 都支援 GraphDef 版本的間隔。此間隔在修補程式版本之間將保持不變,且只會在次要版本之間成長。只有在 TensorFlow 的主要版本發行時 (且僅與 SavedModel 保證的版本支援一致),才會停止支援 GraphDef 版本。

  • 新建立的圖表會指派最新的 GraphDef 版本號碼。

  • 如果特定版本的 TensorFlow 支援圖表的 GraphDef 版本,則無論 TensorFlow 的主要版本為何,它都會以與用於產生圖表的 TensorFlow 版本相同的行為載入和評估 (上述浮點數值詳細資訊和隨機數字除外)。特別是,在某個 TensorFlow 版本中與檢查點檔案相容的 GraphDef (例如 SavedModel 中的情況) 在後續版本中仍會與該檢查點相容,只要支援 GraphDef 即可。

    請注意,這僅適用於 GraphDef (和 SavedModel) 中的序列化圖表:讀取檢查點的程式碼可能無法讀取由執行不同版本 TensorFlow 的相同程式碼產生的檢查點。

  • 如果在 (次要) 版本中 GraphDef 上限提高至 X,則至少在下限提高至 X 之前會有六個月的時間。例如 (我們在此使用假設的版本號碼)

    • TensorFlow 1.2 可能支援 GraphDef 4 至 7 版。
    • TensorFlow 1.3 可以新增 GraphDef 8 版,並支援 4 至 8 版。
    • 至少六個月後,TensorFlow 2.0.0 可以停止支援 4 至 7 版,僅保留 8 版。

    請注意,由於 TensorFlow 的主要版本通常間隔超過 6 個月發佈,因此上述受支援 SavedModel 的保證比 GraphDef 的 6 個月保證強得多。

最後,當停止支援 GraphDef 版本時,我們會嘗試提供工具,將圖表自動轉換為較新的受支援 GraphDef 版本。

擴充 TensorFlow 時的圖表和檢查點相容性

本節僅在對 GraphDef 格式進行不相容變更時才相關,例如新增運算元、移除運算元或變更現有運算元的功能時。上一節應足以滿足大多數使用者。

回溯相容性和部分前向相容性

我們的版本控制機制有三項要求

  • 回溯相容性,以支援載入使用舊版 TensorFlow 建立的圖表和檢查點。
  • 前向相容性,以支援在取用者之前,圖表或檢查點的生產者升級至較新版本 TensorFlow 的情況。
  • 能夠以不相容的方式發展 TensorFlow。例如,移除運算元、新增屬性和移除屬性。

請注意,雖然 GraphDef 版本機制與 TensorFlow 版本分開,但對 GraphDef 格式進行不回溯相容變更仍受語意化版本控制的限制。這表示只能在 TensorFlow 的 MAJOR 版本之間移除或變更功能 (例如 1.7 至 2.0)。此外,前向相容性會在修補程式版本 (例如 1.x.1 至 1.x.2) 內強制執行。

為了達成回溯相容性和前向相容性,並瞭解何時強制執行格式變更,圖表和檢查點具有描述其產生時間的中繼資料。以下各節詳細說明 TensorFlow 實作和發展 GraphDef 版本的指南。

獨立資料版本機制

圖表和檢查點有不同的資料版本。這兩種資料格式彼此之間以及與 TensorFlow 的發展速度不同。這兩種版本控制系統都在 core/public/version.h 中定義。每當新增版本時,都會在標頭中新增註解,詳細說明變更內容和日期。

資料、生產者和取用者

我們區分下列幾種資料版本資訊

  • 生產者:產生資料的二進位檔。生產者具有版本 (producer) 和與其相容的最低取用者版本 (min_consumer)。
  • 取用者:取用資料的二進位檔。取用者具有版本 (consumer) 和與其相容的最低生產者版本 (min_producer)。

每個版本化的資料片段都有一個 VersionDef versions 欄位,用於記錄產生資料的 producer、與之相容的 min_consumer,以及不允許使用的 bad_consumers 版本清單。

根據預設,當生產者產生一些資料時,資料會繼承生產者的 producermin_consumer 版本。如果已知特定消費者版本包含錯誤且必須避免,則可以設定 bad_consumers。如果以下條件皆為真,則消費者可以接受資料片段

  • consumer >= 資料的 min_consumer
  • 資料的 producer >= 消費者的 min_producer
  • consumer 不在資料的 bad_consumers

由於生產者和消費者都來自相同的 TensorFlow 程式碼庫,core/public/version.h 包含一個主要資料版本,該版本根據上下文被視為 producerconsumer,以及 min_consumermin_producer(分別為生產者和消費者所需)。具體來說,

  • 對於 GraphDef 版本,我們有 TF_GRAPH_DEF_VERSIONTF_GRAPH_DEF_VERSION_MIN_CONSUMERTF_GRAPH_DEF_VERSION_MIN_PRODUCER
  • 對於檢查點版本,我們有 TF_CHECKPOINT_VERSIONTF_CHECKPOINT_VERSION_MIN_CONSUMERTF_CHECKPOINT_VERSION_MIN_PRODUCER

將具有預設值的新屬性新增至現有的運算元

僅當運算元集合未變更時,遵循以下指南才能提供向前相容性

  1. 如果需要向前相容性,在使用 SavedModelBuilder 類別的 tf.saved_model.SavedModelBuilder.add_meta_graph_and_variablestf.saved_model.SavedModelBuilder.add_meta_graph 方法,或 tf.estimator.Estimator.export_saved_model 匯出模型時,將 strip_default_attrs 設定為 True
  2. 這會在產生/匯出模型時剝離預設值的屬性。這確保當使用預設值時,匯出的 tf.MetaGraphDef 不包含新的運算元屬性。
  3. 擁有此控制權可讓過時的消費者(例如,落後於訓練二進位檔的服務二進位檔)繼續載入模型,並防止模型服務中斷。

演進 GraphDef 版本

本節說明如何使用此版本控制機制對 GraphDef 格式進行不同類型的變更。

新增運算元

同時將新的運算元新增到消費者和生產者,並且不要變更任何 GraphDef 版本。這種變更類型會自動向後相容,並且不會影響向前相容性計畫,因為現有的生產者腳本不會突然使用新功能。

新增運算元並切換現有的 Python 包裝函式以使用它

  1. 實作新的消費者功能並遞增 GraphDef 版本。
  2. 如果可以讓包裝函式僅在以前無法運作的情況下使用新功能,則現在可以更新包裝函式。
  3. 變更 Python 包裝函式以使用新功能。不要遞增 min_consumer,因為不使用此運算元的模型不應中斷。

移除或限制運算元的功能

  1. 修正所有生產者腳本(而非 TensorFlow 本身),使其不使用禁止的運算元或功能。
  2. 遞增 GraphDef 版本,並實作新的消費者功能,該功能禁止在新版本及更高版本的 GraphDefs 中使用已移除的運算元或功能。如果可能,讓 TensorFlow 停止產生具有禁止功能的 GraphDefs。為此,請新增 REGISTER_OP(...).Deprecated(deprecated_at_version, message)
  3. 等待主要版本發布以實現向後相容性。
  4. min_producer 增加到 (2) 的 GraphDef 版本,並完全移除該功能。

變更運算元的功能

  1. 新增一個名為 SomethingV2 或類似名稱的新相似運算元,並完成新增它和切換現有 Python 包裝函式以使用它的過程。為了確保向前相容性,在變更 Python 包裝函式時,請使用 compat.py 中建議的檢查。
  2. 移除舊的運算元(由於向後相容性,只能在主要版本變更時進行)。
  3. 增加 min_consumer 以排除具有舊運算元的消費者,將舊運算元作為 SomethingV2 的別名重新新增,並完成切換現有 Python 包裝函式以使用它的過程。
  4. 完成移除 SomethingV2 的過程。

禁止單個不安全的消費者版本

  1. 調升 GraphDef 版本,並將不良版本新增到所有新 GraphDefs 的 bad_consumers 中。如果可能,僅針對包含特定運算元或類似運算元的 GraphDefs 新增到 bad_consumers
  2. 如果現有的消費者具有不良版本,請盡快將其推出。