1. 使用 tensorflow 的 keras 接口实现线性回归
import tensorflow as tf
from tensorflow import data as tfdata
2. 生成数据集
# 数据维度
num_input = 2
# 元素个数
num_examples = 1000
# 参数
true_w = [2, -3.4]
true_b = 4.2
# 生成特征, 特征基于正太分布, 均值方差为1的随机数
features = tf.random.normal(shape=(num_examples, num_input), stddev=1)
# 基于 true_w, true_b 生成标签
labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
# 加入随机噪声值
labels += tf.random.normal(shape=labels.shape, stddev=0.01)
3. 读取数据
- 基于 Tensorflow 的 data 模块划分数据
- shuffle 的 buffer_size 参数应大于等于样本数,batch 可以指定 batch_size 的分割大小。
- iter(dataset) : 返回支持迭代的集合对象, 参考 : Python iter 函数
# 定义数据批次大小
batch_size = 10
# 组合数据集的标签和样本
dataset = tfdata.Dataset.from_tensor_slices((features, labels))
# 随机读取小批量数据
dataset = dataset.shuffle(buffer_size=num_examples)
dataset = dataset.batch(batch_size)
data_iter = iter(dataset)
4. 定义模型和初始化参数
-
Tensorflow 2.0推荐使用 Keras 定义网络,故使用 Keras 定义网络 我们先定义一个模型变量 model,它是一个 Sequential 实例。 在 Keras 中,Sequential 实例可以看作是一个串联各个层的容器。
-
在构造模型时,我们在该容器中依次添加层。 当给定输入数据时,容器中的每一层将依次推断下一层的输入尺寸。 重要的一点是,在 Keras 中我们无须指定每一层输入的形状。 线性回归,输入层与输出层等效为一层全连接层 keras.layers.Dense()。
-
Keras 中初始化参数由 kernel_initializer 和 bias_initializer 选项分别设置权重和偏置的初始化方式。我们从 tensorflow 导入 initializers 模块,指定权重参数每个元素将在初始化时随机采样于均值为0、标准差为0.01的正态分布。偏差参数默认会初始化为零。RandomNormal(stddev=0.01) 指定权重参数每个元素将在初始化时随机采样于均值为0、标准差为0.01的正态分布。偏差参数默认会初始化为零。
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow import initializers as init
# Sequential实例可以看作是一个串联各个层的容器。
model = keras.Sequential()
# 添加连接层, RandomNormal 指定权重参数, 偏差参数默认初始化为0
model.add(layers.Dense(1, kernel_initializer=init.RandomNormal(stddev=0.01)))
5. 定义损失函数
- Tensoflow在losses模块中提供了各种损失函数和自定义损失函数的基类,并直接使用它的均方误差损失作为模型的损失函数
from tensorflow import losses
loss = losses.MeanSquaredError() # 使用均值误差作为模型的参数
6. 定义优化参数
- 我们也无须自己实现小批量随机梯度下降算法。tensorflow.keras.optimizers 模块提供了很多常用的优化算法比如SGD、Adam和RMSProp等。下面我们创建一个用于优化model 所有参数的优化器实例,并指定学习率为0.03的小批量随机梯度下降(SGD)为优化算法。
from tensorflow.keras import optimizers
trainer = optimizers.SGD(learning_rate=0.02)
7. 训练模型
- 在使用Tensorflow训练模型时,我们通过调用tensorflow.GradientTape记录动态图梯度,执行tape.gradient获得动态图中各变量梯度。通过 model.trainable_variables 找到需要更新的变量,并用 trainer.apply_gradients 更新权重,完成一步训练。
- 使用初始随机的参数, 计算预测值, 然后根据预测值和标签计算误差, 根据误差调整参数
num_epoch = 10
for epoch in range(num_epoch):
for (batch, (x, y)) in enumerate(dataset):
with tf.GradientTape() as tape:
l = loss(model(x, training=True), y)
grid = tape.gradient(l, model.trainable_variables) # model.trainable_variables 是需要更新的变量
trainer.apply_gradients(zip(grid, model.trainable_variables)) # 更新权重
l = loss(model(features), labels)
print('epoch %d, loss : %f' % (epoch, l))
epoch 0, loss : 0.007073
epoch 1, loss : 0.000100
epoch 2, loss : 0.000099
epoch 3, loss : 0.000099
epoch 4, loss : 0.000099
epoch 5, loss : 0.000099
epoch 6, loss : 0.000099
epoch 7, loss : 0.000099
epoch 8, loss : 0.000099
epoch 9, loss : 0.000099
- 比较学习到的模型和误差
true_w , model.get_weights()[0]
([2, -3.4],
array([[ 1.9997687],
[-3.4000773]], dtype=float32))
true_b, model.get_weights()[1]
(4.2, array([4.200079], dtype=float32))
8. 总结
- tensorflow.data模块提供了有关数据处理的工具
- tensorflow.keras.layers模块定义了大量神经网络的层
- tensorflow.initializers模块定义了各种初始化方法
- tensorflow.optimizers模块提供了模型的各种优化算法