我是一個很懶的人八秃,我想試試
希望我能堅持到最后机隙,把tensorflow的官方教程全部翻譯出來
提高自己臼隔,也幫助他人
我的博客:終身學習者
Tensorflow 入門
本篇是Tensorflow編程入門指南寥假。在開始本教程前,請先安裝 TensorFlow疗隶。為了充分利用本指南佑笋,你需要知道以下知識:
- 如何使用 Python 編程。
- 至少知道一點 Arrays 知識抽减。
- 最好能懂一點機器學習的知識允青。但即使你一點機器學習的知識都不懂也沒有關系,這依然可以是你閱讀的第一份教程卵沉。
TensorFlow 提供了多個 APIs。最低級的 API——TensorFlow Core 提供完整的編程控制法牲。我們建議機器學習研究者和其他需要對模型進行精確控制的人員來使用TensorFlow Core史汗。更高級的 APIs 建立在 TensorFlow Core之上。這些更高級的 APIs 相比于 TensorFlow Core 也更加容易學習與使用拒垃。另外停撞,更高級的 API 使得不同用戶之間的重復任務更容易也更一致。像 tf.estimator 這樣的高級 API 可以幫助您管理數(shù)據(jù)集悼瓮,評價戈毒,訓練和推理。
本指南將以 Tensorflow Core 開始横堡。接下來埋市,我們將演示如何在 tf.estimator 中運行相同的模型。理解 Tensorflow Core 原理將在你使用更抽象的高級 API 時能夠更好的理解事情內部的工作原理命贴。
Tensors
Tensorflow 數(shù)據(jù)的核心單位是張量 (tensor)道宅。一個張量是由一組任意維度的原始值組成食听。張量的 (rank) 是它的維數(shù), 下面是一些張量的例子:
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 Core 教程
Importing TensorFlow
TensorFlow 程序規(guī)范導入語句如下:
import tensorflow as tf
這使得 Python 可以訪問所有的 TensorFlow 類(classes), 方法(methods)和符號(symbols)。接下來大多數(shù)的教程都假設你已完成了此項工作污茵。
The Computational Graph
你可能會認為 Tensorflow Core 程序都是包含以下兩個部分:
- 構建 computational graph樱报。
- 執(zhí)行 computational graph。
計算圖 (computational graph) 是一系列排列成節(jié)點圖的 TensorFlow 操作泞当。讓我們來構建一個簡單的計算圖迹蛤。每個節(jié)點將輸入零個或多個張量并產生一個張量作為輸出。每個類型的節(jié)點都是一個常量襟士。類似于所有的 TensorFlow 常量盗飒,它沒有輸入,而只輸出一個內部存儲值敌蜂。我們可以創(chuàng)建兩個浮點型張量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)
注意箩兽,打印節(jié)點不會像你預期的那樣輸出 3.0
和4.0
。相反章喉,他們在評估時將會分別輸出 3.0 和 4.0. 為了實際評估節(jié)點汗贫,我們必須在會話 (session) 內運行計算圖。session 封裝了 Tensorflow 運行時的控制和狀態(tài)秸脱。
以下代碼創(chuàng)建了一個 Session
對象并調用了 run
方法運行計算圖來評估node1
和 node2
落包。通過在 session 中運行計算圖:
sess = tf.Session()
print(sess.run([node1, node2]))
我們就可以看到期望的答案 3.0 和 4.0:
[3.0, 4.0]
我們可以通過將張量節(jié)點與操作相結合來構建更復雜的計算(操作也是節(jié)點)。例如摊唇,我們可以增加兩個常量節(jié)點并產生一個新的圖(graph):
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將圖可視化:
就目前來看巷查,這張圖并不特別有趣有序,因為它總是產生一個不變的結果。圖可以被參數(shù)化來接收稱為占位符的外部輸入岛请。占位符是接下來提供值的變量旭寿。
a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
adder_node = a + b # + provides a shortcut for tf.add(a, b)
這三行有點像一個函數(shù)(function)或者一個lambda,其中我們定義了兩個參數(shù)(a和b)和一個操作崇败。我們可以通過多個輸入來評估這個圖盅称,這些輸入是通過使用 run 方法 的 feed_dict 參數(shù)將具體值 feed 給占位符:
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,這圖看起來是這樣的:
我們可以通過添加其他的操作來使得計算圖更加的復雜后室,例如缩膝,
add_and_triple = adder_node * 3.
print(sess.run(add_and_triple, {a: 3, b: 4.5}))
輸出結果:
22.5
在TensorBoard中,上面的計算圖如下所示:
在機器學習中岸霹,我們通常需要一個可以計算任意輸入的模型疾层,比如上面的模型。為了使得模型可訓練松申,我們需要能夠修改圖使得其具有相同的輸入能得到新的輸出云芦。變量(Variables)允許我們添加可訓練的參數(shù)到圖中俯逾。他們可以被構造成一個類型和初始值:
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.constant
的時候變量并沒有被初始化琉历。為了初始化TensorFlow里面的變量坠七,你必須顯式的調用下面的操作:
init = tf.global_variables_initializer()
sess.run(init)
實現(xiàn)init
是TensorFlow子圖初始化所有的全局變量的一個很重要的句柄。在我們調用sess.run
之前旗笔,變量是未初始化的彪置。
由于x
是一個占位符,我們可以同時為多個x
評估linear_model
:
print(sess.run(linear_model, {x: [1, 2, 3, 4]}))
輸出結果:
[ 0. 0.30000001 0.60000002 0.90000004]
我們創(chuàng)建了一個模型蝇恶,但是我們不知道這個模型的好壞拳魁。為了評估訓練數(shù)據(jù)的模型,我們需要一個y
占位符來提供期望值撮弧,并且我們需要寫一個代價函數(shù)潘懊。
代價函數(shù)用于衡量當前模型與預期值之間的差距有多遠。我們將使用線性回歸的標準代價模型贿衍,其中代價是當前模型與期望值之間的差距的平方的總和授舟。linear_model - y
創(chuàng)建一個每個元素與其對應實例的誤差的向量。我們調用tf.square
來計算這個誤差的平方贸辈。然后我們統(tǒng)計所有的平方差來創(chuàng)建一個標量释树,通過調用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
就是我們這個模型的最優(yōu)參數(shù)嘴拢,我們可以對應改變 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
的最佳值,但是機器學習的重點是自動找到正確的模型參數(shù)炊汤。我們將在下一節(jié)展示如何完成這項工作。
tf.train API
對于機器學習的完整討論已超出了本教程的范圍弊攘。但是Tensorflow提供的優(yōu)化器(optimizers) 可以逐步改變每個變量來逐步使得代價函數(shù)達到最小值抢腐。最簡單的優(yōu)化器是梯度下降(gradient descent) 。它根據(jù)相對于該變量的損失導數(shù)的大小來修改每個變量襟交。一般來說迈倍,手動計算符號導數(shù)是繁瑣而又容易出錯的。所以只要使用tf.gradients
來描述模型 tensorflow 就可以自動計算導數(shù)捣域。簡單來說啼染,優(yōu)化器通常會自動為你做這件事宴合,例如:
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]))
最終的模型參數(shù)結果如下:
[array([-0.9999969], dtype=float32), array([ 0.99999082], dtype=float32)]
現(xiàn)在我們已經完成了一個實際的機器學習了!雖然這個簡單的線性模型不需要太多的 tensorflow core 代碼迹鹅,但是使用更復雜的模型和方法給我們的模型 feed 數(shù)據(jù)則需要更多的代碼卦洽。因此 tensorflow 為常見的模型,結構和功能提供更高級的抽象斜棚。我們將在下一節(jié)中學習如何使用這些抽象阀蒂。
Complete program
完成可訓練的線性回歸模型如下所示:
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
注意,loss 是一個非常小的數(shù)字(非常接近于零)弟蚀。如果你運行這段代碼蚤霞,你的 loss 可能和上面的 loss 不完全一致,因為模型的初始化是使用偽隨機值的义钉。
在 tensorboard 仍然可以可視化非常復雜的程序昧绣。tf.estimator
tf.estimator
是一個高級的 TensorFlow 庫,它簡化了機器學習的機制:
- 運行訓練循環(huán)
- 運行評估循環(huán)
- 管理數(shù)據(jù)集
tf.estimator 定義了許多常見的模型捶闸。
Basic usage
注意在 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}
注意鉴嗤,不論我們評估的loss有多高斩启,但它仍然接近與零。這意味這我們的學習是正確的醉锅。
A custom model
tf.estimator
不會限制你在預定義模型中兔簇。假設我們想要創(chuàng)建一個自定義的 TensorFlow 沒有的模型。我們仍然可以使用 tf.estimator
來使用高度抽象的數(shù)據(jù)集硬耍,處理垄琐,訓練。為了說明经柴,我們將展示如何利用我們的知識使用低級的 TensorFlow API 來實現(xiàn)相同的線性回歸模型狸窘。
為了定義一個使用tf.estimator
的自定義模型,我們需要使用 tf.estimator.Estimator
坯认。實際上 tf.estimator.LinearRegressor
是 tf.estimator.Estimator
的一個子類翻擒。為了替代子類Estimator
,我們只需要提供 Estimator
的一個函數(shù) 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()
函數(shù)的內容與我們從低級 API 得到的手動訓練循環(huán)是非常相似的。
Next steps
現(xiàn)在你已經掌握了 TensorFlow 的基礎知識引润。我們還有更多的教程助你了解學習更多巩趁。如果你是一個機器學習初學者,請查看 MNIST for beginners 淳附,否則請查看 Deep MNIST for experts 议慰。