【Tensorflow教程笔记】TensorFlow 基础

  1. 基础
    TensorFlow 基础
    TensorFlow 模型建立与训练
    基础示例:多层感知机(MLP)
    卷积神经网络(CNN)
    循环神经网络(RNN)
    深度强化学习(DRL)
    Keras Pipeline
    自定义层、损失函数和评估指标
    常用模块 tf.train.Checkpoint :变量的保存与恢复
    常用模块 TensorBoard:训练过程可视化
    常用模块 tf.data :数据集的构建与预处理
    常用模块 TFRecord :TensorFlow 数据集存储格式
    常用模块 tf.function :图执行模式
    常用模块 tf.TensorArray :TensorFlow 动态数组
    常用模块 tf.config:GPU 的使用与分配

  2. 部署
    TensorFlow 模型导出
    TensorFlow Serving
    TensorFlow Lite

  3. 大规模训练与加速
    TensorFlow 分布式训练
    使用 TPU 训练 TensorFlow 模型

  4. 扩展
    TensorFlow Hub 模型复用
    TensorFlow Datasets 数据集载入

  5. 附录
    强化学习基础简介


计算图纸

Tensorflow 首先要定义神经网络的结构, 然后再把数据放入结构当中去运算和 training.
在这里插入图片描述
因为TensorFlow是采用 数据流图(data flow graphs) 来计算, 所以首先我们得创建一个数据流图, 然后再将我们的数据(数据以张量(tensor)的形式存在)放在数据流图中计算. 节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组, 即张量(tensor). 训练模型时tensor会不断的从数据流图中的一个节点flow到另一节点, 这就是TensorFlow名字的由来.

Tensor 张量意义

张量(Tensor): 张量有多种.

  • 零阶张量为 纯量或标量 (scalar) 也就是一个数值. 比如 [1]
    random_float = tf.random.uniform(shape=()) 定义一个随机数
  • 一阶张量为 向量 (vector), 比如 一维的 [1, 2]
    zero_vector = tf.zeros(shape=(2)) 定义一个有2个元素的零向量
  • 二阶张量为 矩阵 (matrix), 比如 二维的 [[1, 2],[3, 4]]
    A = tf.constant([[1., 2.], [3., 4.]]) 定义一个2×2的常量矩阵
  • 以此类推, 还有 三阶 三维的 …

张量的重要属性是其形状、类型和值。可以通过张量的 shapedtype 属性和 numpy() 方法获得。例如:

# 查看矩阵A的形状、类型和值
print(A.shape)      # 输出(2, 2),即矩阵的长和宽均为2
print(A.dtype)      # 输出<dtype: 'float32'>
print(A.numpy())    # 输出[[1. 2.]
                    #      [3. 4.]]
  • TensorFlow 的大多数 API 函数会根据输入的值自动推断张量中元素的类型(一般默认为 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+by2 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} wL(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 bL(w,b)w=(1,2)T,b=1=30

基础示例:线性回归

考虑一个实际问题,某城市在 2013 年 - 2017 年的房价如下表所示:
在这里插入图片描述
现在,我们希望通过对该数据进行线性回归,即使用线性模型 y = a x + b y = ax + b y=ax+b 来拟合上述数据,此处 ab 是待求的参数。

首先,我们定义数据,进行基本的归一化操作。

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())

接下来,我们使用梯度下降方法来求线性模型中两个参数 ab 的值。

回顾机器学习的基础知识,对于多元函数 f ( x ) f(x) f(x) 求局部极小值,梯度下降 的过程如下:

  • 初始化自变量为 x 0 , k = 0 x_0 , k=0 x0k=0
  • 迭代进行下列步骤直到满足收敛条件:
    • 求函数 f ( x ) f(x) f(x) 关于自变量的梯度 ∇ f ( x k ) \nabla f(x_k) f(xk)
    • 更新自变量: x k + 1 = x k − γ ∇ f ( x k ) x_{k+1} = x_{k} - \gamma \nabla f(x_k) xk+1=xkγf(xk) 。这里 γ \gamma γ 是学习率(也就是梯度下降一次迈出的 “步子” 大小)
    • k ← k + 1 k \leftarrow k+1 kk+1

接下来,我们考虑如何使用程序来实现梯度下降方法,求得线性回归的解 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+byi)2

NumPy 下的线性回归

在以下代码中,我们手工求损失函数关于参数 ab 的偏导数,并使用梯度下降法反复迭代,最终获得 ab 的值。

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 下的线性回归

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))
  • 在这里,我们使用了前文的方式计算了损失函数关于参数的偏导数。

  • 同时,使用 tf.keras.optimizers.SGD(learning_rate=5e-4) 声明了一个梯度下降 优化器 (Optimizer),其学习率为 5e-4。优化器可以帮助我们根据计算出的求导结果更新模型参数,从而最小化某个特定的损失函数,具体使用方式是调用其 apply_gradients() 方法。

  • 注意到这里,更新模型参数的方法 optimizer.apply_gradients() 需要提供参数 grads_and_vars,即待更新的变量(如上述代码中的 variables )及损失函数关于这些变量的偏导数(如上述代码中的 grads )。

  • 具体而言,这里需要传入一个 Python 列表(List),列表中的每个元素是一个(变量的偏导数,变量) 对。比如上例中需要传入的参数是 [(grad_a, a), (grad_b, b)] 。我们通过 grads = tape.gradient(loss, variables) 求出 tape 中记录的 loss 关于 variables = [a, b] 中每个变量的偏导数,也就是 grads = [grad_a, grad_b],再使用 Python 的 zip() 函数将 grads = [grad_a, grad_b]variables = [a, b] 拼装在一起,就可以组合出所需的参数了。

在实际应用中,我们编写的模型往往比这里一行就能写完的线性模型 y_pred = a * X + b (模型参数为 variables = [a, b] )要复杂得多。所以,我们往往会编写并实例化一个模型类 model = Model() ,然后使用 y_pred = model(X) 调用模型,使用 model.variables 获取模型参数。

  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值