计算图纸
Tensorflow 首先要定义神经网络的结构, 然后再把数据放入结构当中去运算和 training.
因为TensorFlow是采用 数据流图(data flow graphs) 来计算, 所以首先我们得创建一个数据流图, 然后再将我们的数据(数据以张量(tensor)的形式存在)放在数据流图中计算. 节点(Nodes)
在图中表示数学操作,图中的线(edges)
则表示在节点间相互联系的多维数据数组, 即张量(tensor)
. 训练模型时tensor会不断的从数据流图中的一个节点flow到另一节点, 这就是TensorFlow名字的由来.Tensor 张量意义
张量(Tensor): 张量有多种.
random_float = tf.random.uniform(shape=())
定义一个随机数zero_vector = tf.zeros(shape=(2))
定义一个有2个元素的零向量A = tf.constant([[1., 2.], [3., 4.]])
定义一个2×2的常量矩阵张量的重要属性是其形状、类型和值。可以通过张量的 shape
、 dtype
属性和 numpy()
方法获得。例如:
登录后复制
# 查看矩阵A的形状、类型和值
print(A.shape) # 输出(2, 2),即矩阵的长和宽均为2
print(A.dtype) # 输出<dtype: 'float32'>
print(A.numpy()) # 输出[[1. 2.]
# [3. 4.]]
tf.float32
)。不过你也可以通过加入 dtype
参数来自行指定类型,例如 zero_vector = tf.zeros(shape=(2), dtype=tf.int32)
将使得张量中的元素类型均为整数。numpy()
方法是将张量的值转换为一个 NumPy 数组。自动求导机制 在机器学习中,我们经常需要计算函数的导数。TensorFlow 提供了强大的 自动求导机制 来计算导数。在即时执行模式下,TensorFlow 引入了 tf.GradientTape()
这个 “求导记录器” 来实现自动求导。
在机器学习中,更加常见的是对多元函数求偏导数,以及对向量或矩阵的求导。这些对于 TensorFlow 也不在话下。以下代码展示了如何使用 tf.GradientTape()
计算函数 L ( w , b ) = ∥ X w + b − y ∥ 2 L(w, b) = \|Xw + b - y\|^2 L(w,b)=∥Xw+b−y∥2在 w = ( 1 , 2 ) T w = (1, 2)^T w=(1,2)T, b = 1 b = 1 b=1 时分别对 w , b w, b w,b 的偏导数。其中 X = [ 1 2 3 4 ] , y = [ 1 2 ] X = \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix}, y = \begin{bmatrix} 1 \\ 2\end{bmatrix} X=[1324],y=[12]。
登录后复制
import tensorflow as tf
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 = tf.reduce_sum(tf.square(tf.matmul(X, w) + b - y))
w_grad, b_grad = tape.gradient(L, [w, b]) # 计算L(w, b)关于w, b的偏导数
print(L, w_grad, b_grad)
输出:
登录后复制
tf.Tensor(125.0, shape=(), dtype=float32)
tf.Tensor(
[[ 70.]
[100.]], shape=(2, 1), dtype=float32)
tf.Tensor(30.0, shape=(), dtype=float32)
tf.square()
操作代表对输入张量的每一个元素求平方,不改变张量形状。tf.reduce_sum()
操作代表对输入张量的所有元素求和,输出一个形状为空的纯量张量(可以通过 axis
参数来指定求和的维度,不指定则默认对所有元素求和)。从输出可见,TensorFlow 帮助我们计算出了
L ( ( 1 , 2 ) T , 1 ) = 125 L((1, 2)^T, 1) = 125 L((1,2)T,1)=125
∂ L ( w , b ) ∂ w ∣ w = ( 1 , 2 ) T , b = 1 = [ 70 100 ] \frac{\partial L(w, b)}{\partial w} |_{w = (1, 2)^T, b = 1} = \begin{bmatrix} 70 \\ 100\end{bmatrix} ∂w∂L(w,b)∣w=(1,2)T,b=1=[70100]
∂ L ( w , b ) ∂ b ∣ w = ( 1 , 2 ) T , b = 1 = 30 \frac{\partial L(w, b)}{\partial b} |_{w = (1, 2)^T, b = 1} = 30 ∂b∂L(w,b)∣w=(1,2)T,b=1=30基础示例:线性回归
考虑一个实际问题,某城市在 2013 年 - 2017 年的房价如下表所示:
现在,我们希望通过对该数据进行线性回归,即使用线性模型 y = a x + b y = ax + b y=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())
接下来,我们使用梯度下降方法来求线性模型中两个参数 a
和 b
的值。
回顾机器学习的基础知识,对于多元函数 f ( x ) f(x) f(x) 求局部极小值,梯度下降 的过程如下:
接下来,我们考虑如何使用程序来实现梯度下降方法,求得线性回归的解 min a , b L ( a , b ) = ∑ i = 1 n ( a x i + b − y i ) 2 \min_{a, b} L(a, b) = \sum_{i=1}^n(ax_i + b - y_i)^2 mina,bL(a,b)=∑i=1n(axi+b−yi)2 。
在以下代码中,我们手工求损失函数关于参数 a
和 b
的偏导数,并使用梯度下降法反复迭代,最终获得 a
和 b
的值。
登录后复制
a, b = 0, 0
num_epoch = 10000
learning_rate = 5e-4
for e in range(num_epoch):
# 手动计算损失函数关于自变量(模型参数)的梯度
y_pred = a * X + b
grad_a, grad_b = 2 * (y_pred - y).dot(X), 2 * (y_pred - y).sum()
# 更新参数
a, b = a - learning_rate * grad_a, b - learning_rate * grad_b
print(a, b)
TensorFlow 的 即时执行模式 与上述 NumPy 的运行方式十分类似,然而提供了更快速的运算(GPU 支持)、自动求导、优化器等一系列对深度学习非常重要的功能。以下展示了如何使用 TensorFlow 计算线性回归。可以注意到,程序的结构和前述 NumPy 的实现非常类似。这里,TensorFlow 帮助我们做了两件重要的工作:
tape.gradient(ys, xs)
自动计算梯度;optimizer.apply_gradients(grads_and_vars)
自动更新模型参数。登录后复制
X = tf.constant(X)
y = tf.constant(y)
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=5e-4)
for e in range(num_epoch):
# 使用tf.GradientTape()记录损失函数的梯度信息
with tf.GradientTape() as tape:
y_pred = a * X + b
loss = tf.reduce_sum(tf.square(y_pred - y))
# TensorFlow自动计算损失函数关于自变量(模型参数)的梯度
grads = tape.gradient(loss, variables)
# TensorFlow自动根据梯度更新参数
optimizer.apply_gradients(grads_and_vars=zip(grads, variables))
在实际应用中,我们编写的模型往往比这里一行就能写完的线性模型 y_pred = a * X + b
(模型参数为 variables = [a, b]
)要复杂得多。所以,我们往往会编写并实例化一个模型类 model = Model()
,然后使用 y_pred = model(X)
调用模型,使用 model.variables
获取模型参数。
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删