機器學習的敲門磚:手把手教你TensorFlow初級入門


摘要: 在開始使用機器學習算法之前,我們應該首先熟悉如何使用它們。 而本文就是通過對TensorFlow的一些基本特點的介紹,讓你了解它是機器學習類庫中的一個不錯的選擇。

本文由北郵@愛可可-愛生活 老師推薦,阿里雲雲棲社區組織翻譯。

以下為譯文:
 
在開始使用機器學習算法之前,我們應該首先熟悉如何使用它們。 而本文就是通過對TensorFlow的一些基本特點的介紹,讓你了解它是機器學習類庫中的一個不錯的選擇。

讓我們設想一下,當我們用Python寫代碼時,沒有那些方便的類庫會是怎樣一種窘境。 這就好比你有一個新的智能手機,而不安裝任何應用程序。 雖然它仍然可以打電話,發短信,但如果有了那些更方便的應用程序,這部智能手機才更有價值。

 

設想一下這個場景...你作為一名業務負責人,需要負責跟蹤銷售流程。 你希望計算銷售產品的收入。 現在有100個不同的產品在你的倉庫中,你需要用一個向量表示每個產品的價格。另一個大小為100的向量表示每個產品的庫存量。 以下的Python代碼是用來計算銷售所有產品的收入。注意了, 這里沒有調用任何類庫。

 

 

revenue = 0
for price, amount in zip(prices, amounts):
    revenue += price * amount

 

代碼列表1. 不使用任何Python類庫計算兩個向量的內積

 

這段代碼只是計算兩個向量(也稱為點積)的內積。 想象一下,對於更復雜的問題,需要多少代碼。例如求解線性方程或計算兩個向量之間的距離。

 

 

當你安裝TensorFlow類庫的同時,其中還包括了非常知名的NumPy類庫,對Python編程中的數學操作非常有用。用Python編程時,不使用類庫(例如NumPy和TensorFlow)就像使用沒有自動對焦的相機:你雖然獲得了更多的靈活性,但你可能很容易犯錯。在機器學習的過程中已經很容易犯錯誤了,所以就讓我們使用TensorFlow來提高化軟件開發的效率吧。

 

代碼列表2展示了如何使用NumPy簡潔地編寫相同的內積運算。

 

import numpy as np
revenue = np.dot(prices, amounts)
代碼列表2. 用NumPy類庫計算內積

Python是一種簡潔的語言,這意味着你不會看到冗長的代碼。另一方面,Python語言的簡潔意味着許多處理都在后台進行,因此我們應該熟悉它背后的原理。

 

 

 

關於TensorFlowPythonC ++ API的各種函數的詳細文檔,請參見https://www.tensorflow.org/api_docs/index.html

 

機器學習主要依賴於很多數學公式,本文將對使用TensorFlow進行這類數學運算做一個初步的介紹。通過示例和代碼,大家可以對TensorFlow有一個初步了解。例如如何運用TensorFlow計算大數據的統計信息。 因此本文的重點將完全是關於如何使用TensorFlow,而不是一般的機器學習算法運用。

 

 

機器學習算法需要大量的數學運算。 通常,某個算法可以歸結為簡單函數組合的迭代,直到它收斂為止。 當然,也可以使用任何標准編程語言來執行這些計算。但是使用像TensorFlow這樣已經非常完善了的類庫是提高代碼可控性和性能的關鍵。

確保TensorFlow工作

首先,為我們的第一段代碼創建一個名為test.py的新文件。 通過運行以下代碼導入TensorFlow:

 

import tensorflow as tf

在導入TensorFlow后,如果Python解釋器沒有報錯,那么我們就可以開始使用TensorFlow了。

 

遇到了錯誤? 在這里,常見錯誤的原因是你可能安裝了GPU版本,並且類庫無法搜索CUDA驅動程序。 請記住,如果使用CUDA編譯庫,則需要使用CUDA的路徑更新環境變量。 你需要檢查TensorFlow上的CUDA指令。 (有關詳情,請參閱https://www.tensorflow.org/versions/master/get_started/os_setup.html#optional-linux-enable-gpu-support)。

使用TensorFlow中的規則

TensorFlow庫通常使用tf限定名稱來進行導入。 一般來說,使用tf限定名稱是一個不錯的方法,以便與其他開發人員和開源TensorFlow項目保持一致。 你也可以選擇不使用這個限定名稱,但這會影響你在自己的項目中重用別人的TensorFlow代碼。

表示張量

在現實世界中描述對象的一個簡便方法就是通過羅列出它的屬性或特征。 例如,我們可以通過顏色,型號,發動機類型和里程數描述一輛汽車。 這些特征的有序列表被稱為特征向量,這正是我們要在TensorFlow代碼中所表示的。

特征向量是機器學習中最有用的方法之一,(它們就是一個數字列表)。每個數據項通常有一個特征向量,而一個好的數據集則具有數千個特征向量。 毫無疑問,你會經常一次處理多個向量。 矩陣簡明地表示了向量列表,其中矩陣的每列表示一個特征向量。

 

在TensorFlow中用向量的向量表示矩陣,每個向量具有相同的長度。 圖1是一個兩行三列的矩陣的示例,例如[[1,2,3],[4,5,6]]。 注意,這是一個包含兩個元素的向量,每個元素對應一個矩陣行。

 

eeeb458a8a0089d543f75d2b10bbfc4c5f845c76

 

圖1.圖上半部分是計算機對矩陣的表示,下半部分是我們日常生活中對矩陣的表示。 這種形式的符號是大多數科學計算類庫中的常見范例。

 

 

我們通過指定其行和列索引來定位矩陣中的元素。 例如,第一行和第一列來表示左上角第一個元素。 有時,我們需要使用兩個以上的索引,這樣來表示一個元素會很方便。例如,在表示一個圖片中的像素時,我們不僅通過其行和列值來描述它,而且還使用紅藍通道來對其進行描述。 張量是通過任意數量的索引指定矩陣中元素的一般化。

 

一個張量的例子...假設一所小學為每個學生分配座位。 你是這個學校的校長,並且你記不住這些學生的名字。 幸運的是,每個教室都有一個座位網格,可以通過學生的行和列來指定某個學生。

 

 

因為有多個教室,所以你不能簡單的說早上好,410!”你還需要指定教室,比如說你好, 教室24排10列。不像矩陣只需要兩個索引就能指定一個元素,這所學校的學生需要三個數字。 這三個數字都是三階張量的一部分!

 

 

張量是更多的嵌套向量。例如,一個2×3×2的張量為[[[1,2],[3,4],[5,6]],[[7,8],[9,10] 11,12]]],它可以被認為是兩個矩陣,每個大小為3×2。 因此,我們說這個張量的秩是3.一般來說,張量的秩是指定一個元素所需的索引的數量。 TensorFlow中的機器學習算法是作用於張量上的,理解如何使用它們是關鍵。

 

192f94164f8b96575d058f4051193c7b2216458b

圖2.該張量可以被認為是堆疊在彼此之上的多個矩陣。 要指定其中的某個元素,必須指明行和列,以及要訪問的矩陣。 因此,該張量的秩為三。

 

 

你可能會對如何表示張量產生疑惑。下面三行代碼試圖表示相同的2×2矩陣。 該矩陣表示兩個維度的兩個特征向量。 例如,它可以表示兩個人對兩部電影的評價。 每個人,由矩陣的行索引表示,分配一個數字來描述每個人的電影評價值,由列索引表示。 運行代碼以了解如何在TensorFlow中生成矩陣。

 

import tensorflow as tf
# We’ll use NumPy matrices in TensorFlow
import numpy as np   
# Define a 2x2 matrix in 3 different ways
m1 = [[1.0, 2.0], 
      [3.0, 4.0]]
m2 = np.array([[1.0, 2.0], 
               [3.0, 4.0]], dtype=np.float32)
m3 = tf.constant([[1.0, 2.0], 
                  [3.0, 4.0]])

# Print the type for each matrix
print(type(m1))
print(type(m2))
print(type(m3))

# Create tensor objects out of the different types
t1 = tf.convert_to_tensor(m1, dtype=tf.float32)
t2 = tf.convert_to_tensor(m2, dtype=tf.float32)
t3 = tf.convert_to_tensor(m3, dtype=tf.float32)

# Notice that the types will be the same now
print(type(t1))
print(type(t2))
print(type(t3))

 

代碼列表3.表示張量的不同方式

 

第一個變量m1是一個列表,第二個變量m2是NumPy類庫中的一個ndarray,最后一個變量m3是TensorFlow的Tensor對象。TensorFlow中所有運算符(如neg)都設計為對張量對象進行操作。tf.convert_to_tensor(...)這個方法,我們可以用在任何地方,以確保我們處理張量而不是其他類型。TensorFlow類庫中的大多數方法都已經調用了它。使用tf.convert_to_tensor(...)並不是必須的,在這里使用它,是因為它有助於我們理解隱式類型的跨類庫處理。

 

 

<class ‘tensorflow.python.framework.ops.Tensor’>


 

 

 

讓我們再來看看如何中定義張量。 導入TensorFlow類庫之后,我們可以使用常量運算符,如代碼列表4所示。

 

import tensorflow as tf
# Define a 2x1 matrix
matrix1 = tf.constant([[1., 2.]])
# Define a 1x2 matrix
matrix2 = tf.constant([[1], 
                       [2]])
# Define a rank 3 tensor
myTensor = tf.constant([ [[1,2], 
                          [3,4], 
                          [5,6]], 
                         [[7,8], 
                          [9,10], 
                          [11,12]] ])
# Try printing the tensors 
print(matrix1)
print(matrix2)
print(myTensor)

 

代碼列表4。 創建張量

 

代碼4的運行結果:

 

 

Tensor( “Const:0”,
        shape=TensorShape([Dimension(1), 
                           Dimension(2)]),
        dtype=float32 )
Tensor( “Const_1:0”,
        shape=TensorShape([Dimension(2), 
                           Dimension(1)]),
        dtype=int32 )
Tensor( “Const_2:0”,
         shape=TensorShape([Dimension(2), 
                            Dimension(3), 
                            Dimension(2)]),
         dtype=int32 )

從運行結果中可以看出,每個張量都由已命名的Tensor對象表示。每個Tensor對象都有一個唯一的標簽(名稱),一個用於定義其結構的維度(shape),以及用於指定我們要操作的數據類型(dtype)。因為我們並沒有顯示指定名稱,所以他們被自動命名為:“Const:0”,“Const_1:0”和“Const_2:0”。

 

 

 

張量類型

 

需要注意的是matrix1的每個元素以小數點結束,這是為了告訴Python該元素的數據類型不是整數,而是浮點數。 我們可以傳遞顯式dtype值。 和NumPy數組一樣,張量可以接受我們指定的類型。

 

 

TensorFlow也提供了一些構造函數用於一些簡單的張量。例如,tf.zeros(shape)創建了一個包涵所有值都被初始化為零的特定形態的張量。 類似地,tf.ones(shape)創建了一個所有元素值為1的張量。 shape參數是描述張量的維度的一維張量,它的類型是int32。

 

創建運算符

 

我們已經有了幾個初始的張量,現在我們可以用運算符對他們進行操作,比如加減乘除。 假設現在有一個矩陣,它的行表示貨幣交易,收款金額(正值)和收款金額(負值)。 矩陣取反是表示某個人的貨幣流歷史記錄的一種方式。 我們現在對代碼列表4中的matrix1進行取反操作neg(negation的縮寫)。矩陣取反將正數轉換為絕對值相同的負數,反之亦然。

取反操作是最簡單的操作之一。 如代碼列表5所示,取反只需將一個張量作為輸入,得出另一個張量,每個元素取反。現在,嘗試自己運行代碼。 如果你已經掌握了如何使用取反,那就可以推廣到所有其他TensorFlow的操作。

 

 

這里需要指出,定義操作(如取反操作)和運行它是不一樣的。

 

import tensorflow as tf

# Define an arbitrary tensor
x = tf.constant([[1, 2]])

# Negate the tensor
neg_x = tf.neg(x)

# Print the object
print(neg_x)

 

代碼列表5. 取反運算符的使用

 

代碼列表5的輸出:

 

Tensor(“Neg:0”, shape=(1, 2), dtype=int32)

 

更多TensorFlow的運算符
 

官方文檔詳細地列出了所有可用的數學操作:

https://www.tensorflow.org/api_docs/Python/math_ops.html。

 

常用操作符的示例包括:

 

tf.add(x, y) 
Add two tensors of the same type, x + y
tf.sub(x, y) 
Subtract tensors of the same type, x — y
tf.mul(x, y) 
Multiply two tensors element-wise
tf.pow(x, y) 
Take the element-wise power of x to y
tf.exp(x) 
Equivalent to pow(e, x), where e is Euler’s number (2.718…)
tf.sqrt(x) 
Equivalent to pow(x, 0.5)
tf.div(x, y) 
Take the element-wise division of x and y
tf.truediv(x, y) 
Same as tf.div, except casts the arguments as a float
tf.floordiv(x, y) 
Same as truediv, except rounds down the final answer into an integer
tf.mod(x, y) 
Takes the element-wise remainder from division

 

 

我們可以這些TensorFlow運算符來產生高斯分布(也稱為正態分布)。 參見圖3提示。 你可以參考wiki,找到正態分布的概率密度:https://en.wikipedia.org/wiki/Normal_distribution。

 

為了簡潔起見,諸如“*”,“ - ”,“+”等大多數數學表達式是其TensorFlow運算符的快捷方式。高斯函數包括許多運算,如下所示:

 

 

from math import pi
mean = 1.0
sigma = 0.0
(tf.exp(tf.neg(tf.pow(x — mean, 2.0) /
               (2.0 * tf.pow(sigma, 2.0) ))) *
(1.0 / (sigma * tf.sqrt(2.0 * pi) )))

713c3ec7042deeb93d4dcff11c886c160e51fe71

 

 

圖3.該圖表示產生高斯分布所需的操作。 節點之間的鏈接表示數據如何從一個操作進入下一個操作。 操作本身很簡單,但是它們如何相互作用是相對復雜的。

 

TensorFlow算法很容易可視化。 它們可以用流程圖來進行描述。 流程圖就是一種圖表。 流程圖中的每個箭頭都稱為圖形的邊。 而它的每個狀態被稱為節點。

 

在會話中執行運算符

 

會話(session)是描述代碼應該如何運行的軟件系統環境。在TensorFlow中,會話設置了硬件設備(如CPU和GPU)如何相互通信。這樣,你只要關心如何設計機器學習算法,而不必擔心底層硬件設備的運行。當然,你也可以配置會話以更改其底層硬件設備交互行為,而不更改上層代碼。

 

要在TensorFlow中運行程序計算數值是需要一個會話的。 只有在已創建的會話才可以對Tensor對象進行賦值。 為此,我們必須使用tf.Session()創建一個會話類,並由它來運行一個運算符(代碼列表6)。

 

 

import tensorflow as tf

# Define an arbitrary matrix
matrix = tf.constant([[1., 2.]])

# Run the negation operator on it
neg_matrix = tf.neg(matrix)

# Start a session to be able to run operations
with tf.Session() as sess:
    # Tell the session to evaluate negMatrix
    result = sess.run(neg_matrix)

# Print the resulting matrix
print(result)

 

代碼列表6.使用會話

 

恭喜! 你剛剛寫了第一個完整的TensorFlow代碼。 盡管它所做的是只是對一個矩陣進行取反,但它已經能充分體現TensorFlow中的核心概念與框架了。

 

 

會話配置

在創建tf.Session類時,我們可以向構造函數傳遞一些參數。 例如,TensorFlow會根據可用的內容自動確定為指定GPU或CPU設備的最佳方式。 在創建會話時,我們可以設置log_device_placements = True,如代碼列表7所示。

 

import tensorflow as tf

# Define a matrix and negate it
matrix = tf.constant([[1., 2.]])
negMatrix = tf.neg(matrix)

# Start the session with a special config passed into the constructor to enable logging
with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess:
    # Evaluate negMatrix
    result = sess.run(negMatrix)

# Print the resulting value
print(result)
代碼列表7 登錄一個會話

 

這將輸出有關每個操作的會話中使用哪些CPU / GPU設備的信息。 例如,執行代碼列表6中的程序會有以下輸出,它顯示了用於運行取反操作的設備:

 

 

Neg: /job:localhost/replica:0/task:0/cpu:0


 

 

會話在TensorFlow中是必不可少的。 我們需要調用一個會話來執行數學操作。 圖4描述了TensorFlow上的不同組件如何與機器學習管道的交互。 會話不僅執行圖像操作,而且還可以使用占位符,變量和常量作為輸入。 到目前為止,我們已經使用了常量,但在后面的部分,我們將開始使用變量和占位符。 以下是這三種類型值的簡要概述。

 

•占位符:未分配的值,但將由運行的會話初始化。

•變量:可以更改的值,例如機器學習模型的參數。

 

•常數:不更改的值,例如超參數或設置。

 

932d751396aa0cb74b18a7b6a680ba9c5489f284

 

圖4.會話指示如何使用硬件來最有效地處理圖形。 當會話開始時,它將CPU和GPU設備分配給每個節點。 在處理之后,會話用可用格式(例如NumPy數組)輸出數據。 會話可以接受占位符,變量和常量。

 

想了解更多?

 

 

我希望你通過本文已經熟悉了一些TensorFlow編程的基本方法。 如果這篇文章讓你對TensorFlow 產生了興趣,請下載Machine Learning with TensorFlow的第一章,從中了解更多內容。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM