TensorFlow2.0教程-使用低級api訓練(非tf.keras)

TensorFlow2.0教程-使用低級api訓練(非tf.keras)

tensorflow2.0推薦使用tf.keras這樣的高級api來構建網絡,但tensorflow仍然保持了靈活的構造網絡的低級api,我們這節就來介紹怎麼通過使用這些低級api構建一個神經網絡並訓練。

原文地址:https://doit-space.blog.csdn.net/article/details/95040964

最全Tensorflow 2.0 入門教程持續更新:https://blog.csdn.net/qq_31456593/article/details/88606284

完整tensorflow2.0教程代碼請看 https://github.com/czy36mengfei/tensorflow2_tutorials_chinese (歡迎star)

本教程主要由tensorflow2.0官方教程的個人學習復現筆記整理而來,中文講解,方便喜歡閱讀中文教程的朋友,官方教程:https://www.tensorflow.org

一、Variables

TensorFlow的張量是不可變的無狀態對象。當我們有要改變的張量時,可以使用python的特性,把計算得到的值賦給這個python變量。

x = tf.ones([6,6])
x = x + 3 # x+3後得到了一個新的張量,並把這個張量賦給x
print(x)

tf.Tensor(
[[4. 4. 4. 4. 4. 4.]
 [4. 4. 4. 4. 4. 4.]
 [4. 4. 4. 4. 4. 4.]
 [4. 4. 4. 4. 4. 4.]
 [4. 4. 4. 4. 4. 4.]
 [4. 4. 4. 4. 4. 4.]], shape=(6, 6), dtype=float32)

然而機器學習中間需要變化的狀態(每個參數朝損失變小的方向改變,所以TensorFlow也要內置有狀態的操作,這就是Variables,它可以表示模型中的參數,而且方便高效。

Variables是一個存在值的對象,當其被使用是,它被隱式地被從存儲中讀取,而當有諸如tf.assign_sub, tf.scatter_update這樣的操作時,得到的新值會儲存到原對象中。

v = tf.Variable(2)
v.assign(6)
print(v)
v.assign_add(tf.square(3))
print(v)
<tf.Variable 'Variable:0' shape=() dtype=int32, numpy=6>
<tf.Variable 'Variable:0' shape=() dtype=int32, numpy=15>

注:梯度計算時會自動跟蹤變量的計算(不用watch),對錶示嵌入的變量,TensorFlow會默認使用稀疏更新,這樣可以提高計算和存儲效率。

二、示例:擬合線性模型

使用Tensor, Variable和GradientTape這些簡單的要是,就可以構建一個簡單的模型。步驟如下:

  • 定義模型
  • 定義損失函數
  • 獲取訓練數據
  • 模型訓練,使用優化器調整變量

在下面我們會構造一個簡單的線性模型:f(x) = W + b, 它有2個變量W和b,同時我們會使用W=3.0,b=2.0來構造數據,用於學習。

1、定義模型

我們把模型定義爲一個簡單的類,裏面封裝了變量和計算

class Model(object):
    def __init__(self):
        # 初始化變量
        self.W = tf.Variable(5.0)
        self.b = tf.Variable(0.0)
    
    def __call__(self, x):
        return self.W * x + self.b
# 測試
model = Model()
print(model(2))
tf.Tensor(10.0, shape=(), dtype=float32)

2.定義損失函數

損失函數測量給定輸入的模型輸出與期望輸出的匹配程度。 這裏使用標準的L2損失。

def loss(predicted_y, true_y):
    return tf.reduce_mean(tf.square(predicted_y - true_y))

3.獲取訓練數據

生成帶有噪音的數據

TRUE_W = 3.0
TRUE_b = 2.0
num = 1000

# 隨機輸入
inputs = tf.random.normal(shape=[num])
# 隨機噪音
noise = tf.random.normal(shape=[num])

# 構造數據
outputs = TRUE_W * inputs + TRUE_b + noise

在我們訓練模型之前,讓我們可以看到模型現在所處的位置。 我們將用紅色繪製模型的預測,用藍色繪製訓練數據。

import matplotlib.pyplot as plt

plt.scatter(inputs, outputs, c='b')
plt.scatter(inputs, model(inputs), c='r')
plt.show()

# 當前loss
print('Init Loss:')
print(loss(model(inputs), outputs))

[外鏈圖片轉存失敗(img-C0a314y0-1562512078616)(output_14_0.png)]

Init Loss:
tf.Tensor(8.763554, shape=(), dtype=float32)

4.定義訓練循環

我們現在已經有了模型和訓練數據。 我們準備開始訓練,即使用訓練數據來更新模型的變量(W和b),以便使用梯度下降來減少損失。 在tf.train.Optimizer中實現了許多梯度下降方案的變體。 強烈建議大家使用這些實現,但本着從第一原則構建的精神,在這個特定的例子中,我們將自己實現基本的優化器。

def train(model, inputs, outputs, learning_rate):
    # 記錄loss計算過程
    with tf.GradientTape() as t:
        current_loss = loss(model(inputs), outputs)
        # 對W,b求導
        dW, db = t.gradient(current_loss, [model.W, model.b])
        # 減去梯度×學習率
        model.W.assign_sub(dW*learning_rate)
        model.b.assign_sub(db*learning_rate)
        

我們反覆訓練模型,並觀察W和b的變化

model= Model()

# 收集W,b畫圖
Ws, bs = [], []
for epoch in range(10):
    Ws.append(model.W.numpy())
    bs.append(model.b.numpy())
    # 計算loss
    current_loss = loss(model(inputs), outputs)
    train(model, inputs, outputs, learning_rate=0.1)
    print('Epoch %2d: W=%1.2f b=%1.2f, loss=%2.5f' %
        (epoch, Ws[-1], bs[-1], current_loss))
# 畫圖
# Let's plot it all
epochs = range(10)
plt.plot(epochs, Ws, 'r',
         epochs, bs, 'b')
plt.plot([TRUE_W] * len(epochs), 'r--',
         [TRUE_b] * len(epochs), 'b--')
plt.legend(['W', 'b', 'true W', 'true_b'])
plt.show()
Epoch  0: W=5.00 b=0.00, loss=8.76355
Epoch  1: W=4.61 b=0.40, loss=5.97410
Epoch  2: W=4.30 b=0.72, loss=4.18118
Epoch  3: W=4.05 b=0.98, loss=3.02875
Epoch  4: W=3.85 b=1.18, loss=2.28800
Epoch  5: W=3.69 b=1.35, loss=1.81184
Epoch  6: W=3.56 b=1.48, loss=1.50577
Epoch  7: W=3.46 b=1.58, loss=1.30901
Epoch  8: W=3.38 b=1.67, loss=1.18253
Epoch  9: W=3.31 b=1.73, loss=1.10123

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章