《动手学习深度学习》- 基于Tensor flow实现线性回归

《动手学习深度学习》- 基于Tensor flow实现线性回归

Scroll Down

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模块提供了模型的各种优化算法