當(dāng)前位置:首頁(yè) > 智能硬件 > 人工智能AI
[導(dǎo)讀] 導(dǎo)讀:“我叫 Jacob,是谷歌 AI Residency 項(xiàng)目的學(xué)者。2017 年夏天我進(jìn)入這個(gè)項(xiàng)目的時(shí)候,我自己的編程經(jīng)驗(yàn)很豐富,對(duì)機(jī)器學(xué)習(xí)理解也很深刻,但以前我從未使用過 Te

導(dǎo)讀:“我叫 Jacob,是谷歌 AI Residency 項(xiàng)目的學(xué)者。2017 年夏天我進(jìn)入這個(gè)項(xiàng)目的時(shí)候,我自己的編程經(jīng)驗(yàn)很豐富,對(duì)機(jī)器學(xué)習(xí)理解也很深刻,但以前我從未使用過 Tensorflow。當(dāng)時(shí)我認(rèn)為憑自己的能力可以很快掌握 Tensorflow,但沒想到我學(xué)習(xí)它的過程竟然如此跌宕起伏。甚至加入項(xiàng)目幾個(gè)月后我還偶爾會(huì)感到困惑,不知道怎樣用 Tensorflow 代碼實(shí)現(xiàn)自己的新想法。

這篇博文就像是我給過去自己寫的瓶中信:回顧當(dāng)初,我希望在開始學(xué)習(xí)的時(shí)候有這樣一篇入門介紹。我也希望本文能夠幫助同行,為他們提供參考。”AI 前線將這位現(xiàn)谷歌大腦工程師關(guān)于學(xué)習(xí) Tensorflow 過程中遭遇的方方面面難題的文章做了翻譯,希望對(duì)大家有幫助。

過去的教程缺少哪些內(nèi)容?

Tensorflow 發(fā)布已經(jīng)有三年,如今它已成為深度學(xué)習(xí)生態(tài)系統(tǒng)的基石。然而對(duì)于初學(xué)者來說它并不怎么簡(jiǎn)單易懂,與 PyTorch 或 DyNet 這樣的運(yùn)行即定義的神經(jīng)網(wǎng)絡(luò)庫(kù)相比就更明顯了。

有很多 Tensorflow 的入門教程,內(nèi)容涵蓋線性回歸、MNIST 分類乃至機(jī)器翻譯。這些內(nèi)容具體、實(shí)用的指南能幫助人們快速啟動(dòng)并運(yùn)行 Tensorflow 項(xiàng)目,并且可以作為類似項(xiàng)目的切入點(diǎn)。但有的開發(fā)者開發(fā)的應(yīng)用并沒有很好的教程參考,還有的項(xiàng)目在探索全新的路線(研究中很常見),對(duì)于這些開發(fā)者來說入門 Tensorflow 是非常容易感到困惑的。

我寫這篇文章就想彌補(bǔ)這一缺口。本文不會(huì)研究某個(gè)具體任務(wù),而是提出更加通用的方法,并解析 Tensorflow 的基礎(chǔ)抽象概念。掌握好這些概念后,用 Tensorflow 進(jìn)行深度學(xué)習(xí)就會(huì)更加直觀易懂。

目標(biāo)受眾

本教程適用于在編程和機(jī)器學(xué)習(xí)方面有一定經(jīng)驗(yàn),并想要入門 Tensorflow 的從業(yè)者。他們可以是:想在深度學(xué)習(xí)課程的最后一個(gè)項(xiàng)目中使用 Tensorflow 的 CS 專業(yè)學(xué)生;剛剛被調(diào)到涉及深度學(xué)習(xí)的項(xiàng)目的軟件工程師;或者是一位處于困惑之中的 Google AI 新手(向 Jacob 大聲打個(gè)招呼吧)。如果你需要基礎(chǔ)知識(shí)入門,請(qǐng)參閱以下資源。這些都了解的話,我們就開始吧!

理解 Tensorflow

Tensorflow 不是一個(gè)普通的 Python 庫(kù)。

大多數(shù) Python 庫(kù)被編寫為 Python 的自然擴(kuò)展形式。當(dāng)你導(dǎo)入一個(gè)庫(kù)時(shí),你得到的是一組變量、函數(shù)和類,它們補(bǔ)充并擴(kuò)展了你的代碼“工具箱”。使用這些庫(kù)時(shí),你知道它們將產(chǎn)生怎樣的結(jié)果。我認(rèn)為談及 Tensorflow 時(shí)應(yīng)該拋棄這些認(rèn)識(shí),這些認(rèn)知從根本上就不符合 Tensorflow 的理念,無法反映 TF 與其它代碼交互的方式。

Python 和 Tensorflow 之間的聯(lián)系,可以類比 Javascript 和 HTML 之間的關(guān)系。Javascript 是一種全功能的編程語言,可以實(shí)現(xiàn)各種出色的效果。HTML 是用于表示某種類型的實(shí)用計(jì)算抽象(這里指的是可由 Web 瀏覽器呈現(xiàn)的內(nèi)容)的框架。Javascript 在交互式網(wǎng)頁(yè)中的作用是組裝瀏覽器看到的 HTML 對(duì)象,然后在需要時(shí)通過將其更新為新的 HTML 來與其交互。

與 HTML 類似,Tensorflow 是用于表示某種類型的計(jì)算抽象(稱為“計(jì)算圖”)的框架。當(dāng)我們用 Python 操作 Tensorflow 時(shí),我們用 Python 代碼做的第一件事是組裝計(jì)算圖。之后我們的第二個(gè)任務(wù)就是與它進(jìn)行交互(使用 Tensorflow 的“會(huì)話”)。但重要的是,要記住計(jì)算圖不在變量?jī)?nèi)部,它處在全局命名空間內(nèi)。莎士比亞曾經(jīng)說過:“所有的 RAM 都是一個(gè)階段,所有的變量都只不過是指針。”

第一個(gè)關(guān)鍵抽象:計(jì)算圖

我們?cè)跒g覽 Tensorflow 文檔時(shí),有時(shí)會(huì)發(fā)現(xiàn)內(nèi)容提到“圖形”和“節(jié)點(diǎn)”。如果你仔細(xì)閱讀、深入挖掘,甚至可能已經(jīng)發(fā)現(xiàn)了這個(gè)頁(yè)面,該頁(yè)面中涵蓋的內(nèi)容我將以更精確和技術(shù)化的風(fēng)格詳細(xì)解釋。本節(jié)將從頂層入手,把握關(guān)鍵的直覺概念,同時(shí)略過一些技術(shù)細(xì)節(jié)。

那么什么是計(jì)算圖?它實(shí)質(zhì)上是一個(gè)全局?jǐn)?shù)據(jù)結(jié)構(gòu):計(jì)算圖是一個(gè)有向圖,捕獲有關(guān)計(jì)算方法的指令。

我們來看看如何構(gòu)建一個(gè)示例。下圖中,上半部分是我們運(yùn)行的代碼和它的輸出,下半部分是結(jié)果計(jì)算圖。

顯然,僅僅導(dǎo)入 Tensorflow 并不會(huì)給我們生成一個(gè)有趣的計(jì)算圖,而只有一個(gè)孤獨(dú)的,空白的全局變量。但是當(dāng)我們調(diào)用一個(gè) Tensorflow 操作時(shí)會(huì)發(fā)生什么呢?

快看!我們得到了一個(gè)節(jié)點(diǎn),它包含常量:2。我知道你很驚訝,驚訝的是一個(gè)名為 tf.constant 的函數(shù)。當(dāng)我們打印這個(gè)變量時(shí),我們看到它返回一個(gè) tf.Tensor 對(duì)象,它是一個(gè)指向我們剛創(chuàng)建的節(jié)點(diǎn)的指針。為了強(qiáng)調(diào)這一點(diǎn),這里是另一個(gè)例子:

每次我們調(diào)用 tf.constant 的時(shí)候,我們都會(huì)在圖中創(chuàng)建一個(gè)新節(jié)點(diǎn)。即使節(jié)點(diǎn)在功能上與現(xiàn)有節(jié)點(diǎn)完全相同,即使我們將節(jié)點(diǎn)重新分配給同一個(gè)變量,甚至我們根本沒有將其分配給變量,結(jié)果都一樣。

相反,如果創(chuàng)建一個(gè)新變量并將其設(shè)置為與現(xiàn)有節(jié)點(diǎn)相等,則只需將該指針復(fù)制到該節(jié)點(diǎn),并且不會(huì)向該圖添加任何內(nèi)容:

好的,我們更進(jìn)一步。

現(xiàn)在我們來看——這才是我們要的真正的計(jì)算圖表!請(qǐng)注意,+ 操作在 Tensorflow 中過載,所以同時(shí)添加兩個(gè)張量會(huì)在圖中增加一個(gè)節(jié)點(diǎn),盡管它看起來不像是 Tensorflow 操作。

好的,所以 two_node 指向包含 2 的節(jié)點(diǎn),three_node 指向包含 3 的節(jié)點(diǎn),而 sum_node 指向包含... + 的節(jié)點(diǎn)?什么情況?它不是應(yīng)該包含 5 嗎?

事實(shí)證明,沒有。計(jì)算圖只包含計(jì)算步驟,不包含結(jié)果。至少...... 還沒有!

第二個(gè)關(guān)鍵抽象:會(huì)話

如果錯(cuò)誤地理解 TensorFlow 抽象也有個(gè)瘋狂三月競(jìng)賽(美國(guó)大學(xué)籃球繁忙冠軍賽季),那么“會(huì)話”將成為每年排名第一的種子選手。能獲此尷尬的榮譽(yù),是因?yàn)闀?huì)話的命名反直覺,應(yīng)用卻如此廣泛——幾乎每個(gè) Tensorflow 程序都至少會(huì)調(diào)用一次 tf.Session () 。

會(huì)話的作用是處理內(nèi)存分配和優(yōu)化,使我們能夠?qū)嶋H執(zhí)行由圖形指定的計(jì)算。可以將計(jì)算圖想象為我們想要執(zhí)行的計(jì)算的“模板”:它列出了所有的步驟。為了使用這個(gè)圖表,我們還需要發(fā)起一個(gè)會(huì)話,它使我們能夠?qū)嶋H地完成任務(wù)。例如,遍歷模板的所有節(jié)點(diǎn)來分配一組用于存儲(chǔ)計(jì)算輸出的存儲(chǔ)器。為了使用 Tensorflow 進(jìn)行各種計(jì)算,我們既需要圖也需要會(huì)話。

會(huì)話包含一個(gè)指向全局圖的指針,該指針通過指向所有節(jié)點(diǎn)的指針不斷更新。這意味著在創(chuàng)建節(jié)點(diǎn)之前還是之后創(chuàng)建會(huì)話都無所謂。

創(chuàng)建會(huì)話對(duì)象后,可以使用 sess.run (node) 返回節(jié)點(diǎn)的值,并且 Tensorflow 將執(zhí)行確定該值所需的所有計(jì)算。

精彩!我們還可以傳遞一個(gè)列表,sess.run ([node1,node2,...]),并讓它返回多個(gè)輸出:

一般來說,sess.run () 調(diào)用往往是最大的 TensorFlow 瓶頸之一,所以調(diào)用它的次數(shù)越少越好。可以的話在一個(gè) sess.run () 調(diào)用中返回多個(gè)項(xiàng)目,而不是進(jìn)行多個(gè)調(diào)用。

占位符和 feed_dict

我們迄今為止所做的計(jì)算一直很乏味:沒有機(jī)會(huì)獲得輸入,所以它們總是輸出相同的東西。一個(gè)實(shí)用的應(yīng)用可能涉及構(gòu)建這樣一個(gè)計(jì)算圖:它接受輸入,以某種(一致)方式處理它,并返回一個(gè)輸出。

最直接的方法是使用占位符。占位符是一種用于接受外部輸入的節(jié)點(diǎn)。

……這是個(gè)糟糕的例子,因?yàn)樗l(fā)了一個(gè)異常。占位符預(yù)計(jì)會(huì)被賦予一個(gè)值,但我們沒有提供,因此 Tensorflow 崩潰了。

為了提供一個(gè)值,我們使用 sess.run () 的 feed_dict 屬性。

好多了。注意傳遞給 feed_dict 的數(shù)值格式。這些鍵應(yīng)該是與圖中占位符節(jié)點(diǎn)相對(duì)應(yīng)的變量(如前所述,它實(shí)際上意味著指向圖中占位符節(jié)點(diǎn)的指針)。相應(yīng)的值是要分配給每個(gè)占位符的數(shù)據(jù)元素——通常是標(biāo)量或 Numpy 數(shù)組。第三個(gè)關(guān)鍵抽象:計(jì)算路徑下面是另一個(gè)使用占位符的例子:

為什么第二次調(diào)用 sess.run () 會(huì)失敗?我們并沒有在檢查 input_placeholder,為什么會(huì)引發(fā)與 input_placeholder 相關(guān)的錯(cuò)誤?答案在于最終的關(guān)鍵 Tensorflow 抽象:計(jì)算路徑。還好這個(gè)抽象非常直觀。

當(dāng)我們?cè)谝蕾囉趫D中其他節(jié)點(diǎn)的節(jié)點(diǎn)上調(diào)用 sess.run () 時(shí),我們也需要計(jì)算這些節(jié)點(diǎn)的值。如果這些節(jié)點(diǎn)有依賴關(guān)系,那么我們需要計(jì)算這些值(依此類推......),直到達(dá)到計(jì)算圖的“頂端”,也就是所有的節(jié)點(diǎn)都沒有前置節(jié)點(diǎn)的情況。

考察 sum_node 的計(jì)算路徑:

所有三個(gè)節(jié)點(diǎn)都需要評(píng)估以計(jì)算 sum_node 的值。最重要的是,這里面包含了我們未填充的占位符,并解釋了例外情況!

相反,考察 three_node 的計(jì)算路徑:

根據(jù)圖的結(jié)構(gòu),我們不需要計(jì)算所有的節(jié)點(diǎn)也可以評(píng)估我們想要的節(jié)點(diǎn)!因?yàn)槲覀儾恍枰u(píng)估 placeholder_node 來評(píng)估 three_node,所以運(yùn)行 sess.run (three_node) 不會(huì)引發(fā)異常。

Tensorflow 僅通過必需的節(jié)點(diǎn)自動(dòng)路由計(jì)算這一事實(shí)是它的巨大優(yōu)勢(shì)。如果計(jì)算圖非常大并且有許多不必要的節(jié)點(diǎn),它就能節(jié)約大量運(yùn)行時(shí)間。它允許我們構(gòu)建大型的“多用途”圖形,這些圖形使用單個(gè)共享的核心節(jié)點(diǎn)集合根據(jù)采取的計(jì)算路徑來做不同的任務(wù)。對(duì)于幾乎所有應(yīng)用程序而言,根據(jù)所采用的計(jì)算路徑考慮 sess.run () 的調(diào)用方法是很重要的。

變量和副作用

到目前為止,我們已經(jīng)看到兩種類型的“無祖先”節(jié)點(diǎn):tf.constant(每次運(yùn)行都一樣)和 tf.placeholder(每次運(yùn)行都不一樣)。還有第三種節(jié)點(diǎn):通常情況下具有相同的值,但也可以更新成新值。這個(gè)時(shí)候就要用到變量。

了解變量對(duì)于使用 Tensorflow 進(jìn)行深度學(xué)習(xí)來說至關(guān)重要,因?yàn)槟P偷膮?shù)就是變量。在訓(xùn)練期間,你希望通過梯度下降在每個(gè)步驟更新參數(shù),但在計(jì)算過程中,你希望保持參數(shù)不變,并將大量不同的測(cè)試輸入集傳入到模型中。模型所有的可訓(xùn)練參數(shù)很有可能都是變量。

要?jiǎng)?chuàng)建變量,請(qǐng)使用 tf.get_variable ()。tf.get_variable () 的前兩個(gè)參數(shù)是必需的,其余是可選的。它們是 tf.get_variable (name,shape)。name 是一個(gè)唯一標(biāo)識(shí)這個(gè)變量對(duì)象的字符串。它在全局圖中必須是唯一的,所以要確保不會(huì)出現(xiàn)重復(fù)的名稱。shape 是一個(gè)與張量形狀相對(duì)應(yīng)的整數(shù)數(shù)組,它的語法很直觀——每個(gè)維度對(duì)應(yīng)一個(gè)整數(shù),并按照排列。例如,一個(gè) 3&TImes;8 的矩陣可能具有形狀 [3,8]。要?jiǎng)?chuàng)建標(biāo)量,請(qǐng)使用空列表作為形狀:[]。

發(fā)現(xiàn)另一個(gè)異常。一個(gè)變量節(jié)點(diǎn)在首次創(chuàng)建時(shí),它的值基本上就是“null”,任何嘗試對(duì)它進(jìn)行計(jì)算的操作都會(huì)拋出這個(gè)異常。我們只能先給一個(gè)變量賦值后才能用它做計(jì)算。有兩種主要方法可以用于給變量賦值:初始化器和 tf.assign ()。我們先看看 tf.assign ():

與我們迄今為止看到的節(jié)點(diǎn)相比,tf.assign (target,value) 有一些獨(dú)特的屬性:

標(biāo)識(shí)操作。tf.assign (target,value) 不做任何計(jì)算,它總是與 value 相等。

副作用。當(dāng)計(jì)算“流經(jīng)”assign_node 時(shí),就會(huì)給圖中的其他節(jié)點(diǎn)帶來副作用。在這種情況下,副作用就是用保存在 zero_node 中的值替換 count_variable 的值。

非依賴邊。即使 count_variable 節(jié)點(diǎn)和 assign_node 在圖中是相連的,兩者都不依賴于其他節(jié)點(diǎn)。這意味著在計(jì)算任一節(jié)點(diǎn)時(shí),計(jì)算不會(huì)通過該邊回流。不過,assign_node 依賴 zero_node,它需要知道要分配什么。

“副作用”節(jié)點(diǎn)充斥在大部分 Tensorflow 深度學(xué)習(xí)工作流中,因此,請(qǐng)確保你對(duì)它們了解得一清二楚。當(dāng)我們調(diào)用 sess.run (assign_node) 時(shí),計(jì)算路徑將經(jīng)過 assign_node 和 zero_node。

當(dāng)計(jì)算流經(jīng)圖中的任何節(jié)點(diǎn)時(shí),它還會(huì)讓該節(jié)點(diǎn)控制的副作用(綠色所示)起效。由于 tf.assign 的特殊副作用,與 count_variable(之前為“null”)關(guān)聯(lián)的內(nèi)存現(xiàn)在被永久設(shè)置為 0。這意味著,當(dāng)我們下一次調(diào)用 sess.run (count_variable) 時(shí),不會(huì)拋出任何異常。相反,我們將得到 0。

接下來,讓我們來看看初始化器:

這里都發(fā)生了什么?為什么初始化器不起作用?

問題在于會(huì)話和圖之間的分隔。我們已經(jīng)將 get_variable 的 iniTIalizer 屬性指向 const_init_node,但它只是在圖中的節(jié)點(diǎn)之間添加了一個(gè)新的連接。我們還沒有做任何與導(dǎo)致異常有關(guān)的事情:與變量節(jié)點(diǎn)(保存在會(huì)話中,而不是圖中)相關(guān)聯(lián)的內(nèi)存仍然為“null”。我們需要通過會(huì)話讓 const_init_node 更新變量。

為此,我們添加了另一個(gè)特殊節(jié)點(diǎn):init = tf.global_variables_iniTIalizer ()。與 tf.assign () 類似,這是一個(gè)帶有副作用的節(jié)點(diǎn)。與 tf.assign () 不一樣的是,我們實(shí)際上并不需要指定它的輸入!tf.global_variables_iniTIalizer () 將在其創(chuàng)建時(shí)查看全局圖,自動(dòng)將依賴關(guān)系添加到圖中的每個(gè) tf.initializer 上。當(dāng)我們調(diào)用 sess.run (init) 時(shí),它會(huì)告訴每個(gè)初始化器完成它們的任務(wù),初始化變量,這樣在調(diào)用 sess.run (count_variable) 時(shí)就不會(huì)出錯(cuò)。

變量共享

你可能會(huì)碰到帶有變量共享的 Tensorflow 代碼,代碼有它們的作用域,并設(shè)置“reuse=True”。我強(qiáng)烈建議你不要在代碼中使用變量共享。如果你想在多個(gè)地方使用單個(gè)變量,只需要使用指向該變量節(jié)點(diǎn)的指針,并在需要時(shí)使用它。換句話說,對(duì)于打算保存在內(nèi)存中的每個(gè)參數(shù),應(yīng)該只調(diào)用一次 tf.get_variable ()。

優(yōu)化器

最后:進(jìn)行真正的深度學(xué)習(xí)!如果你還在狀態(tài),那么其余的概念對(duì)于你來說應(yīng)該是非常簡(jiǎn)單的。

在深度學(xué)習(xí)中,典型的“內(nèi)循環(huán)”訓(xùn)練如下:

獲取輸入和 true_output

根據(jù)輸入和參數(shù)計(jì)算出一個(gè)“猜測(cè)”

根據(jù)猜測(cè)和 true_output 之間的差異計(jì)算出一個(gè)“損失”

根據(jù)損失的梯度更新參數(shù)

讓我們把所有東西放在一個(gè)腳本里,解決一個(gè)簡(jiǎn)單的線性回歸問題:

正如你所看到的,損失基本上沒有變化,而且我們對(duì)真實(shí)參數(shù)有了很好的估計(jì)。這部分代碼只有一兩行對(duì)你來說是新的:

既然你對(duì) Tensorflow 的基本概念已經(jīng)有了很好的理解,這段代碼應(yīng)該很容易解釋!第一行,optimizer = tf.train.GradientDescentOptimizer (1e-3) 不會(huì)向圖中添加節(jié)點(diǎn)。它只是創(chuàng)建了一個(gè) Python 對(duì)象,包含了一些有用的函數(shù)。第二行 train_op = optimizer.minimize (loss),將一個(gè)節(jié)點(diǎn)添加到圖中,并將一個(gè)指針賦給 train_op。train_op 節(jié)點(diǎn)沒有輸出,但有一個(gè)非常復(fù)雜的副作用:

train_op 回溯其輸入的計(jì)算路徑,尋找變量節(jié)點(diǎn)。對(duì)于找到的每個(gè)變量節(jié)點(diǎn),它計(jì)算與損失相關(guān)的變量梯度。然后,它為該變量計(jì)算新值:當(dāng)前值減去梯度乘以學(xué)習(xí)率。最后,它執(zhí)行一個(gè)賦值操作來更新變量的值。

基本上,當(dāng)我們調(diào)用 sess.run (train_op) 時(shí),它為我們對(duì)所有的變量做了一個(gè)梯度下降的操作。當(dāng)然,我們還需要使用 feed_dict 來填充輸入和輸出占位符,并且我們還希望打印這些損失,因?yàn)檫@樣方便調(diào)試。

用 tf.Print 進(jìn)行調(diào)試

當(dāng)你開始使用 Tensorflow 做更復(fù)雜的事情時(shí),你需要進(jìn)行調(diào)試。一般來說,檢查計(jì)算圖中發(fā)生了什么是很困難的。你不能使用常規(guī)的 Python 打印語句,因?yàn)槟阌肋h(yuǎn)無法訪問到要打印的值——它們被鎖定在 sess.run () 調(diào)用中。舉個(gè)例子,假設(shè)你想檢查一個(gè)計(jì)算的中間值,在調(diào)用 sess.run () 之前,中間值還不存在。但是,當(dāng) sess.run () 調(diào)用返回時(shí),中間值不見了!

我們來看一個(gè)簡(jiǎn)單的例子。

我們看到了結(jié)果是 5。但是,如果我們想檢查中間值 two_node 和 three_node,該怎么辦?檢查中間值的一種方法是向 sess.run () 添加一個(gè)返回參數(shù),該參數(shù)指向要檢查的每個(gè)中間節(jié)點(diǎn),然后在返回后打印它。

這樣做通常沒有問題,但當(dāng)代碼變得越來越復(fù)雜時(shí),這可能有點(diǎn)尷尬。更方便的方法是使用 tf.Print 語句。令人困惑的是,tf.Print 實(shí)際上是 Tensorflow 的一種節(jié)點(diǎn),它有輸出和副作用!它有兩個(gè)必需的參數(shù):一個(gè)要復(fù)制的節(jié)點(diǎn)和一個(gè)要打印的內(nèi)容列表。“要復(fù)制的節(jié)點(diǎn)”可以是圖中的任何節(jié)點(diǎn),tf.Print 是與“要復(fù)制的節(jié)點(diǎn)”相關(guān)的標(biāo)識(shí)操作,也就是說,它將輸出其輸入的副本。不過,它有個(gè)副作用,就是會(huì)打印“打印清單”里所有的值。

有關(guān) tf.Print 的一個(gè)重要卻有些微妙的點(diǎn):打印其實(shí)只是它的一個(gè)副作用。與所有其他副作用一樣,只有在計(jì)算流經(jīng) tf.Print 節(jié)點(diǎn)時(shí)才會(huì)進(jìn)行打印。如果 tf.Print 節(jié)點(diǎn)不在計(jì)算路徑中,則不會(huì)打印任何內(nèi)容。即使 tf.Print 節(jié)點(diǎn)正在復(fù)制的原始節(jié)點(diǎn)位于計(jì)算路徑上,但 tf.Print 節(jié)點(diǎn)本身可能不是。這個(gè)問題要注意!當(dāng)這種情況發(fā)生時(shí),它會(huì)讓你感到非常沮喪,你需要費(fèi)力地找出問題所在。一般來說,最好在創(chuàng)建要復(fù)制的節(jié)點(diǎn)后立即創(chuàng)建 tf.Print 節(jié)點(diǎn)。

結(jié)論

希望這篇文章能夠幫助你更好地理解 Tensorflow,了解它的工作原理以及如何使用它。畢竟,這里介紹的概念對(duì)所有 Tensorflow 程序來說都很重要,但這些還都只是表面上的東西。在你的 Tensorflow 探險(xiǎn)之旅中,你可能會(huì)遇到各種你想要使用的其他有趣的東西:條件、迭代、分布式 Tensorflow、變量作用域、保存和加載模型、多圖、多會(huì)話和多核數(shù)據(jù)加載器隊(duì)列等。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉