採用其他程式語言的 TensorFlow

2021-09-19 11:27:41 字數 4630 閱讀 9710

背景

本文件旨在為那些想要用其他程式語言建立或開發 tensorflow 功能的人員提供指導。本文介紹了 tensorflow 的功能以及在其他程式語言中實現相同功能應採取的推薦步驟。海風教育退費

python 是 tensorflow 支援的第一種客戶端語言,目前支援的功能最多。該功能正逐步移植到 tensorflow 的核心(用 c++ 實現)並通過 c api 公開。客戶端語言應使用該語言的外部函式介面 (ffi) 呼叫此 c api 以提供 tensorflow 功能。

概述通過某個程式語言提供 tensorflow 功能可分為幾大類別:

執行預定義圖:給定 graphdef(或 metagraphdef)協議訊息,能夠建立會話,執行查詢並獲得張量結果。這對於想要在預訓練模型上進行推斷的移動應用或伺服器來說已足夠

圖構造:每個定義的 tensorflow 操作至少有乙個向圖新增操作的函式。理想情況下,這些函式會自動生成,因此在修改操作定義時它們會保持同步

梯度(亦稱為自動微分):給定圖及輸入和輸出操作列表,向圖新增計算輸入相對於輸出的偏導數(梯度)的操作。允許針對圖中的特定操作自定義梯度函式

函式:定義可在主 graphdef 中的多個位置呼叫的子圖。在包含在 graphdef 中的 functiondeflibrary 內定義 functiondef

控制流:使用使用者指定的子圖構造 if 和 while 迴圈。理想情況下,這些控制流支援梯度(參見上文)

神經網路庫:一些元件,它們共同支援神經網路模型的建立和訓練(可能在分布式設定中)。雖然以其他語言提供此功能會很方便,但目前還沒有用除 python 以外的語言支援此功能的計畫。這些庫通常是上述功能的封裝容器

語言繫結至少應支援執行預定義的圖,但大多數還應支援圖構造。tensorflow python api 提供了所有這些功能。

當前狀態

應該在 c api 基礎之上構建新的語言支援。但是,正如您在下表中所看到的,部分功能尚未在 c 中提供。在 c api 中提供更多功能是乙個長期專案。

推薦方法

執行預定義的圖

語言繫結應該定義以下類:

graph:表示 tensorflow 計算的圖。包含操作(在客戶端語言中由 operation 表示)並且對應於 c api 中的 tf_graph。主要在建立新的 operation 物件和啟動 session 時用作引數。還支援遍歷圖中的操作 (tf_graphnextoperation),按名稱查詢操作 (tf_graphoperationbyname),以及轉換為 graphdef 協議訊息或對其進行轉換(c api 中的 tf_graphtographdef 和 tf_graphimportgraphdef)

operation:表示圖中的計算節點。對應於 c api 中的 tf_operation

output:表示圖中某個操作的乙個輸出。具有 datatype(最終是乙個形狀)。可以作為輸入引數傳遞給函式以向圖新增操作,或傳遞給 session 的 run() 方法以將該輸出提取為張量。對應於 c api 中的 tf_output

session:表示 tensorflow 執行時的特定例項的客戶端。它的主要任務是使用 graph 和一些選項進行構建,然後進行字段呼叫以對圖執行 run() 操作。對應於 c api 中的 tf_session

tensor:表示所有元素都具有相同 datatype 的 n 維(矩形)陣列。向 session 的 run() 呼叫提供資料或從中獲取資料。對應於 c api 中的 tf_tensor

datatype:包含受 tensorflow 支援的所有可能張量型別的列舉。對應於 c api 中的 tf_datatype,在 python api 中通常稱為 dtype

圖構造tensorflow 有很多操作,並且操作列表不是靜態的,因此我們建議生成用於將操作新增到圖中的函式,而不是手動逐個編寫這些函式(但手動編寫一些函式不失為確定生成器應該生成哪些內容的不錯方法)。生成函式所需的資訊包含在 opdef 協議訊息中。

您可以通過以下幾種方法獲取已註冊操作的 opdef 列表:

c api 中的 tf_getalloplist 會檢索所有已註冊的 opdef 協議訊息。它可以用於以客戶端語言編寫生成器。這就要求客戶端語言支援協議緩衝區,以便解釋 opdef 訊息

c++ 函式 opregistry::global()->getregisteredops() 會返回所有已註冊 opdef(在 tensorflow/core/framework/op.h 中定義)的相同列表。它可以用於以 c++ 編寫生成器(對於不支援協議緩衝區的語言特別有用)

該列表的 ascii 序列化版本通過自動化流程定期檢入 tensorflow/core/ops/ops.pbtxt

opdef 會指定以下內容:

駝峰命名法 (camelcase) 的操作名稱。對於生成的函式,請遵循相應語言的慣例。例如,如果該語言使用蛇形命名法 (snake_case),則使用該命名法而不是駝峰命名法表示此操作的函式名稱

輸入和輸出列表。這些內容的型別可以通過引用屬性實現多型,如新增操作的輸入和輸出部分所述

屬性列表及其預設值(如果有)。請注意,系統會推斷其中一些屬性(如果它們由輸入確定),一些屬性是可選屬性(如果它們具有預設值),另一些屬性是必需屬性(無預設值)

一般操作以及輸入、輸出和非推斷屬性的文件

執行時使用的其他一些字段,可以被**生成器忽略

可以將 opdef 轉換為函式的文字,該函式使用 tf_operationdescription c api(封裝在相應語言的 ffi 中)將該操作新增到圖中:

從 tf_newoperation() 開始建立 tf_operationdescription*。

每個輸入呼叫 tf_addinput() 或 tf_addinputlist() 一次(取決於輸入是否具有列表型別)。

呼叫 tf_setattr*() 函式來設定非推斷屬性。如果您不想替換預設值,可以跳過具有預設值的屬性。

根據需要設定選填字段:

tf_setdevice():強制在特定裝置上執行操作。

tf_addcontrolinput():新增要求以說明在此操作開始執行之前完成另乙個操作

tf_setattrstring("_kernel"):設定核心標籤(很少使用)

tf_colocatewith():將乙個操作與另乙個操作共置到一起

完成後呼叫 tf_finishoperation()。這樣會將操作新增到圖中,之後便無法修改。

現有示例會在編譯流程中執行**生成器(使用 bazel genrule)。或者,**生成器可以由自動化 cron 程序執行,並可能檢入結果中。這可能會導致生成的**與檢入**庫中的 opdef 之間產生分歧,但對於會提前生成**的語言(例如適用於 go 的 go get 和適用於 rust 的 cargo ops)很有用。另一方面,對於某些語言,**可以從 tensorflow/core/ops/ops.pbtxt 動態生成。

處理常量

如果使用者可以為輸入引數提供常量,則呼叫**將更加簡潔。生成的**應該將這些常量轉換為以下操作:新增到圖中並用作正在例項化的操作的輸入。

可選引數

如果語言允許函式具有可選引數(如 python 中具有預設值的關鍵字引數),則將它們用於可選屬性、操作名稱、裝置、控制輸入等。在某些語言中,可以使用動態作用域設定這些可選引數(如 python 中的 「with」 塊)。如果沒有這些功能,庫可能會依靠 「編譯器模式」,就像在 tensorflow api 的 c++ 版本中所做的那樣。

名稱作用域

建議您使用某種作用域層次結構支援命名圖操作,特別是考慮到 tensorboard 依靠它以合理的方式顯示大圖這一事實。現有的 python 和 c++ api 採用不同的方法:在 python 中,名稱的 「目錄」 部分(最後乙個 「/」 前面的所有內容)來自 with塊。實際上,有乙個執行緒區域性堆疊,其中的作用域定義了名稱層次結構。名稱的最後乙個組成部分由使用者顯式提供(使用可選的 name 關鍵字引數),或者預設為要新增的操作的型別名稱。在 c++ 中,名稱的 「目錄」 部分儲存在顯式 scope 物件中。newsubscope() 方法附加到名稱的該部分並返回乙個新的 scope。名稱的最後乙個組成部分是使用 withopname() 方法設定的,並且像 python 一樣預設為要新增的操作的型別名稱。系統會顯式傳遞 scope 物件以指定上下文的名稱。

封裝容器

可以保留生成的函式專用於某些操作,這樣可以改用執行一些額外工作的封裝容器函式。這也為支援所生成**作用域之外的功能提供了乙個應急路徑。

封裝容器的乙個用途是支援 sparsetensor 輸入和輸出。sparsetensor 是乙個包含 3 個密集張量(索引、值和形狀)的元組。值是向量大小 [n],形狀是向量大小 [秩],索引是矩陣大小 [n, 秩]。有一些稀疏操作使用此三元組表示單個稀疏張量。

使用封裝容器的另乙個原因是用於保留狀態的操作。有一些此類操作(例如變數)有幾個用於處理該狀態的伴隨操作。python api 為這些操作提供了類,其中建構函式會建立操作,並且此類上的方法會向處理該狀態的圖新增操作。

其他注意事項

最好新增乙個關鍵字列表,用於重新命名與語言關鍵字衝突的操作函式和引數(或其他會導致問題的符號,如生成的**中引用的庫函式或變數的名稱)。

用於向圖新增 const 操作的函式通常是封裝容器,因為生成的函式通常具有冗餘的 datatype 輸入。

梯度、函式和控制流

目前,對梯度、函式和控制流操作(「if」 和 「while」)的支援並未在除 python 以外的其他語言中提供。當 c api 提供必要的支援時,將會更新這方面的功能。

Python 和其他程式語言資料型別的比較

摘自 dive into python 靜態型別語言 一種在編譯期間就確定資料型別的語言。大多數靜態型別語言是通過要求在使用任一變數之前宣告其資料型別來保證這一點的。是靜態型別語言。動態型別語言 一種在執行期間才去確定資料型別的語言,與靜態型別相反。強型別語言 一種總是強制型別定義的語言。弱型別語言...

python迴圈語句與其他程式語言不同之處

近兩年python語言不斷受到各大企業的歡迎,學習python 1 區域性變數 foriinrange 5 print i,print i,執行結果 0 1 2 3 4 4 i是for 語句裡面的區域性變數。但在 python 裡面,在同一方法體內,定義了乙個區域性變數,該變數的作用域是定義行開始至...

Python與其他語言的區別

python中沒有自增自減運算。python 不使用 的哲學邏輯 編譯解析上的簡潔與語言本身的簡潔。舉個例子來說python 與 c 語言概念上的一些差異 python 中,變數是以內容為基準而不是像 c 中以變數名為基準,所以只要你的數字內容是5,不管你起什麼名字,這個變數的 id 是相同的,同時...