令人困惑的TensorFlow!

2020-12-11 機器之心Pro

選自jacobbuckman.com

作者:Jacob Buckman

機器之心編譯

雖然對於大多數人來說 TensorFlow 的開發語言是 Python,但它並不是一個標準的 Python 庫。這個神經網絡框架通過構建「計算圖」來運行,對於很多新手來說,在理解其邏輯時會遇到很多困難。本文中,來自谷歌大腦的工程師 Jacob Buckman 將試圖幫你解決初遇 TensorFlow 時你會遇到的麻煩。

導論

這是什麼?我是誰?

我叫 Jacob,是 Google AI Resident 項目的研究學者。我是在 2017 年夏天加入該項目的,儘管已經擁有了豐富的編程經驗,並且對機器學習的理解也很深刻,但此前我從未使用過 TensorFlow。當時我覺得憑我的能力應該很快就能上手。但讓我沒想到的是,學習曲線相當的陡峭,甚至在加入該項目幾個月後,我還偶爾對如何使用 TensorFlow 代碼來實現想法感到困惑。我把這篇博文當作瓶中信寫給過去的自己:一篇我希望在學習之初能被給予的入門介紹。我希望這篇博文也能幫助到其他人。

以往的教程缺少了那些內容?

自 TensorFlow 發布的三年以來,其已然成為深度學習生態系統中的一塊基石。然而對於初學者來說,它可能並不直觀,特別是與 PyTorch 或 DyNet 這樣運行即定義的神經網絡庫相比。

市面上有許多 TensorFlow 的入門教程,包含從線性回歸到 MNIST 分類和機器翻譯的內容。這些具體實用的指南是使 TensorFlow 項目啟動並運行的良好資源,同時可以作為類似項目的切入點。但對於有些應用開發人員而言,他們開發的應用並沒有好的教程,或對於那些想打破常規的人(在研究中很常見)而言,剛接觸 TensorFlow 肯定是讓人沮喪的。

我試圖通過這篇文章去填補這個空白。我沒有專注於某個特定的任務,而是提出更一般的方法,並解析 TensorFlow 背後基礎的抽象概念。掌握好這些概念之後,用 TensorFlow 進行深度學習就會變得直觀易懂。

目標受眾

本教程適用於那些在編程和機器學習方面有一定經驗,並想要學習 TensorFlow 的人。例如:一位想在機器學習課程的最後一個項目中使用 TensorFlow 的計算機科學專業的學生;一位剛被分配到涉及深度學習項目的軟體工程師;或是一位處於困惑中的新的 Google AI Resident 新手(向過去的 Jacob 大聲打招呼)。如果你想進一步了解基礎知識,請參閱以下資源:

https://ml.berkeley.edu/blog/2016/11/06/tutorial-1/http://colah.github.io/https://www.udacity.com/course/intro-to-machine-learning—ud120https://www.coursera.org/learn/machine-learning

我們就開始吧!

理解 TensorFlow

TensorFlow 不是一個標準的 Python 庫

大多數 Python 庫被編寫為 Python 的自然擴展形式。當你導入一個庫時,你得到的是一組變量、函數和類,他們擴展並補充了你的代碼「工具箱」。當你使用它們時,你能預期到返回的結果是怎樣的。在我看來,當談及 TensorfFlow 時,應該把這種認知完全拋棄。思考什麼是 TensorFlow 及其如何與其他代碼進行交互從根本上來說就是錯誤的。

Python 和 TensorFlow 之間的關係可以類比 Javascript 和 HTML 之間的關係。Javascript 是一種全功能的程式語言,可以做各種美妙的事情。HTML 是用於表示某種類型的實用計算抽象(此處指可由 Web 瀏覽器呈現的內容)的框架。Javascript 在交互式網頁中的作用是組裝瀏覽器看到的 HTML 對象,然後在需要時通過將其更新為新的 HTML 來與其交互。

與 HTML 類似,TensorFlow 是用於表示某種類型的計算抽象(稱為「計算圖」)的框架。但我們用 Python 操作 TensorFlow 時,我們用 Pyhton 代碼做的第一件事就是構建計算圖。一旦完成,我們做的第二件事就是與它進行交互(啟動 TensorFlow 的「會話」)。但重要的是,要記住計算圖不在變量內部;而是處在全局命名空間中。正如莎士比亞所說:「所有的 RAM 都是一個階段,所有的變量都僅僅是指針」

第一個關鍵抽象:計算圖

當你在瀏覽 TensorFlow 文檔時,可能會發現對「圖形」和「節點」的間接引用。如果你仔細閱讀,你甚至可能已經發現了這個頁面(https://www.tensorflow.org/programmers_guide/graphs),該頁面涵蓋了我將以更準確和技術化的方式去解釋的內容。本節是一篇高級攻略,把握重要的直覺概念,同時忽略一些技術細節。

那麼:什麼是計算圖?它本質上是一個全局數據結構:是一個有向圖,用於捕獲有關如何計算的指令。

讓我們來看看構建計算圖的一個示例。在下圖中,上半部分是我們運行的代碼及其輸出,下半部分是生成的計算圖。

import tensorflow as tf

計算圖:

可見,僅僅導入 TensorFlow 並不會給我們生成一個有趣的計算圖。而只是一個單獨的,空白的全局變量。但當我們調用一個 TensorFlow 操作時,會發生什麼?

代碼:

import tensorflow as tftwo_node = tf.constant(2)print two_node

輸出:

Tensor("Const:0", shape=(), dtype=int32)

計算圖:

快看!我們得到了一個節點。它包含常量 2。很驚訝吧,這來自於一個名為 tf.constant 的函數。當我們列印這個變量時,我們看到它返回一個 tf.Tensor 對象,它是一個指向我們剛剛創建的節點的指針。為了強調這一點,以下是另外一個示例:

代碼:

import tensorflow as tftwo_node = tf.constant(2)another_two_node = tf.constant(2)two_node = tf.constant(2)tf.constant(3)

計算圖:

每次我們調用 tf.constant 時,我們都會在圖中創建一個新的節點。即使該節點的功能與現有節點相同,即使我們將節點重新分配給同一個變量,或者即使我們根本沒有將其分配給一個變量,結果都是一樣的。

代碼:

import tensorflow as tftwo_node = tf.constant(2)another_pointer_at_two_node = two_nodetwo_node = Noneprint two_nodeprint another_pointer_at_two_node

輸出:

NoneTensor("Const:0", shape=(), dtype=int32)

計算圖:

好啦,讓我們更進一步:

代碼:

import tensorflow as tftwo_node = tf.constant(2)three_node = tf.constant(3)sum_node = two_node + three_node ## equivalent to tf.add(two_node, three_node)

計算圖:

現在我們正談論—這才是我們真正想要的計算圖!請注意,+ 操作在 TensorFlow 中過載,因此同時添加兩個張量會在圖中增加一個節點,儘管它表面上看起來不像是 TensorFlow 操作。

那好,所以 two_node 指向包含 2 的節點,three_node 指向包含 3 的節點,同時 sum_node 指向包含 ...+ 的節點?怎麼回事?它不是應該包含 5 嗎?

事實證明,並沒有。計算圖只包含計算步驟;不包含結果。至少……現在還沒有!

第二個關鍵抽象: 會話

如果錯誤地理解 TensorFlow 抽象概念也有個「瘋狂三月」(NCAA 籃球錦標賽,大部分在三月進行),那麼會話將成為每年的一號種子選手。會話有著那樣令人困惑的殊榮是因為其反直覺的命名卻又普遍存在—幾乎每個 TensorFlow 呈現都至少一次明確地調用 tf.Session()。

會話的作用是處理內存分配和優化,使我們能夠實際執行由計算圖指定的計算。你可以將計算圖想像為我們想要執行的計算的「模版」:它列出了所有步驟。為了使用計算圖,我們需要啟動一個會話,它使我們能夠實際地完成任務;例如,遍歷模版的所有節點來分配一堆用於存儲計算輸出的存儲器。為了使用 TensorFlow 進行各種計算,你既需要計算圖也需要會話。

會話包含一個指向全局圖的指針,該指針通過指向所有節點的指針不斷更新。這意味著在創建節點之前還是之後創建會話都無所謂。

創建會話對象後,可以使用 sess.run(node) 返回節點的值,並且 TensorFlow 將執行確定該值所需的所有計算。

代碼:

import tensorflow as tftwo_node = tf.constant(2)three_node = tf.constant(3)sum_node = two_node + three_nodesess = tf.Session()print sess.run(sum_node)

輸出:

5

計算圖:

太好了!我們也可以傳遞一個列表,sess.run([node1, node2, ...]),並讓它返回多個輸出:

代碼:

import tensorflow as tftwo_node = tf.constant(2)three_node = tf.constant(3)sum_node = two_node + three_nodesess = tf.Session()print sess.run([two_node, sum_node])

輸出:

[2, 5]

計算圖:

一般來說,sess.run() 的調用往往是 TensorFlow 最大的瓶頸之一,因此調用它的次數越少越好。如果可以的話,在一個 sess.run() 的調用中返回多個項目,而不是進行多個調用。

佔位符和 feed_dict

迄今為止,我們所做的計算一直很乏味:沒有機會獲得輸入,所以它們總是輸出相同的東西。一個更有價值的應用可能涉及構建一個計算圖,它接受輸入,以某種(一致)方式處理它,並返回一個輸出。

最直接的方法是使用佔位符。佔位符是一種用於接受外部輸入的節點。

代碼:

import tensorflow as tfinput_placeholder = tf.placeholder(tf.int32)sess = tf.Session() print sess.run(input_placeholder)

輸出:

Traceback (most recent call last):...InvalidArgumentError (see above *for* traceback): You must feed a value *for* placeholder tensor 'Placeholder' *with* dtype int32 [[Node: Placeholder = Placeholder[dtype=DT_INT32, shape=, _device="/job:localhost/replica:0/task:0/device:CPU:0"]()]]

計算圖:

... 這是一個糟糕的例子,因為它引發了一個異常。佔位符預計會被賦予一個值。但我們沒有提供一個值,所以 TensorFlow 崩潰了。

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

代碼:

import tensorflow as tf input_placeholder = tf.placeholder(tf.int32) sess = tf.Session() print sess.run(input_placeholder, feed_dict={input_placeholder: 2})

輸出:

2

計算圖:

這就好多了。注意傳遞給 feed_dict 的 dict 格式,其關鍵應該是與圖中的佔位符節點相對應的變量(如前所述,它實際上意味著指向圖中佔位符節點的指針)。相應的值是要分配給每個佔位符的數據元素——通常是標量或 Numpy 數組。

第三個關鍵抽象:計算路徑

讓我們看看另一個使用佔位符的示例:

代碼:

import tensorflow as tfinput_placeholder = tf.placeholder(tf.int32)three_node = tf.constant(3)sum_node = input_placeholder + three_nodesess = tf.Session()print sess.run(three_node)print sess.run(sum_node)

輸出:

3Traceback (most recent call last):...InvalidArgumentError (see above for traceback): You must feed a value *for* placeholder tensor 'Placeholder_2' with dtype int32 [[Node: Placeholder_2 = Placeholder[dtype=DT_INT32, shape=, _device="/job:localhost/replica:0/task:0/device:CPU:0"]()]]

計算圖:

為什麼第二次調用 sess.run() 會失敗?即使我們沒有評估 input_placeholder,為什麼仍會引發與 input_placeholder 相關的錯誤?答案在於最終的關鍵 TensorFlow 抽象:計算路徑。幸運的是,這個抽象非常直觀。

當我們在依賴於圖中其他節點的節點上調用 sess.run() 時,我們也需要計算那些節點的值。如果這些節點具有依賴關係,那麼我們需要計算這些值(依此類推……),直到達到計算圖的「頂端」,即節點沒有父節點時。

sum_node 的計算路徑:

所有三個節點都需要進行求值以計算 sum_node 的值。最重要的是,這包含了我們未填充的佔位符,並解釋了異常!

現在來看 three_node 的計算路徑:

根據圖結構,我們不需要計算所有節點才能評估我們想要的節點!因為我們在評估 three_node 時不需要評估 placehoolder_node,所以運行 sess.run(three_node) 不會引發異常。

TensorFlow 僅通過必需的節點自動進行計算這一事實是該框架的一個巨大優勢。如果計算圖非常大並且有許多不必要的節點,那麼它可以節省大量調用的運行時間。它允許我們構建大型的「多用途」計算圖,這些計算圖使用單個共享的核心節點集合,並根據所採取的不同計算路徑去做不同的事情。對於幾乎所有應用而言,根據所採取的計算路徑考慮 sess.run() 的調用是很重要的。

變量 & 副作用

至此,我們已經看到兩種類型的「無祖先」節點(no-ancestor node):每次運行都一樣的 tf.constant 和每次運行都不一樣的 tf.placeholder。我們常常要考慮第三種情況:一個通常在運行時保持值不變的節點也可以被更新為新值。

這時就需要引入變量。

變量對於使用 TensorFlow 進行深度學習是至關重要的,因為模型的參數就是變量。在訓練期間,你希望通過梯度下降在每個步驟更新參數;但在評估時,你希望保持參數不變,並將大量不同的測試集輸入模型。通常,模型所有可訓練參數都是變量。

要創建變量,就需要使用 tf.get_variable()。tf.get_variable() 的前兩個參數是必需的,其餘參數是可選的。它們是 tf.get_variable(name,shape)。name 是一個唯一標識這個變量對象的字符串。它必須相對於全局圖是唯一的,所以要明了你使用過的所有命名,確保沒有重複。shape 是與張量形狀對應的整數數組,它的語法非常直觀:按順序,每個維度只有一個整數。例如,一個 3x8 矩陣形狀是 [3, 8]。要創建一個標量,就需要使用形狀為 [] 的空列表。

代碼:

import tensorflow as tfcount_variable = tf.get_variable("count", [])sess = tf.Session()print sess.run(count_variable)

輸出:

Traceback (most recent call last):...tensorflow.python.framework.errors_impl.FailedPreconditionError: Attempting to use uninitialized value count [[Node: _retval_count_0_0 = _Retval[T=DT_FLOAT, index=0, _device="/job:localhost/replica:0/task:0/device:CPU:0"](count)]]

計算圖:

噫,另一個異常。當首次創建變量節點時,它的值基本上為「null」,並且任何試圖對它求值的操作都會引發這個異常。我們只能在將值放入變量之後才能對其求值。主要有兩種將值放入變量的方法:初始化器和 tf.assign()。我們先看看 tf.assign():

代碼:

import tensorflow as tfcount_variable = tf.get_variable("count", [])zero_node = tf.constant(0.)assign_node = tf.assign(count_variable, zero_node)sess = tf.Session()sess.run(assign_node)print sess.run(count_variable)

輸出:

0

計算圖:

與我們迄今為止見過的節點相比,tf.assign(target, value) 是具備一些獨特屬性:

恆等運算。tf.assign(target, value) 不做任何有趣的運算,通常與 value 相等。副作用。當計算「流經」assign_node 時,副作用發生在圖中的其他節點上。此時,副作用是用存儲在 zero_node 中的值替換 count_variable 的值。非依賴邊。即使 count_variable 節點和 assign_node 在圖中是相連的,但它們彼此獨立。這意味著計算任一節點時,計算不會通過邊回流。然而,assign_node 依賴於 zero_node,它需要知道分配了什麼。

「副作用」節點支撐著大部分 Tensorflow 深度學習工作流程,所以請確保自己真正理解了在該節點發生的事情。當我們調用 sess.run(assign_node) 時,計算路徑會通過 assign_node 和 zero_node。

計算圖:

當計算流經圖中的任何節點時,它還會執行由該節點控制的任何副作用,如圖中綠色所示。由於 tf.assign 的特殊副作用,與 count_variable(之前為「null」)關聯的內存現在被永久設置為 0。這意味著當我們下一次調用 sess.run(count_variable) 時,不會引發任何異常。相反,我們會得到 0 值。成功!

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

代碼:

import tensorflow as tfconst_init_node = tf.constant_initializer(0.)count_variable = tf.get_variable("count", [], initializer=const_init_node)sess = tf.Session()print sess.run([count_variable])

輸出:

Traceback (most recent call last):...tensorflow.python.framework.errors_impl.FailedPreconditionError: Attempting to use uninitialized value count [[Node: _retval_count_0_0 = _Retval[T=DT_FLOAT, index=0, _device="/job:localhost/replica:0/task:0/device:CPU:0"](count)]]

計算圖:

那好,這裡發生了什麼?為什麼初始化器不工作?

問題出現在會話和圖之間的分離。我們已將 get_variable 的 initializer 屬性設置為指向 const_init_node,但它只是在圖中的節點之間添加了一個新的連接。我們還沒有做任何解決異常根源的事:與變量節點(存儲在會話中,而不是計算圖中)相關聯的內存仍然設置為「null」。我們需要通過會話使 const_init_node 去更新變量。

代碼:

import tensorflow as tfconst_init_node = tf.constant_initializer(0.)count_variable = tf.get_variable("count", [], initializer=const_init_node)init = tf.global_variables_initializer()sess = tf.Session()sess.run(init)print sess.run(count_variable)

輸出:

0

計算圖:

為此,我們添加另一個特殊的節點:init = tf.global_variables_initializer()。與 tf.assign() 類似,這是一個帶有副作用的節點。與 tf.assign() 相反,實際上我們不需要指定它的輸入是什麼!tf.global_variables_initializer() 將在其創建時查看全局圖並自動將依賴關係添加到圖中的每個 tf.initializer。當我們在之後使用 sess.run(init) 對它求值時,它會告訴每個初始化程序執行變量初始化,並允許我們運行 sess.run(count_variable) 而不出錯。

變量共享

你可能會遇到帶有變量共享的 Tensorflow 代碼,其涉及創建作用域並設置「reuse = True」。我強烈建議不要在自己的代碼中使用變量共享。如果你想在多個地方使用單個變量,只需以編程方式記錄指向該變量節點的指針,並在需要時重新使用它。換言之,對於想要保存在內存中的每個變量,你只需要調用一次 tf.get_variable()。

優化器

最後:進行真正的深度學習!如果你跟上我的節奏,那麼其餘概念對你來說應該非常簡單。

在深度學習中,典型的「內循環」訓練如下:

1. 獲取輸入和 true_output

2. 根據輸入和參數計算「推測」值

3. 根據推測與 true_output 之間的差異計算「損失」

4. 根據損失的梯度更新參數

讓我們把所有東西放在一個快速腳本裡,解決簡單的線性回歸問題:

代碼:

import tensorflow as tf### build the graph## first set up the parametersm = tf.get_variable("m", [], initializer=tf.constant_initializer(0.))b = tf.get_variable("b", [], initializer=tf.constant_initializer(0.))init = tf.global_variables_initializer()## then set up the computationsinput_placeholder = tf.placeholder(tf.float32)output_placeholder = tf.placeholder(tf.float32)x = input_placeholdery = output_placeholdery_guess = m * x + bloss = tf.square(y - y_guess)## finally, set up the optimizer and minimization nodeoptimizer = tf.train.GradientDescentOptimizer(1e-3)train_op = optimizer.minimize(loss)### start the sessionsess = tf.Session()sess.run(init)### perform the training loop*import* random## set up problemtrue_m = random.random()true_b = random.random()*for* update_i *in* range(100000): ## (1) get the input and output input_data = random.random() output_data = true_m * input_data + true_b ## (2), (3), and (4) all take place within a single call to sess.run()! _loss, _ = sess.run([loss, train_op], feed_dict={input_placeholder: input_data, output_placeholder: output_data}) *print* update_i, _loss### finally, print out the values we learned for our two variables*print* "True parameters: m=%.4f, b=%.4f" % (true_m, true_b)*print* "Learned parameters: m=%.4f, b=%.4f" % tuple(sess.run([m, b]))

輸出:

0 2.32053831 0.57927422 1.552543 1.57332594 0.64356485 2.40612656 1.07462567 2.19987158 1.67751169 1.646242310 2.441034...99990 2.9878322e-1299991 5.158629e-1199992 4.53646e-1199993 9.422685e-1299994 3.991829e-1199995 1.134115e-1199996 4.9467985e-1199997 1.3219648e-1199998 5.684342e-1499999 3.007017e-11*True* parameters: m=0.3519, b=0.3242Learned parameters: m=0.3519, b=0.3242

就像你看到的一樣,損失基本上變為零,並且我們對真實參數進行了很好的估計。我希望你只對代碼中的以下部分感到陌生:

## finally, set up the optimizer and minimization nodeoptimizer = tf.train.GradientDescentOptimizer(1e-3)train_op = optimizer.minimize(loss)

但是,既然你對 Tensorflow 的基本概念有了很好的理解,這段代碼就很容易解釋!第一行,optimizer = tf.train.GradientDescentOptimizer(1e-3) 不會向計算圖中添加節點。它只是創建一個包含有用的幫助函數的 Python 對象。第二行,train_op = optimizer.minimize(loss) 將一個節點添加到圖中,並將一個指針存儲在變量 train_op 中。train_op 節點沒有輸出,但是有一個十分複雜的副作用:

train_op 回溯輸入和損失的計算路徑,尋找變量節點。對於它找到的每個變量節點,計算該變量對於損失的梯度。然後計算該變量的新值:當前值減去梯度乘以學習率的積。最後,它執行賦值操作更新變量的值。

因此基本上,當我們調用 sess.run(train_op) 時,它對我們的所有變量做了一個梯度下降的步驟。當然,我們也需要使用 feed_dict 填充輸入和輸出佔位符,並且我們還希望列印損失的值,因為這樣方便調試。

用 tf.Print 調試

當你用 Tensorflow 開始做更複雜的事情時,你需要進行調試。一般來說,檢查計算圖中發生了什麼是相當困難的。因為你永遠無法訪問你想列印的值—它們被鎖定在 sess.run() 的調用中,所以你不能使用常規的 Python 列印語句。具體來說,假設你是想檢查一個計算的中間值。在調用 sess.run() 之前,中間值還不存在。但是,當你調用的 sess.run() 返回時,中間值又不見了!

讓我們看一個簡單的示例。

代碼:

import tensorflow as tftwo_node = tf.constant(2)three_node = tf.constant(3)sum_node = two_node + three_nodesess = tf.Session()print sess.run(sum_node)

輸出:

5

這讓我們看到了答案是 5。但是,如果我們想要檢查中間值,two_node 和 three_node,怎麼辦?檢查中間值的一個方法是向 sess.run() 中添加一個返回參數,該參數指向要檢查的每個中間節點,然後在返回後,列印它的值。

代碼:

import tensorflow as tftwo_node = tf.constant(2)three_node = tf.constant(3)sum_node = two_node + three_nodesess = tf.Session()answer, inspection = sess.run([sum_node, [two_node, three_node]])print inspectionprint answer

輸出:

[2, 3]5

這通常是有用的,但當代碼變得越來越複雜時,這可能有點棘手。一個更方便的方法是使用 tf.Print 語句。令人困惑的是,tf.Print 實際上是一種具有輸出和副作用的 Tensorflow 節點!它有兩個必需參數:要複製的節點和要列印的內容列表。「要複製的節點」可以是圖中的任何節點;tf.Print 是一個與「要複製的節點」相關的恆等操作,意味著輸出的是輸入的副本。但是,它的副作用是列印出「列印列表」裡的所有當前值。

代碼:

import tensorflow as tftwo_node = tf.constant(2)three_node = tf.constant(3)sum_node = two_node + three_nodeprint_sum_node = tf.Print(sum_node, [two_node, three_node])sess = tf.Session()print sess.run(print_sum_node)

輸出:

[2][3]5

計算圖:

有關 tf.Print 一個重要且有點微妙的點:列印是一個副作用。像所有其他副作用一樣,只要在計算流經 tf.Print 節點時才會進行列印。如果 tf.Print 節點不在計算路徑上,則不會列印任何內容。特別的是,即使 tf.Print 節點正在複製的原始節點位於計算路徑上,但 tf.Print 節點本身可能不在。請注意這個問題!當這種情況發生時(總會發生的),如果你沒有明確地找到問題所在,它會讓你感到十分沮喪。一般來說,最好在創建要複製的節點後,立即創建你的 tf.Print 節點。

代碼:

import tensorflow as tftwo_node = tf.constant(2)three_node = tf.constant(3)sum_node = two_node + three_node### this new copy of two_node is not on the computation path, so nothing prints!print_two_node = tf.Print(two_node, [two_node, three_node, sum_node])sess = tf.Session() print sess.run(sum_node)

輸出:

5

計算圖:

這裡有一個很好的資源(https://wookayin.github.io/tensorflow-talk-debugging/#1),它提供了其他一些實用的調試建議。

結論

希望這篇博文可以幫助你更好地理解什麼是 Tensorflow,它是如何工作的以及怎麼使用它。總而言之,本文介紹的概念對所有 Tensorflow 項目都很重要,但只是停留在表面。在你探索 Tensorflow 的旅程中,你可能會遇到其他各種你需要的有趣概念:條件、迭代、分布式 Tensorflow、變量作用域、保存和加載模型、多圖、多會話和多核、數據加載器隊列等等。我將在未來的博文中討論這些主題。但如果你使用官方文檔、一些代碼示例和一點深度學習的魔力來鞏固你在本文學到的思想,我相信你一定可以弄明白 Tensorflow!

相關焦點

  • tensorflow安裝教程
    tensorflow是谷歌開源的人工智慧庫,有最完善的生態支持。是進行人工智慧領域開發和科研的必備工具。本文在windows10下,藉助anacondaAnaconda安裝和使用,AkShare入門,安裝tensorflow2.0。
  • TensorFlow應用實戰 | TensorFlow基礎知識
    dtypeTensorFlow.datatype listhttps://www.tensorflow.org/api_docs/python/tf/DType# -*- coding: UTF-8 -*-# 引入tensorflowimport tensorflow as tf# 設置了gpu加速提示信息太多了,設置日誌等級屏蔽一些import osos.environ['TF_CPP_MIN_LOG_LEVEL']='2'# 創建兩個常量 Tensor.第一個為
  • TensorFlow極速入門
    最後給出了在 tensorflow 中建立一個機器學習模型步驟,並用一個手寫數字識別的例子進行演示。1、tensorflow是什麼?tensorflow 是 google 開源的機器學習工具,在2015年11月其實現正式開源,開源協議Apache 2.0。
  • tensorflow極速入門
    最後給出了在 tensorflow 中建立一個機器學習模型步驟,並用一個手寫數字識別的例子進行演示。1、 tensorflow是什麼?tensorflow 是 google 開源的機器學習工具,在2015年11月其實現正式開源,開源協議Apache 2.0。下圖是 query 詞頻時序圖,從中可以看出 tensorflow 的火爆程度。
  • Anaconda軟體安裝TensorFlow教程
    Anaconda軟體的安裝,請閱讀文章《Anaconda軟體安裝和簡易使用教程》第一步:創建r-tensorflow環境打開Anaconda Prompt,執行命令conda create --name r-tensorflow python=3.6該命令用來創建r-tensorflow虛擬環境
  • Windows配置tensorflow開發環境
    通過這篇文章,希望能夠幫助大家更加順利地配置tensorflow的開發環境。4、測試tensorflow是否可用可通過兩種方式測試tensorflow:(1)通過Anaconda Prompt窗口:首先,激活tensorflow環境。
  • tensorflow機器學習模型的跨平臺上線
    生成的模型,但是由於tensorflow模型往往較大,使用無法優化的PMML文件大多數時候很笨拙,因此本文我們專門討論下tensorflow機器學習模型的跨平臺上線的方法。tensorflow模型的跨平臺上線的備選方案tensorflow模型的跨平臺上線的備選方案一般有三種:即PMML方式,tensorflow serving方式,以及跨語言API方式。PMML方式的主要思路在上一篇以及講過。
  • TensorFlow發布JavaScript開發者的機器學習框架TensorFlow.js
    發布新的 TensorFlow 官方博客(http://blog.tensorflow.org/)與 TensorFlow YouTube 頻道;2. 面向 JavaScript 開發者的全新機器學習框架 TensorFlow.js;3.
  • Windows上安裝Tensorflow踩的坑
    安裝了,不免想試試在自己的Windows上用R跑跑tensorflow的。安裝tensorflow R 包devtools::install_github("rstudio/tensorflow")載入TensorFlowSys.setenv(TENSORFLOW_PYTHON="/usr/local/bin/python")library(tensorflow)驗證安裝
  • 【TensorFlow超級指南】你能想到的TF教程和資源都在這裡了
    Jacob Buckman—《TensorFlow:令人困惑的部分(1)》:https://jacobbuckman.com/post/tensorflow-the-confusing-parts-1/
  • 運行tensorflow2.0出錯
    今天在調試tf2.0的代碼的時候,Console丟了一個錯誤出來:AttributeError: module 'tensorflow'
  • TensorFlow圖像分類教程
    docker run -v /path/to/local:/notebooks/local --rm -it --name tensorflow tensorflow/tensorflow:nightly /bin/bash-v /path/to/local:/notebooks/local將剛創建的local目錄掛載到容器中適當的位置。
  • TensorFlow學習
    ,學習內容為tensorflow!if activation_function is None:        outputs = Wx_plus_b    else:        outputs = activation_function(Wx_plus_b)返回輸出return outputs完整函數import tensorflow
  • TensorFlow 安裝詳解
    節點(Nodes)在圖中表示數學操作,圖中的線(edges)則表示在節點間相互聯繫的多維數據數組,即張量(tensor)。它靈活的架構讓你可以在多種平臺上展開計算,例如臺式計算機中的一個或多個 CPU(或GPU),伺服器,行動裝置等等。
  • 基於TensorFlow的深度學習實戰
    為了將環境建在 ~/tensorflow 目錄下, 執行:$ virtualenv --system-site-packages ~/tensorflow接下來激活virtualenv:$ source ~/tensorflow/bin/activate #  with bash $ source ~/tensorflow/bin/activate.csh
  • TensorFlow 的簡單例子 | Linux 中國
    import numpy as npimport tensorflow as tfarr = np.array([1, 5.5, 3, 15, 20])tensor = tf.convert_to_tensor(arr,tf.float64)print(tensor)這次的運行結果顯示了張量具體的含義
  • 【官方教程】TensorFlow在圖像識別中的應用
    /main.cc:200] military uniform (866): 0.647296I tensorflow/examples/label_image/main.cc:200] suit (794): 0.0477196I tensorflow/examples/label_image/main.cc:200] academic gown (896): 0.0232411I tensorflow
  • mnist tensorflow 預測專題及常見問題 - CSDN
    for updating:Please use alternatives such as official/mnist/dataset.py from tensorflow/models.WARNING:tensorflow:From /home/cnu105/anaconda3/lib/python3.6/site-packages/tensorflow/contrib/learn/python
  • TensorFlow安裝與卷積模型
    1:Tensorflow 安裝:首先目前已學習的方法中有兩種方法可用於安裝TensorFlow:一是pip,二是Anaconda。另外 TensorFlow還有cpu和Gpu兩個版本。使用pip安裝1)下載安裝Python 2)打開windows的命令行窗口,安裝CPU版本pip installtensorflow安裝GPU版本Pip install tensorflow-gpu之後驗證是否安裝了 TensorFlow 可以嘗試一下代碼>>> importtensorflow
  • TensorFlow基本概念整理
    keeping the same elements containedtf.squeezeTo delete in a tensor dimensions of size 1tf.expand_dimsTo insert a dimension to a tensor tf.sliceTo remove a portions of a tensortf.splitTo divide a tensor