Google 人工智慧 TensorFlow 入門中文版

我是傳奇哈哈發表於2017-12-22

TensorFlow入門

本指南讓您開始在TensorFlow中程式設計。在使用本指南之前, 請安裝TensorFlow。為了充分利用本指南,您應該瞭解以下內容:

  • 如何用Python程式設計。
  • 至少有一點關於陣列陣列的知識。
  • 理想的是,關於機器學習的東西。但是,如果您對機器學習知之甚少,那麼這仍然是您應該閱讀的第一本指南。

TensorFlow提供了多個API。最低階別的API - TensorFlow核心 - 為您提供完整的程式設計控制。我們推薦TensorFlow Core用於機器學習研究人員和其他需要對其模型進行精細控制的人員。更高層次的API建立在TensorFlow核心之上。這些更高階別的API通常比TensorFlow Core更容易學習和使用。另外,更高階別的API使得不同使用者之間的重複任務更容易和更一致。像tf.estimator這樣的高階API可以幫助您管理資料集,估算器,培訓和推理。

本指南從TensorFlow核心教程開始。稍後,我們演示如何在tf.estimator中實現相同的模型。瞭解TensorFlow核心原則將給你一個很好的思維模型,說明當你使用更緊湊的更高階別的API時,內部是如何工作的。

張量

TensorFlow中的資料中心單位是張量。一個張量由一組形成任意數量維數的原始值組成。張量的等級是它的維數。這裡是一些張量的例子:

3 # a rank 0 tensor; a scalar with shape []
[1., 2., 3.] # a rank 1 tensor; a vector with shape [3]
[[1., 2., 3.], [4., 5., 6.]] # a rank 2 tensor; a matrix with shape [2, 3]
[[[1., 2., 3.]], [[7., 8., 9.]]] # a rank 3 tensor with shape [2, 1, 3]
複製程式碼

TensorFlow核心教程

匯入張量流

TensorFlow程式的規範匯入語句如下所示:

import tensorflow as tf
複製程式碼

這使得Python可以訪問所有 TensorFlow 的類,方法和符號。大多數文件假定您已經完成了這個工作。

計算圖

你可能會想到TensorFlow核心程式由兩個獨立的部分組成:

  • 構建計算圖。
  • 執行計算圖。

甲計算圖形是一系列排列成節點的圖形TensorFlow操作。我們來構建一個簡單的計算圖。每個節點將零個或多個張量作為輸入,併產生張量作為輸出。一種型別的節點是一個常量。像所有的TensorFlow常量一樣,它不需要輸入,而是輸出一個內部儲存的值。我們可以建立兩個浮點Tensors node1 ,node2如下所示:

node1 = tf.constant(3.0, dtype=tf.float32)
node2 = tf.constant(4.0) # also tf.float32 implicitly
print(node1, node2)
複製程式碼

最後的列印宣告產生

Tensor("Const:0", shape=(), dtype=float32) Tensor("Const_1:0", shape=(), dtype=float32)
複製程式碼

請注意,列印節點不會輸出值3.0,4.0正如您所期望的那樣。相反,它們是在評估時分別產生3.0和4.0的節點。為了實際評估節點,我們必須在會話中執行計算圖。會話封裝了TensorFlow執行時的控制和狀態。

下面的程式碼建立一個Session物件,然後呼叫它的run方法來執行足夠的計算圖來評估node1和node2。通過在會話中執行計算圖如下:

sess = tf.Session()
print(sess.run([node1, node2]))
複製程式碼

我們看到了3.0和4.0的預期值:

[3.0, 4.0]
複製程式碼

我們可以通過組合Tensor節點和操作來構建更復雜的計算(操作也是節點)。例如,我們可以新增我們的兩個常量節點,併產生一個新的圖形如下:

from __future__ import print_function
node3 = tf.add(node1, node2)
print("node3:", node3)
print("sess.run(node3):", sess.run(node3))
複製程式碼

最後兩個列印語句產生

node3: Tensor("Add:0", shape=(), dtype=float32)
sess.run(node3): 7.0
複製程式碼

TensorFlow提供了一個名為TensorBoard的實用程式,可以顯示計算圖的圖片。下面是一個螢幕截圖,顯示了TensorBoard如何將圖形視覺化:

Google 人工智慧 TensorFlow 入門中文版

就目前來看,這張圖並不是特別有趣,因為它總是會產生一個不變的結果。圖形可以被引數化來接受稱為佔位符的外部輸入。一個佔位符是一個承諾後提供一個值。

a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
adder_node = a + b  # + provides a shortcut for tf.add(a, b)
複製程式碼

前面的三行有點像一個函式或lambda,我們在其中定義兩個輸入引數(a和b),然後對它們進行操作。我們可以通過使用run方法的feed_dict引數將多個輸入的 具體值提供給佔位符來評估這個圖形。

print(sess.run(adder_node, {a: 3, b: 4.5}))
print(sess.run(adder_node, {a: [1, 3], b: [2, 4]}))
複製程式碼

導致輸出

7.5 [ 3. 7.] 在TensorBoard中,圖形如下所示:

Google 人工智慧 TensorFlow 入門中文版

我們可以通過新增另一個操作來使計算圖更加複雜。例如,

add_and_triple = adder_node * 3.
print(sess.run(add_and_triple, {a: 3, b: 4.5}))
複製程式碼

產生輸出

22.5 在TensorBoard中,上面的計算圖如下所示:

Google 人工智慧 TensorFlow 入門中文版

在機器學習中,我們通常需要一個可以進行任意輸入的模型,比如上面的模型。為了使模型可訓練,我們需要能夠修改圖形以獲得具有相同輸入的新輸出。 變數允許我們將可訓練引數新增到圖形中。它們被構造成一個型別和初始值:

W = tf.Variable([.3], dtype=tf.float32)
b = tf.Variable([-.3], dtype=tf.float32)
x = tf.placeholder(tf.float32)
linear_model = W*x + b
複製程式碼

常量在呼叫時被初始化tf.constant,其值永遠不會改變。相比之下,變數在呼叫時不會被初始化tf.Variable。要初始化TensorFlow程式中的所有變數,您必須顯式呼叫一個特殊的操作,如下所示:

init = tf.global_variables_initializer()
sess.run(init)
複製程式碼

實現initTensorFlow子圖的一個控制程式碼是初始化所有的全域性變數,這一點很重要。在我們呼叫之前sess.run,變數是未初始化的。

既然x是佔位符,我們可以同時評估linear_model幾個值, x如下所示:

print(sess.run(linear_model, {x: [1, 2, 3, 4]}))
複製程式碼

產生輸出

[ 0.          0.30000001  0.60000002  0.90000004]
複製程式碼

我們已經建立了一個模型,但我們不知道它有多好。為了評估培訓資料模型,我們需要一個y佔位符來提供所需的值,我們需要編寫一個損失函式。

損失函式用於衡量當前模型距離提供的資料有多遠。我們將使用線性迴歸的標準損失模型,它將當前模型和提供的資料之間的三角形的平方相加。linear_model - y建立一個向量,其中每個元素是相應示例的錯誤增量。我們打電話tf.square來解決這個錯誤。然後,我們總結所有的平方誤差來建立一個標量,它使用下面的方法來抽象所有例子的錯誤tf.reduce_sum:

y = tf.placeholder(tf.float32)
squared_deltas = tf.square(linear_model - y)
loss = tf.reduce_sum(squared_deltas)
print(sess.run(loss, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]}))
複製程式碼

產生損失價值

23.66
複製程式碼

我們可以手動重新分配的值提高這W和b為-1和1變數的值,完美初始化為提供的價值tf.Variable,但可以使用操作等來改變tf.assign。例如, W=-1並且b=1是我們模型的最佳引數。我們可以改變W, b因此:

fixW = tf.assign(W, [-1.])
fixb = tf.assign(b, [1.])
sess.run([fixW, fixb])
print(sess.run(loss, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]}))
複製程式碼

最後的印刷品顯示現在的損失是零。

0.0
複製程式碼

我們猜測的“完美”的價值觀W和b,但機器學習的整點自動找到正確的模型引數。我們將在下一節展示如何完成這個。

tf.train API
複製程式碼

機器學習的完整討論超出了本教程的範圍。但是,TensorFlow提供了優化器,可以逐漸改變每個變數,以最大限度地減少損失函式。最簡單的優化器是梯度下降。它根據相對於該變數的損失導數的大小來修改每個變數。一般來說,手動計算符號派生是繁瑣和容易出錯的。因此,TensorFlow可以自動生成衍生產品,僅使用該函式對模型進行描述tf.gradients。為了簡單起見,優化程式通常會為您執行此操作。例如,

optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
複製程式碼
sess.run(init) # reset values to incorrect defaults.
for i in range(1000):
  sess.run(train, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]})
複製程式碼
print(sess.run([W, b]))
複製程式碼

導致最終的模型引數:

[array([-0.9999969], dtype=float32), array([ 0.99999082], dtype=float32)]
複製程式碼

現在我們已經完成了機器學習!雖然這個簡單的線性迴歸模型不需要太多的TensorFlow核心程式碼,但是更復雜的模型和方法將資料提供給模型需要更多的程式碼。因此,TensorFlow為常見的模式,結構和功能提供更高層次的抽象。我們將在下一節學習如何使用這些抽象。

完整的程式 完成的可訓練線性迴歸模型如下所示:

import tensorflow as tf

# Model parameters
W = tf.Variable([.3], dtype=tf.float32)
b = tf.Variable([-.3], dtype=tf.float32)
# Model input and output
x = tf.placeholder(tf.float32)
linear_model = W*x + b
y = tf.placeholder(tf.float32)

# loss
loss = tf.reduce_sum(tf.square(linear_model - y)) # sum of the squares
# optimizer
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)

# training data
x_train = [1, 2, 3, 4]
y_train = [0, -1, -2, -3]
# training loop
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init) # reset values to wrong
for i in range(1000):
  sess.run(train, {x: x_train, y: y_train})

# evaluate training accuracy
curr_W, curr_b, curr_loss = sess.run([W, b, loss], {x: x_train, y: y_train})
print("W: %s b: %s loss: %s"%(curr_W, curr_b, curr_loss))
複製程式碼

執行時產生

W: [-0.9999969] b: [ 0.99999082] loss: 5.69997e-11
複製程式碼

請注意,損失是非常小的數字(非常接近零)。如果你執行這個程式,你的損失可能與上述損失不完全一樣,因為模型是用偽隨機值初始化的。

這個更復雜的程式仍然可以在 TensorBoard 中視覺化

Google 人工智慧 TensorFlow 入門中文版

tf.estimator
複製程式碼

tf.estimator 是一個高階的TensorFlow庫,它簡化了機器學習的機制,包括以下內容:

  • 執行訓練迴圈
  • 執行評估迴圈
  • 管理資料集

tf.estimator定義了許多常見的模型。

基本用法 注意線性迴歸程式變得簡單多了 tf.estimator:

# NumPy is often used to load, manipulate and preprocess data.
import numpy as np
import tensorflow as tf

# Declare list of features. We only have one numeric feature. There are many
# other types of columns that are more complicated and useful.
feature_columns = [tf.feature_column.numeric_column("x", shape=[1])]

# An estimator is the front end to invoke training (fitting) and evaluation
# (inference). There are many predefined types like linear regression,
# linear classification, and many neural network classifiers and regressors.
# The following code provides an estimator that does linear regression.
estimator = tf.estimator.LinearRegressor(feature_columns=feature_columns)

# TensorFlow provides many helper methods to read and set up data sets.
# Here we use two data sets: one for training and one for evaluation
# We have to tell the function how many batches
# of data (num_epochs) we want and how big each batch should be.
x_train = np.array([1., 2., 3., 4.])
y_train = np.array([0., -1., -2., -3.])
x_eval = np.array([2., 5., 8., 1.])
y_eval = np.array([-1.01, -4.1, -7, 0.])
input_fn = tf.estimator.inputs.numpy_input_fn(
    {"x": x_train}, y_train, batch_size=4, num_epochs=None, shuffle=True)
train_input_fn = tf.estimator.inputs.numpy_input_fn(
    {"x": x_train}, y_train, batch_size=4, num_epochs=1000, shuffle=False)
eval_input_fn = tf.estimator.inputs.numpy_input_fn(
    {"x": x_eval}, y_eval, batch_size=4, num_epochs=1000, shuffle=False)

# We can invoke 1000 training steps by invoking the  method and passing the
# training data set.
estimator.train(input_fn=input_fn, steps=1000)

# Here we evaluate how well our model did.
train_metrics = estimator.evaluate(input_fn=train_input_fn)
eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
print("train metrics: %r"% train_metrics)
print("eval metrics: %r"% eval_metrics)
複製程式碼

執行時,會產生類似的東西

train metrics: {'average_loss': 1.4833182e-08, 'global_step': 1000, 'loss': 5.9332727e-08}
eval metrics: {'average_loss': 0.0025353201, 'global_step': 1000, 'loss': 0.01014128}
複製程式碼

請注意我們的評估資料是如何有更高的損失,但仍然接近於零。這意味著我們正在正確地學習。

自定義模型 tf.estimator不會將您鎖定在預定義的模型中。假設我們想建立一個沒有內建到TensorFlow中的自定義模型。我們仍然可以保留資料集,餵養,培訓等的高層次抽象 tf.estimator。為了說明,我們將展示如何實現我們自己的等價模型,以LinearRegressor使用我們對低階別TensorFlow API的知識。

要定義一個適用的自定義模型tf.estimator,我們需要使用 tf.estimator.Estimator。tf.estimator.LinearRegressor實際上是一個子類tf.estimator.Estimator。Estimator我們只是簡單地提供Estimator一個函式model_fn來說明 tf.estimator如何評估預測,訓練步驟和損失,而不是分類 。程式碼如下:

import numpy as np
import tensorflow as tf

# Declare list of features, we only have one real-valued feature
def model_fn(features, labels, mode):
  # Build a linear model and predict values
  W = tf.get_variable("W", [1], dtype=tf.float64)
  b = tf.get_variable("b", [1], dtype=tf.float64)
  y = W*features['x'] + b
  # Loss sub-graph
  loss = tf.reduce_sum(tf.square(y - labels))
  # Training sub-graph
  global_step = tf.train.get_global_step()
  optimizer = tf.train.GradientDescentOptimizer(0.01)
  train = tf.group(optimizer.minimize(loss),
                   tf.assign_add(global_step, 1))
  # EstimatorSpec connects subgraphs we built to the
  # appropriate functionality.
  return tf.estimator.EstimatorSpec(
      mode=mode,
      predictions=y,
      loss=loss,
      train_op=train)

estimator = tf.estimator.Estimator(model_fn=model_fn)
# define our data sets
x_train = np.array([1., 2., 3., 4.])
y_train = np.array([0., -1., -2., -3.])
x_eval = np.array([2., 5., 8., 1.])
y_eval = np.array([-1.01, -4.1, -7., 0.])
input_fn = tf.estimator.inputs.numpy_input_fn(
    {"x": x_train}, y_train, batch_size=4, num_epochs=None, shuffle=True)
train_input_fn = tf.estimator.inputs.numpy_input_fn(
    {"x": x_train}, y_train, batch_size=4, num_epochs=1000, shuffle=False)
eval_input_fn = tf.estimator.inputs.numpy_input_fn(
    {"x": x_eval}, y_eval, batch_size=4, num_epochs=1000, shuffle=False)

# train
estimator.train(input_fn=input_fn, steps=1000)
# Here we evaluate how well our model did.
train_metrics = estimator.evaluate(input_fn=train_input_fn)
eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
print("train metrics: %r"% train_metrics)
print("eval metrics: %r"% eval_metrics)
複製程式碼

執行時產生

train metrics: {'loss': 1.227995e-11, 'global_step': 1000}
eval metrics: {'loss': 0.01010036, 'global_step': 1000}
複製程式碼

請注意,自定義model_fn()函式的內容與下層API的手動模型訓練迴圈非常相似。

文章是根據官方英文文件翻譯而來,掃一掃我的微信公眾號一起學習吧。

Google 人工智慧 TensorFlow 入門中文版
微信公眾號:Android開發吹牛皮

個人網站:

http://chaodongyang.com

相關文章