4.2 TensorFlow基础
学习目标
-
目标
-
掌握TensorFlow基本张量操作
-
掌握TensorFlow的自动求导机制
-
-
应用
-
无
-
4.2.1 Tensorflow 计算
TensorFlow 视为一个科学计算库。导入TensorFlow
import tensorflow as tf
TensorFlow 使用 张量 (Tensor)作为数据的基本单位。TensorFlow 的张量在概念上等同于多维数组,我们可以使用它来描述数学中的标量(0 维数组)、向量(1 维数组)、矩阵(2 维数组)等各种量,示例如下:
# 定义一个随机数(标量)
# 定义一个随机数(标量)
random_float = tf.random.uniform(shape=())
# 定义一个有2个元素的零向量
zero_vector = tf.zeros(shape=(2))
# 定义两个2×2的常量矩阵
A = tf.constant([[1., 2.], [3., 4.]])
B = tf.constant([[5., 6.], [7., 8.]])
4.2.1.1 张量的类型
4.2.1.2 张量的阶
形状有0阶、1阶、2阶….
tensor1 = tf.constant(4.0)
tensor2 = tf.constant([1, 2, 3, 4])
linear_squares = tf.constant([[4], [9], [16], [25]], dtype=tf.int32)
print(tensor1.shape)
# 0维:() 1维:(10, ) 2维:(3, 4) 3维:(3, 4, 5)
4.2.2 张量操作
-
固定值张量
-
随机值张量
-
张量的变换
-
算术运算符
-
基本数学函数
-
矩阵运算
-
reduce操作
-
序列索引操作
参考官网链接:https://www.tensorflow.org/api_docs/python/tf/Tensor
4.2.3 自动求导机制
在机器学习中,我们经常需要计算函数的导数。TensorFlow 提供了强大的自动求导机制来计算导数。
1、使用 tf.GradientTape() 计算函数
y(x)=x^{2}
import tensorflow as tf
x = tf.Variable(initial_value=3.)
with tf.GradientTape() as tape: # 在 tf.GradientTape() 的上下文内,所有计算步骤都会被记录以用于求导
y = tf.square(x)
y_grad = tape.gradient(y, x) # 计算y关于x的导数
print([y, y_grad])
输出:
[array([9.], dtype=float32), array([6.], dtype=float32)]
-
1、这里x是一个初始化为 3 的 变量 (Variable),使用 tf.Variable()声明。与普通张量一样,变量同样具有形状、类型和值三种属性。使用变量需要有一个初始化过程,可以通过在 tf.Variable()中指定 initial_value 参数来指定初始值。
-
变量与普通张量的一个重要区别是其默认能够被 TensorFlow 的自动求导机制所求导,因此往往被用于定义机器学习模型的参数。
-
-
tf.GradientTape() 是一个自动求导的记录器,在其中的变量和计算步骤都会被自动记录。在上面的示例中,变量 x和计算步骤 y = tf.square(x) 被自动记录,因此可以通过 y_grad = tape.gradient(y, x) 求张量 y 对变量 x 的导数。
2、多元函数求导
X = tf.constant([[1, 2], [3., 4.]])
y = tf.constant([[1], [2.]])
w = tf.Variable(initial_value=[[1.], [2.]])
b = tf.Variable(initial_value=1.)
with tf.GradientTape() as tape:
L = 0.5 * tf.reduce_sum(tf.square(tf.matmul(X, w) + b - y))
w_grad, b_grad = tape.gradient(L, [w, b])
print([L.numpy(), w_grad.numpy(), b_grad.numpy()])
输出:
[62.5, array([[35.],
[50.]], dtype=float32), 15.0]
求导公式如下:
4.2.4 案例:线性回归
考虑一个实际问题,某城市在 2013 年 - 2017 年的房价如下表所示:
年份 | 2013 | 2014 | 2015 | 2016 | 2017 |
房价 | 12000 | 14000 | 15000 | 16500 | 17500 |
现在,我们希望通过对该数据进行线性回归,即使用线性模型y = ax + by=ax+b来拟合上述数据,此处 a 和 b是待求的参数。首先,我们定义数据,进行基本的归一化操作。
import numpy as np
X_raw = np.array([2013, 2014, 2015, 2016, 2017], dtype=np.float32)
y_raw = np.array([12000, 14000, 15000, 16500, 17500], dtype=np.float32)
X = (X_raw - X_raw.min()) / (X_raw.max() - X_raw.min())
y = (y_raw - y_raw.min()) / (y_raw.max() - y_raw.min())
回顾机器学习的基础知识,对于多元函数 求局部极小值,梯度下降 的过程如下:
1、NumPy 下的线性回归
NumPy 提供了多维数组支持,可以表示向量、矩阵以及更高维的张量。下面为实现过程:
a, b = 0, 0
num_epoch = 10000
learning_rate = 1e-3
for e in range(num_epoch):
# 手动计算损失函数关于自变量(模型参数)的梯度
y_pred = a * X + b
grad_a, grad_b = (y_pred - y).dot(X), (y_pred - y).sum()
# 更新参数
a, b = a - learning_rate * grad_a, b - learning_rate * grad_b
print(a, b)
# 更新参数
a, b = a - learning_rate * grad_a, b - learning_rate * grad_b
print(a, b)
使用常规的科学计算库实现机器学习模型的问题:
-
1、需要手工求函数关于参数的偏导数,但一旦函数的形式变得复杂(尤其是深度学习模型),手工求导的过程将变得非常痛苦,甚至不可行。
-
2、需要手工根据求导的结果更新参数。这里使用了最基础的梯度下降方法,因此参数的更新还较为容易。但如果使用更加复杂的参数更新方法(例如 Adam 或者 Adagrad),这个更新过程的编写同样会非常繁杂。
而 TensorFlow 等深度学习框架的出现很大程度上解决了这些痛点,为机器学习模型的实现带来了很大的便利。
2、TensorFlow 下的线性回归
TensorFlow 的 Eager Execution(动态图)模式与上述 NumPy 的运行方式十分类似,然而提供了更快速的运算(GPU 支持)、自动求导、优化器等一系列对深度学习非常重要的功能。
-
使用 tape.gradient(ys, xs) 自动计算梯度;
-
使用 optimizer.apply_gradients(grads_and_vars) 自动更新模型参数。
-
使用tf.keras.optimizers.SGD(learning_rate=)进行指定优化器
# 1、定义Tensor类型
X = tf.constant(X)
y = tf.constant(y)
# 2、参数使用变量初始化
a = tf.Variable(initial_value=0.)
b = tf.Variable(initial_value=0.)
variables = [a, b]
num_epoch = 10000
optimizer = tf.keras.optimizers.SGD(learning_rate=1e-3)
for e in range(num_epoch):
# 使用tf.GradientTape()记录损失函数的梯度信息
with tf.GradientTape() as tape:
y_pred = a * X + b
loss = 0.5 * tf.reduce_sum(tf.square(y_pred - y))
# TensorFlow自动计算损失函数关于自变量(模型参数)的梯度
grads = tape.gradient(loss, variables)
# TensorFlow自动根据梯度更新参数
optimizer.apply_gradients(grads_and_vars=zip(grads, variables))
print(a, b)
-
tf.keras.optimizers.SGD(learning_rate=1e-3) 声明了一个梯度下降 优化器 (Optimizer),其学习率为 1e-3。优化器可以帮助我们根据计算出的求导结果更新模型参数,从而最小化某个特定的损失函数,具体使用方式是调用其 apply_gradients() 方法。
-
更新模型参数的方法 optimizer.apply_gradients() 需要提供参数 grads_and_vars,具体而言,这里需要传入一个 Python 列表(List),列表中的每个元素是一个 (变量的偏导数,变量) 对,比如这里是 [(grad_a, a), (grad_b, b)]。
在实际应用中,我们编写的模型往往比这里一行就能写完的线性模型 y = a * x + b 要复杂得多。所以,我们往往会编写并实例化一个模型类model = Model(),然后使用 y_pred = model(X)调用模型,使用 model.variables 获取模型参数。
4.2.5 总结
-
TensorFlow基本张量操作
-
TensorFlow自动求导机制