歡迎來(lái)我的個(gè)人Blog獲得更好的閱讀體驗(yàn)。
Tensorflow基礎(chǔ)
Tensor
1.正如名稱(chēng)所示,TensorFlow 這一框架定義和運(yùn)行涉及張量的計(jì)算。張量是對(duì)矢量和矩陣向潛在的更高維度的泛化。TensorFlow 在內(nèi)部將張量表示為基本數(shù)據(jù)類(lèi)型的 n 維數(shù)組。
2.tf.Tensor 具有以下屬性:
數(shù)據(jù)類(lèi)型(例如
float32、int32或string)形狀
3.張量中的每個(gè)元素都具有相同的數(shù)據(jù)類(lèi)型,且該數(shù)據(jù)類(lèi)型一定是已知的。形狀,即張量的維數(shù)和每個(gè)維度的大小,可能只有部分已知。如果其輸入的形狀也完全已知,則大多數(shù)操作會(huì)生成形狀完全已知的張量,但在某些情況下,只能在執(zhí)行圖時(shí)獲得張量的形狀。
4.如何按索引取多個(gè)值?
使用gather_nd方法
a = tf.constant([[1,2],[3,4],[5,6]])
b = tf.Variable([[1],[2]])
tf.gather_nd(a, b)
OUT:
<tf.Tensor: id=11677, shape=(2, 2), dtype=int32, numpy=
array([[3, 4],
[5, 6]])>
Eager Execution
1.如何在enable_eager_execution下求梯度?
導(dǎo)入import tensorflow.contrib.eager as tfe,然后使用tfe.gradients_function()進(jìn)行求梯度。
def square(x, y):
return tf.multiply(x, x) + y
grad = tfe.gradients_function(square)
grad(2., 2.)
OUT:
[<tf.Tensor: id=595913, shape=(), dtype=float32, numpy=4.0>,
<tf.Tensor: id=595910, shape=(), dtype=float32, numpy=1.0>]
2.如何使用batch數(shù)據(jù)集?
batched_dataset = tf.data.Dataset.from_tensor_slices((X, y)).batch(batch_size)
iterator = batched_dataset.make_one_shot_iterator()
for X, y in iterator:
do_something
線(xiàn)性回歸
模型訓(xùn)練三要素:訓(xùn)練數(shù)據(jù)、損失函數(shù)、優(yōu)化算法。
在線(xiàn)性回歸中,
的計(jì)算依賴(lài)于
和
。也就是說(shuō),輸出層中的神經(jīng)元和輸入層中各個(gè)輸入完全連接。因此,這里的輸出層又叫全連接層(fully-connected layer)或稠密層(dense layer)。
在訓(xùn)練模型的時(shí)候,我們需要遍歷數(shù)據(jù)集并不斷讀取小批量數(shù)據(jù)樣本。這里我們定義一個(gè)函數(shù):它每次返回
batch_size(批量大?。﹤€(gè)隨機(jī)樣本的特征和標(biāo)簽。也就是說(shuō)batch_size即為mini梯度下降的每次的數(shù)據(jù)量。
導(dǎo)包
import numpy as np
import tensorflow as tf
import tensorflow.contrib.eager as tfe
%matplotlib inline
from IPython import display
from matplotlib import pyplot as plt
import random
tf.enable_eager_execution() # 開(kāi)啟Eager Execution模式
手?jǐn)]線(xiàn)性回歸
構(gòu)建數(shù)據(jù)集
我們構(gòu)造一個(gè)簡(jiǎn)單的人工訓(xùn)練數(shù)據(jù)集,它可以使我們能夠直觀比較學(xué)到的參數(shù)和真實(shí)的模型參數(shù)的區(qū)別。設(shè)訓(xùn)練數(shù)據(jù)集樣本數(shù)為1000,輸入個(gè)數(shù)(特征數(shù))為2。給定隨機(jī)生成的批量樣本特征,我們使用線(xiàn)性回歸模型真實(shí)權(quán)重
和偏差
,以及一個(gè)隨機(jī)噪聲項(xiàng)
來(lái)生成標(biāo)簽
其中噪聲項(xiàng)服從均值為0、標(biāo)準(zhǔn)差為0.01的正態(tài)分布。噪聲代表了數(shù)據(jù)集中無(wú)意義的干擾。下面,讓我們生成數(shù)據(jù)集。
num_inputs = 2
num_examples = 1000
true_w = [2, -3.4]
true_b = 4.2
features = tf.random.normal(shape=(num_examples, num_inputs), stddev = 1)
labels = true_w[0] * features[:,0] + true_w[1] * features[:,1] + true_b
labels += tf.random.normal(stddev=0.01, shape=labels.shape) # 添加噪音
注意,features的每一行是一個(gè)長(zhǎng)度為2的向量,而labels的每一行是一個(gè)長(zhǎng)度為1的向量(標(biāo)量)。
features[0], labels[0]
OUT:
(<tf.Tensor: id=10879, shape=(2,), dtype=float32, numpy=array([-0.7999102 , 0.21825652], dtype=float32)>,
<tf.Tensor: id=10883, shape=(), dtype=float32, numpy=1.8640134>)
接下來(lái)我們可以畫(huà)圖來(lái)更直觀的看出他們的線(xiàn)性關(guān)系
def use_svg_display():
# 用矢量圖顯示
display.set_matplotlib_formats('svg')
def set_figsize(figsize=(3.5, 2.5)):
use_svg_display()
# 設(shè)置圖的尺寸
plt.rcParams['figure.figsize'] = figsize
set_figsize()
plt.scatter(features[:, 1].numpy(), labels.numpy(), 1); # 加分號(hào)只顯示圖

讀取數(shù)據(jù)
在訓(xùn)練模型的時(shí)候,我們需要遍歷數(shù)據(jù)集并不斷讀取小批量數(shù)據(jù)樣本。這里我們定義一個(gè)函數(shù):它每次返回batch_size(批量大?。﹤€(gè)隨機(jī)樣本的特征和標(biāo)簽。
def data_iter(batch_size, features, labels):
num_examples = len(features)
indices = list(range(num_examples))
random.shuffle(indices) # 樣本的讀取順序是隨機(jī)的
for i in range(0, num_examples, batch_size):
j = tf.Variable(indices[i: min(i + batch_size, num_examples)])
j = tf.reshape(j, [-1,1])
yield tf.gather_nd(features, j), tf.gather_nd(labels, j)
讓我們讀取第一個(gè)小批量數(shù)據(jù)樣本并打印。每個(gè)批量的特征形狀為(10, 2),分別對(duì)應(yīng)批量大小和輸入個(gè)數(shù);標(biāo)簽形狀為批量大小。
batch_size = 10
for X, y in data_iter(batch_size, features, labels):
print(X, y)
break
OUT:
tf.Tensor(
[[-0.227834 0.9596326 ]
[ 0.34192654 -0.66422266]
[ 0.3691396 -0.18605368]
[-1.1413608 0.8678634 ]
[ 0.58045554 0.3434902 ]
[-0.5410006 -0.42822808]
[ 0.9343072 1.4792926 ]
[-0.46756336 -0.6927819 ]
[ 0.08125348 -1.2476276 ]
[ 0.14274137 -0.79248554]], shape=(10, 2), dtype=float32) tf.Tensor(
[ 0.48526025 7.1483665 5.5596623 -1.0285498 4.194294 4.563314
1.0244439 5.611564 8.604012 7.180201 ], shape=(10,), dtype=float32)
初始化模型參數(shù)
我們將權(quán)重初始化成均值為0、標(biāo)準(zhǔn)差為0.01的正態(tài)隨機(jī)數(shù),偏差則初始化成0。
w = tf.random.normal(stddev=0.01, shape=(num_inputs, 1))
b = tf.zeros(shape=(1,))
定義損失函數(shù)
我們使用平方誤差作為損失函數(shù)
def squared_loss(X, w, b, y):
y_pred = tf.matmul(X, w) + b
return tf.reduce_sum((y_pred - tf.reshape(y, shape=y_pred.shape)) ** 2) / 2
定義優(yōu)化算法
我們使用小批量隨機(jī)梯度下降來(lái)定義優(yōu)化算法,其實(shí)就是除了一個(gè)batch_size
def sgd(param, grad, lr, batch_size):
param = param - lr * grad / batch_size
return param
訓(xùn)練模型
我們訓(xùn)練三個(gè)epoch,定義學(xué)習(xí)率為0.03,batch_size為10,使用tfe.gradients_function來(lái)求取梯度
num_epochs = 3
lr = 0.03
batch_size = 10
print("Initial loss: {:.3f}".format(squared_loss(X, w, b, y)))
for epoch in range(num_epochs): # 訓(xùn)練模型一共需要num_epochs個(gè)迭代周期
for X, y in data_iter(batch_size, features, labels):
grad = tfe.gradients_function(squared_loss)
grad_result = grad(X, w, b, y)
w = sgd(w, grad_result[1], lr, batch_size)
b = sgd(b, grad_result[2], lr, batch_size)
train_l = squared_loss(X, w, b, y)
print('epoch %d, loss %f' % (epoch + 1, train_l.numpy()))
OUT:
Initial loss: 170.409
epoch 1, loss 0.397634
epoch 2, loss 0.000867
epoch 3, loss 0.000623
我們來(lái)觀察一下訓(xùn)練后的參數(shù),可以發(fā)現(xiàn)他們是很接近的
true_w, w
([2, -3.4], <tf.Tensor: id=2451472, shape=(2, 1), dtype=float32, numpy=
array([[ 1.9991914],
[-3.399644 ]], dtype=float32)>)
true_b, b
(4.2,
<tf.Tensor: id=2451477, shape=(1,), dtype=float32, numpy=array([4.1997643], dtype=float32)>)
線(xiàn)性回歸更簡(jiǎn)潔的實(shí)現(xiàn)
同樣,我們定義好參數(shù)
num_epochs = 3
lr = 0.02
batch_size = 10
定義模型,這里注意要把w與b都要定義成Variable,不然后面的梯度下降優(yōu)化無(wú)法更新權(quán)值。
class Model(tf.keras.Model):
def __init__(self):
super(Model, self).__init__()
self.W = tf.Variable(tf.random.normal(stddev=0.01, shape=(num_inputs, 1)), name="weight")
self.B = tf.Variable(0., name='bias')
def call(self, inputs):
return tf.matmul(inputs, self.W) + self.B
定義損失函數(shù),這里注意y_pred的維度要與targets的維度相同,不然相減可能會(huì)出問(wèn)題,影響后面的結(jié)果,可能導(dǎo)致算法無(wú)法收斂。
def loss(model, inputs, targets):
y_pred = model(inputs)
error = y_pred - tf.reshape(targets, shape=y_pred.shape)
return tf.reduce_mean(tf.pow(error, 2)) / 2
定義梯度
def grad(model, inputs, targets):
with tf.GradientTape() as tape:
loss_value = loss(model, inputs, targets)
return tape.gradient(loss_value, [model.W, model.B])
初始化模型與優(yōu)化方法,這里我們就用普通的梯度下降優(yōu)化器
model = Model()
optimizer = tf.train.GradientDescentOptimizer(learning_rate=lr)
下面是用兩種方法來(lái)做實(shí)驗(yàn),一種是帶batch_size的小批量隨機(jī)梯度下降,一種是不帶batch_size的批量梯度下降。
小批量:
這里使用到了Dataset,可以直接讀取數(shù)據(jù),然后使用batch方法生成一個(gè)批處理后的數(shù)據(jù)集,然后使用make_one_shot_iterator生成一個(gè)迭代器,通過(guò)此對(duì)象,可以一次訪問(wèn)數(shù)據(jù)集中的一個(gè)元素。
print("Initial loss: {:.3f}".format(loss(model, features, labels)))
batched_dataset = tf.data.Dataset.from_tensor_slices((features, labels)).batch(batch_size)
for epoch in range(1, num_epochs + 1):
iterator = batched_dataset.make_one_shot_iterator()
for X, y in iterator:
grads = grad(model, X, y)
optimizer.apply_gradients(zip(grads, [model.W, model.B]))
# if epoch % 20 == 0:
print("Loss at epoch {:03d}: {:.8f}".format(epoch, loss(model, features, labels)))
print("Final loss: {:.3f}".format(loss(model, features, labels)))
print("W = {}, B = {}".format(model.W.numpy(), model.B.numpy()))
OUT:
Initial loss: 16.771
Loss at epoch 001: 0.28207895
Loss at epoch 002: 0.00484521
Loss at epoch 003: 0.00013049
Final loss: 0.000
W = [[ 1.9972771]
[-3.3913243]], B = 4.190994739532471
批量:
print("Initial loss: {:.3f}".format(loss(model, features, labels)))
for i in range(200):
grads = grad(model, features, labels)
optimizer.apply_gradients(zip(grads, [model.W, model.B]),
global_step=tf.train.get_or_create_global_step())
if i % 20 == 0:
print("Loss at step {:03d}: {:.8f}".format(i, loss(model, features, labels)))
print("Final loss: {:.3f}".format(loss(model, features, labels)))
print("W = {}, B = {}".format(model.W.numpy(), model.B.numpy()))
OUT:
Initial loss: 16.791
Loss at step 000: 16.11963463
Loss at step 020: 7.13295412
Loss at step 040: 3.15785861
Loss at step 060: 1.39871728
Loss at step 080: 0.61985403
Loss at step 100: 0.27484268
Loss at step 120: 0.12194006
Loss at step 140: 0.05414332
Loss at step 160: 0.02406745
Loss at step 180: 0.01071854
Final loss: 0.005
W = [[ 1.9749271]
[-3.3363655]], B = 4.128057956695557
線(xiàn)性回歸更更簡(jiǎn)潔的實(shí)現(xiàn)
這里我們使用到Tensorflow的最新科技Estimator,一種可極大地簡(jiǎn)化機(jī)器學(xué)習(xí)編程的高階 TensorFlow API。
從官方給的圖我們就可以看出有多么的高階,可以說(shuō)是頂峰了。
[圖片上傳失敗...(image-1f118e-1557193297372)]
編寫(xiě)一個(gè)或多個(gè)數(shù)據(jù)集導(dǎo)入函數(shù)
例如,您可以創(chuàng)建一個(gè)函數(shù)來(lái)導(dǎo)入訓(xùn)練集,并創(chuàng)建另一個(gè)函數(shù)來(lái)導(dǎo)入測(cè)試集。每個(gè)數(shù)據(jù)集導(dǎo)入函數(shù)都必須返回兩個(gè)對(duì)象:
一個(gè)字典,其中鍵是特征名稱(chēng),值是包含相應(yīng)特征數(shù)據(jù)的張量(或 SparseTensor)
一個(gè)包含一個(gè)或多個(gè)標(biāo)簽的張量
例如,以下代碼展示了輸入函數(shù)的基本框架:
f0 = features[:,0].numpy()
f1 = features[:,1].numpy()
這里為什么要分開(kāi)寫(xiě)呢?我到現(xiàn)在也不知道,希望知道的大神可以滴我一下。
def input_fn():
feature_dict = {}
feature_dict["w0"] = f0
feature_dict["w1"] = f1
return feature_dict, labels.numpy()
輸入函數(shù)可以以您需要的任何方式生成 features 字典和 label 列表。不過(guò),我們建議使用 TensorFlow 的 Dataset API,它可以解析各種數(shù)據(jù)。概括來(lái)講,Dataset API 包含下列類(lèi):
def dataset_input_fn():
feature_dict = {}
feature_dict["w0"] = f0
feature_dict["w1"] = f1
dataset = tf.data.Dataset.from_tensors((feature_dict, labels.numpy()))
return dataset.shuffle(2000).repeat()
dataset_input_fn是用了沒(méi)有切片的結(jié)果
def dataset_slices_input_fn():
feature_dict = {}
feature_dict["w0"] = f0
feature_dict["w1"] = f1
dataset = tf.data.Dataset.from_tensor_slices((feature_dict, labels.numpy()))
return dataset.shuffle(100).repeat().batch(batch_size)
dataset_slices_input_fn是用了切片的結(jié)果
這兩種的區(qū)別就是dataset_slices_input_fn函數(shù)會(huì)利用 tf.data.Dataset.from_tensor_slices函數(shù)創(chuàng)建一個(gè)代表數(shù)組切片的 tf.data.Dataset。系統(tǒng)會(huì)在第一個(gè)維度內(nèi)對(duì)該數(shù)組進(jìn)行切片。例如,一個(gè)包含MNIST訓(xùn)練數(shù)據(jù)的數(shù)組的形狀為 (60000, 28, 28)。將該數(shù)組傳遞給from_tensor_slices 會(huì)返回一個(gè)包含 60000 個(gè)切片的 Dataset對(duì)象,其中每個(gè)切片都是一個(gè) 28x28 的圖像。而這里就是每一行。
這里有個(gè)坑,就是使用了from_tensor_slices,如果不用batch直接訓(xùn)練會(huì)導(dǎo)致
ValueError: Feature (key: w0) cannot have rank 0. Give: Tensor("IteratorGetNext:0", shape=(), dtype=float32)
報(bào)錯(cuò)。
上面兩個(gè)函數(shù)用到了幾個(gè)對(duì)Dataset的操作:
shuffle方法使用一個(gè)固定大小的緩沖區(qū),在條目經(jīng)過(guò)時(shí)隨機(jī)化處理?xiàng)l目。在這種情況下,buffer_size大于Dataset中樣本的數(shù)量,確保數(shù)據(jù)完全被隨機(jī)化處理。repeat方法會(huì)在結(jié)束時(shí)重啟Dataset。要限制周期數(shù)量,請(qǐng)?jiān)O(shè)置count參數(shù)。batch方法會(huì)收集大量樣本并將它們堆疊起來(lái)以創(chuàng)建批次。這為批次的形狀增加了一個(gè)維度。新的維度將添加為第一個(gè)維度。
定義特征列
每個(gè) tf.feature_column 都標(biāo)識(shí)了特征名稱(chēng)、特征類(lèi)型和任何輸入預(yù)處理操作。例如,這里就要按照上面input_fn的返回值的feature_dict的鍵名來(lái)命名特征名。
w0 = tf.feature_column.numeric_column('w0')
w1 = tf.feature_column.numeric_column('w1')
實(shí)例化相關(guān)的預(yù)創(chuàng)建的 Estimator
例如,下面是對(duì)名為 LinearRegressor的預(yù)創(chuàng)建 Estimator 進(jìn)行實(shí)例化的示例代碼:
estimator = tf.estimator.LinearRegressor(
feature_columns=[w0, w1],
optimizer=tf.train.GradientDescentOptimizer(
learning_rate=0.0001,
))
調(diào)用訓(xùn)練、評(píng)估或推理方法。
1.使用input_fn()函數(shù)
estimator.train(input_fn=lambda:input_fn(), steps=200)
OUT:
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 0 into C:\Users\ADMINI~1\AppData\Local\Temp\2\tmpix5nedss\model.ckpt.
INFO:tensorflow:loss = 33480.66, step = 1
INFO:tensorflow:global_step/sec: 534.187
INFO:tensorflow:loss = 0.09687384, step = 101 (0.187 sec)
INFO:tensorflow:Saving checkpoints for 200 into C:\Users\ADMINI~1\AppData\Local\Temp\2\tmpix5nedss\model.ckpt.
INFO:tensorflow:Loss for final step: 0.09687384.
最終loss為0.09687384.
2.使用dataset_input_fn()函數(shù)
estimator.train(input_fn=lambda:dataset_input_fn(), steps=200)
OUT:
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 0 into C:\Users\ADMINI~1\AppData\Local\Temp\2\tmpt_lj1x_h\model.ckpt.
INFO:tensorflow:loss = 33480.66, step = 1
INFO:tensorflow:global_step/sec: 534.187
INFO:tensorflow:loss = 0.09687384, step = 101 (0.187 sec)
INFO:tensorflow:Saving checkpoints for 200 into C:\Users\ADMINI~1\AppData\Local\Temp\2\tmpt_lj1x_h\model.ckpt.
INFO:tensorflow:Loss for final step: 0.09687384.
最終loss為0.09687384.
和input_fn()函數(shù)結(jié)果一樣,因?yàn)槲覀兌紱](méi)有做任何改變,只是用了官方建議的DatasetAPI去封裝了我們的數(shù)據(jù)集。
3.使用dataset_slices_input_fn()函數(shù)
這里我們要調(diào)整學(xué)習(xí)率,因?yàn)槭褂玫氖切∨刻荻认陆?,所以學(xué)習(xí)率要高一點(diǎn),不然收斂很慢。
重新定義estimator
estimator = tf.estimator.LinearRegressor(
feature_columns=[w0, w1],
optimizer=tf.train.GradientDescentOptimizer(
learning_rate=0.02,
))
訓(xùn)練
estimator.train(input_fn=lambda:dataset_slices_input_fn(), steps=200)
OUT:
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 0 into C:\Users\ADMINI~1\AppData\Local\Temp\2\tmpli_pz5wh\model.ckpt.
INFO:tensorflow:loss = 207.14127, step = 1
INFO:tensorflow:global_step/sec: 493.095
INFO:tensorflow:loss = 0.0006978577, step = 101 (0.218 sec)
INFO:tensorflow:Saving checkpoints for 200 into C:\Users\ADMINI~1\AppData\Local\Temp\2\tmpli_pz5wh\model.ckpt.
INFO:tensorflow:Loss for final step: 0.000740177.
最終loss為0.000740177.
效果果然好了很多
小trick
無(wú)意中發(fā)現(xiàn),estimator有個(gè)牛逼的功能,就是能夠斷點(diǎn)續(xù)訓(xùn),當(dāng)然他不叫斷點(diǎn),官方的說(shuō)法是Checkpoints,翻譯過(guò)來(lái)叫做檢查點(diǎn),這真的太秀了,拿上面的dataset_slices_input_fn()舉個(gè)例子:
我故意把學(xué)習(xí)率調(diào)低
estimator = tf.estimator.LinearRegressor(
feature_columns=[w0, w1],
optimizer=tf.train.GradientDescentOptimizer(
learning_rate=0.0001,
))
然后訓(xùn)練
estimator.train(input_fn=lambda:dataset_slices_input_fn(), steps=200)
OUT:
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 0 into C:\Users\ADMINI~1\AppData\Local\Temp\2\tmplxsxz4hw\model.ckpt.
INFO:tensorflow:loss = 232.43555, step = 1
INFO:tensorflow:global_step/sec: 493.095
INFO:tensorflow:loss = 132.51915, step = 101 (0.218 sec)
INFO:tensorflow:Saving checkpoints for 200 into C:\Users\ADMINI~1\AppData\Local\Temp\2\tmplxsxz4hw\model.ckpt.
INFO:tensorflow:Loss for final step: 191.9462.
loss為191.9462.很明顯,沒(méi)有收斂,于是我繼續(xù)執(zhí)行:
estimator.train(input_fn=lambda:dataset_slices_input_fn(), steps=200)
OUT:
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from C:\Users\ADMINI~1\AppData\Local\Temp\2\tmplxsxz4hw\model.ckpt-200
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 200 into C:\Users\ADMINI~1\AppData\Local\Temp\2\tmplxsxz4hw\model.ckpt.
INFO:tensorflow:loss = 78.7848, step = 201
INFO:tensorflow:global_step/sec: 457.875
INFO:tensorflow:loss = 128.2986, step = 301 (0.203 sec)
INFO:tensorflow:Saving checkpoints for 400 into C:\Users\ADMINI~1\AppData\Local\Temp\2\tmplxsxz4hw\model.ckpt.
INFO:tensorflow:Loss for final step: 70.70934.
他讀取的緩存文件,繼續(xù)訓(xùn)練了,這真的很優(yōu)秀,再也不用重新訓(xùn)練了。