zoukankan      html  css  js  c++  java
  • Tensorflow教程分享:TensorFlow 基础详解

      目录

      计算图纸

      Tensor 张量意义

      自动求导机制

      基础示例:线性回归

      NumPy 下的线性回归

      TensorFlow 下的线性回归

      计算图纸

      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的常量矩阵

      以此类推, 还有 三阶 三维的 …

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

      # 查看矩阵A的形状、类型和值

      print(A.shape) # 输出(2, 2),即矩阵的长和宽均为2

      print(A.dtype) # 输出

      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) = |Xw + b - y|^2

      L(w,b)=∥Xw+b−y∥2

      X = egin{bmatrix} 1 & 2 \ 3 & 4 end{bmatrix}, y = egin{bmatrix} 1 \ 2end{bmatrix}

      X=[13​24​],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

      frac{partial L(w, b)}{partial w} |_{w = (1, 2)^T, b = 1} = egin{bmatrix} 70 \ 100end{bmatrix}

      ∂w∂L(w,b)​∣w=(1,2)T,b=1​=[70100​]

      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 = ax + b大连人流医院 http://mobile.bhbyby.net/

      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) 求局部极小值,梯度下降 的过程如下:

      初始化自变量为

      x_0 , k=0

      x0​,k=0迭代进行下列步骤直到满足收敛条件:

      求函数f(x)

      f(x) 关于自变量的梯度

       abla f(x_k)

      ∇f(xk​)更新自变量

      x_{k+1} = x_{k} - gamma abla f(x_k)

      xk+1​=xk​−γ∇f(xk​) 。这里

      γgamma

      γ 是学习率(也就是梯度下降一次迈出的 “步子” 大小)

      k leftarrow k+1

      k←k+1

      接下来,我们考虑如何使用程序来实现梯度下降方法,求得线性回归的解

      min_{a, b} L(a, b) = sum_{i=1}^n(ax_i + b - y_i)^2

      mina,b​L(a,b)=∑i=1n​(axi​+b−yi​)2 。

      NumPy 下的线性回归

      在以下代码中,我们手工求损失函数关于参数 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 下的线性回归

      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 获取模型参数。

  • 相关阅读:
    Vue学习笔记(4)-带参数路由,嵌套路由,编程式导航
    JS数组&&数组对象去重
    Vue学习笔记(3)-品牌管理系统
    Vue学习笔记(2)-组件生命周期
    负margin
    CSS布局奇淫巧计之-强大的负边距
    由浅入深漫谈margin属性
    双飞翼布局和圣杯布局的对比
    圣杯布局的实现过程
    CSS实现垂直居中的5种方法
  • 原文地址:https://www.cnblogs.com/djw12333/p/14463729.html
Copyright © 2011-2022 走看看