這裏我們實現的是接上一篇的從0開始的線性迴歸,TF-2.x中有比較簡潔的實現方式。mxnet中也有對應章節:MXNET深度學習框架-04-使用gluon實現線性迴歸
1、生成數據集
num_inputs = 2
num_examples = 1000
true_w = [2, -3.4] #真實權重
true_b = 4.2 # 真實偏置值
features = tf.random.normal((num_examples, num_inputs),stddev =1)
labels = true_w[0] * features[:,0] + true_w[1] * features[:,1] + true_b
labels += tf.random.normal(labels.shape,stddev=0.01)
2、讀取數據集
batch_size = 10
# 將訓練數據的特徵和標籤組合
dataset = tfdata.Dataset.from_tensor_slices((features, labels))
# 隨機讀取小批量
dataset = dataset.shuffle(buffer_size=num_examples) #shuffle 的 buffer_size 參數應大於等於樣本數,相當於開闢一個存儲數據的空間,batch 可以指定 batch_size 的分割大小。
dataset = dataset.batch(batch_size) #取數據
for batch_x, batch_y in dataset :
print(batch_x, batch_y)
break
結果:
3、定義模型和初始化參數
def linreg():
model=tf.keras.Sequential()
model.add(tf.keras.layers.Dense(1,kernel_initializer=tf.random_normal_initializer(stddev=0.01)))
return model
4、定義損失函數
loss = tf.losses.MeanSquaredError()
5、定義優化器
trainer = tf.keras.optimizers.SGD(learning_rate=0.03)
6、訓練
num_epochs = 10
for epoch in range(1, num_epochs + 1):
train_loss, num_count = 0, 0
for X, y in dataset:
num_count+=1
with tf.GradientTape() as tape:
l = loss(net(X, training=True), y)
grads = tape.gradient(l, net.trainable_variables) #通過 model.trainable_variables 找到需要更新的變量
trainer.apply_gradients(zip(grads, net.trainable_variables))#使用 trainer.apply_gradients 更新權重
train_loss += tf.reduce_sum(l).numpy()
print('epoch %d, loss: %f' % (epoch, train_loss/num_count))
結果:
7、預測結果
print(true_w, net.get_weights()[0])
print(true_b,net.get_weights()[1])
結果:
可以看到,上節我們使用了整整50個epoch纔將loss訓練到比較小的地步,而使用高階API,訓練速度還加快了。
下面附上所有代碼:
import tensorflow as tf
from tensorflow import data as tfdata
#1、生成數據集
tf.random.set_seed(99)
num_inputs = 2
num_examples = 1000
true_w = [2, -3.4] #真實權重
true_b = 4.2 # 真實偏置值
features = tf.random.normal((num_examples, num_inputs),stddev =1)
labels = true_w[0] * features[:,0] + true_w[1] * features[:,1] + true_b
labels += tf.random.normal(labels.shape,stddev=0.01)
#2、讀取數據
batch_size = 10
# 將訓練數據的特徵和標籤組合
dataset = tfdata.Dataset.from_tensor_slices((features, labels))
# 隨機讀取小批量
dataset = dataset.shuffle(buffer_size=num_examples) #shuffle 的 buffer_size 參數應大於等於樣本數,相當於開闢一個存儲數據的空間,batch 可以指定 batch_size 的分割大小。
dataset = dataset.batch(batch_size) #取數據
for batch_x, batch_y in dataset:
print(batch_x, batch_y)
break
#3、定義模型和初始化參數
def linreg():
model=tf.keras.Sequential()
model.add(tf.keras.layers.Dense(1,kernel_initializer=tf.random_normal_initializer(stddev=0.01)))
return model
net=linreg()
#4、定義損失函數
loss = tf.losses.MeanSquaredError()
#5、定義優化器
trainer = tf.keras.optimizers.SGD(learning_rate=0.03)
#6、訓練
'''
通過調用tf.GradientTape記錄動態圖梯度,執行tape.gradient獲得動態圖中各變量梯度。
通過 model.trainable_variables 找到需要更新的變量,並用 trainer.apply_gradients 更新權重,
完成一步訓練。
'''
num_epochs = 10
for epoch in range(1, num_epochs + 1):
train_loss, num_count = 0, 0
for X, y in dataset:
num_count+=1
with tf.GradientTape() as tape:
l = loss(net(X, training=True), y)
grads = tape.gradient(l, net.trainable_variables) #通過 model.trainable_variables 找到需要更新的變量
trainer.apply_gradients(zip(grads, net.trainable_variables))#使用 trainer.apply_gradients 更新權重
train_loss += tf.reduce_sum(l).numpy()
print('epoch %d, loss: %f' % (epoch, train_loss/num_count))
#7、預測結果
print(true_w, net.get_weights()[0])
print(true_b,net.get_weights()[1])