白话 Broadcasting

文章目录

  • 什么是 Broadcasting
  • Broadcasting 的规则
  • 逐元素操作
    • 向量与标量运算
    • 矩阵与向量运算
      • 行向量
      • 列向量
    • 张量与向量运算
    • 张量与矩阵运算
  • 矩阵与张量的点积
  • 总结

什么是 Broadcasting

在 《白话张量》 中我们讲过,张量之间进行运算需要满足一定的维数条件的,形状大小不满足条件的两个张量之间是无法进行运算的。为了能执行运算,我们通常需要将较小的张量被“拉伸”到与较大张量兼容的形状,这一步“拉伸”操作就是 Broadcasting。

图1. Broadcasting 示意图

Broadcasting 在不创建重复数据的情况下确保张量运算可以执行,从而确保算法可以更高效的执行。

Broadcasting 的规则

根据 PyTorch 的文档,张量在以下情况下可以 Broadcasting :

每个张量至少有一个维度

迭代维度大小时,会从尾部维度开始,向前推进,维度大小要么相等,要么其中一个为1或不存在。

比较形状时,尾部维度指的是最右边的数字。我们以上面的图 1 为例,解释一下 Broadcasting 的通用过程:

  1. 确定最右边的维度是否兼容

    • 每个张量是否至少有一个维度?
    • 尺寸是否相等?其中一个是 1 或不存在吗?
  2. 将尺寸拉伸到合适的大小
  3. 对下一个维度重复前面的步骤

逐元素操作

所有按元素操作的运算都要求张量具有相同或兼容的形状。

向量与标量运算

图2. 向量与标量运算中的 Broadcasting 示意图

在此示例中,标量的形状为 ( 1 , ) (1,) (1,) ,向量的形状为 ( 3 , ) (3,) (3,)。 如图 2 所示,标量 b b b 被 Broadcasting 为 ( 3 , ) (3,) (3,) 的形状,并且按预期执行了 Hadamard 乘积。

上面的示例用 PyTorch 实现如下:

import torcha = torch.tensor([1, 2, 3])
b = 2 # 会拉伸为 ([2, 2, 2])a * b
# Output: tensor([2, 4, 6])

矩阵与向量运算

行向量

图3. 矩阵与行向量运算中的 Broadcasting 示意图

在上面示例中,矩阵 A A A 的形状为 ( 3 , 3 ) (3, 3) (3,3),向量 b b b 的形状为 ( 3 , ) (3,) (3,)。当运算时,向量 b b b 被逐行拉伸成一个 ( 3 , 3 ) (3,3) (3,3) 矩阵,如图 3 所示。 现在,A 和 b 的形状都是 ( 3 , 3 ) (3, 3) (3,3),可以进行逐元素操作。

上面的示例用 PyTorch 实现如下:

A = torch.tensor([[1, 2, 3],[4, 5, 6],[7, 8, 9]])b = torch.tensor([1, 2, 3])A * b
# Output: tensor([[ 1,  4,  9],
#                 [ 4, 10, 18],
#                 [ 7, 16, 27]])

列向量

图4. 矩阵与列向量运算中的 Broadcasting 示意图

在上面示例中,矩阵 A A A 的形状为 ( 3 , 3 ) (3, 3) (3,3),列向量 b b b 的形状为 ( 3 , 1 ) (3, 1) (3,1)。当运算时, b b b 被按列拉伸创建另外 2 列,如图 4 所示。 现在,A 和 b 的形状都是 ( 3 , 3 ) (3, 3) (3,3),可以进行逐元素操作。

上面的示例用 PyTorch 实现如下:

A = torch.tensor([[1, 2, 3],[4, 5, 6],[7, 8, 9]])b = torch.tensor([[1], [2], [3]])
A * b
# Output: tensor([[ 1,  2,  3],
#                 [ 8, 10, 12],
#                 [21, 24, 27]])

张量与向量运算

[ [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ] [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ] ] ⊙ [ [ 1 ] [ 2 ] [ 3 ] ] = [ [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ] [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ] ] ⊙ [ [ [ 1 1 1 ] [ 2 2 2 ] [ 3 3 3 ] ] [ [ 1 1 1 ] [ 2 2 2 ] [ 3 3 3 ] ] ] \begin{bmatrix} \begin{bmatrix} [1 \enspace2\enspace 3]\\ [4\enspace 5\enspace 6]\\ [7\enspace 8\enspace 9] \end{bmatrix}\\ \begin{bmatrix} [1\enspace 2\enspace 3]\\ [4\enspace 5\enspace 6]\\ [7\enspace 8\enspace 9] \end{bmatrix}\\ \end{bmatrix}\odot \begin{bmatrix} [1]\\ [2]\\ [3] \end{bmatrix}= \begin{bmatrix} \begin{bmatrix} [1 \enspace2\enspace 3]\\ [4\enspace 5\enspace 6]\\ [7\enspace 8\enspace 9] \end{bmatrix}\\ \begin{bmatrix} [1\enspace 2\enspace 3]\\ [4\enspace 5\enspace 6]\\ [7\enspace 8\enspace 9] \end{bmatrix}\\ \end{bmatrix}\odot \begin{bmatrix} \begin{bmatrix} [1 \enspace \textcolor{red}{1\enspace 1}]\\ [2\enspace \textcolor{red}{2\enspace 2}]\\ [3\enspace \textcolor{red}{3\enspace 3}] \end{bmatrix}\\ \begin{bmatrix} [\textcolor{red}{1\enspace 1\enspace 1}]\\ [\textcolor{red}{2\enspace 2\enspace 2}]\\ [\textcolor{red}{3\enspace 3\enspace 3}] \end{bmatrix}\\ \end{bmatrix} ​ ​[123][456][789]​ ​ ​[123][456][789]​ ​​ ​⊙ ​[1][2][3]​ ​= ​ ​[123][456][789]​ ​ ​[123][456][789]​ ​​ ​⊙ ​ ​[111][222][333]​ ​ ​[111][222][333]​ ​​ ​

3-D 及以上维度的张量很难用图形清晰地展示,这里我改用公式来表达。上面公式中,红字部分展示了向量如何 Broadcasting 到与张量兼容的尺寸。具体来说,上面示例中张量的形状为 ( 2 , 3 , 3 ) (2,3,3) (2,3,3),向量的形状为 ( 3 , 1 ) (3,1) (3,1),维度大小之间的对应关系为:
A = ( 2 , 3 , 3 ) b = ( , 3 , 1 ) \mathcal{A} = (2,3,3)\\ b = (\enspace,3,1) A=(2,3,3)b=(,3,1)
从最右边的维度开始,每个元素按列拉伸以生成 ( 3 , 3 ) (3, 3) (3,3) 矩阵。中间维度尺寸相等,无需拉伸。 b b b 不存在最左边的维度,因此必须添加一个维度。因此,必须 Broadcasting b b b 拉伸后的矩阵以创建大小为 ( 2 , 3 , 3 ) (2, 3, 3) (2,3,3) 的张量,张量中包含两个 ( 3 , 3 ) (3, 3) (3,3) 矩阵。此时张量 A \mathcal{A} A 与向量 b b b Broadcasting 后得到的张量形状相同,可以计算 Hadamard 积。

上面的示例用 PyTorch 实现如下:

A = torch.tensor([[[1, 2, 3],[4, 5, 6],[7, 8, 9]],[[1, 2, 3],[4, 5, 6],[7, 8, 9]]])b = torch.tensor([[1], [2], [3]])A * b
# Output: tensor([[[ 1,  2,  3],
#                  [ 8, 10, 12],
#                  [21, 24, 27]],
#
#                 [[ 1,  2,  3],
#                  [ 8, 10, 12],
#                  [21, 24, 27]]])

张量与矩阵运算

[ [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ] [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ] ] ⊙ [ [ 1 2 3 ] [ 1 2 3 ] [ 1 2 3 ] ] = [ [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ] [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ] ] ⊙ [ [ [ 1 2 3 ] [ 1 2 3 ] [ 1 2 3 ] ] [ [ 1 2 3 ] [ 1 2 3 ] [ 1 2 3 ] ] ] \begin{bmatrix} \begin{bmatrix} [1 \enspace2\enspace 3]\\ [4\enspace 5\enspace 6]\\ [7\enspace 8\enspace 9] \end{bmatrix}\\ \begin{bmatrix} [1\enspace 2\enspace 3]\\ [4\enspace 5\enspace 6]\\ [7\enspace 8\enspace 9] \end{bmatrix}\\ \end{bmatrix}\odot \begin{bmatrix} [1\enspace 2\enspace 3]\\ [1\enspace 2\enspace 3]\\ [1\enspace 2\enspace 3] \end{bmatrix}= \begin{bmatrix} \begin{bmatrix} [1 \enspace2\enspace 3]\\ [4\enspace 5\enspace 6]\\ [7\enspace 8\enspace 9] \end{bmatrix}\\ \begin{bmatrix} [1\enspace 2\enspace 3]\\ [4\enspace 5\enspace 6]\\ [7\enspace 8\enspace 9] \end{bmatrix}\\ \end{bmatrix}\odot \begin{bmatrix} \begin{bmatrix} [1 \enspace 2\enspace 3]\\ [1\enspace 2\enspace 3]\\ [1\enspace 2\enspace 3] \end{bmatrix}\\ \begin{bmatrix} [\textcolor{red}{1\enspace 2\enspace 3}]\\ [\textcolor{red}{1\enspace 2\enspace 3}]\\ [\textcolor{red}{1\enspace 2\enspace 3}] \end{bmatrix}\\ \end{bmatrix} ​ ​[123][456][789]​ ​ ​[123][456][789]​ ​​ ​⊙ ​[123][123][123]​ ​= ​ ​[123][456][789]​ ​ ​[123][456][789]​ ​​ ​⊙ ​ ​[123][123][123]​ ​ ​[123][123][123]​ ​​ ​

理解了上面张量与向量的运算,张量与矩阵的运算会很简单。上面示例中张量的形状为 ( 2 , 3 , 3 ) (2,3,3) (2,3,3),矩阵的形状为 ( 3 , 3 ) (3,3) (3,3),维度大小之间的对应关系为:
A = ( 2 , 3 , 3 ) B = ( , 3 , 3 ) \mathcal{A} = (2,3,3)\\ B = (\enspace,3,3) A=(2,3,3)B=(,3,3)
这个例子比上一个更容易,因为最右边的两个维度是相同的。这意味着矩阵只需在最左边的维度上 Broadcasting 即可变为 ( 2 , 3 , 3 ) (2, 3, 3) (2,3,3) 的形状。而这仅意味着需要一个额外的矩阵。

上面的示例用 PyTorch 实现如下:

A = torch.tensor([[[1, 2, 3],[4, 5, 6],[7, 8, 9]],[[1, 2, 3],[4, 5, 6],[7, 8, 9]]])B = torch.tensor([[1, 2, 3], [1, 2, 3], [1, 2, 3]])A * B
# Output: tensor([[[ 1,  4,  9],
#                  [ 4, 10, 18],
#                  [ 7, 16, 27]],
#
#                 [[ 1,  4,  9],
#                  [ 4, 10, 18],
#                  [ 7, 16, 27]]])

矩阵与张量的点积

前面所有的示例,目标都是最终得到相同的形状以允许逐元素操作。而点积并不要求两个张量形状一样,只需要第一个矩阵或张量的最后一个维度与第二个矩阵或张量的倒数第二个维度相同即可(详见 《白话张量》 )。

矩阵点积要求
( m , n ) × ( n , r ) = ( m , r ) (m,n) \times (n,r) = (m, r) (m,n)×(n,r)=(m,r)
3维张量点积要求
( c , m , n ) × ( c , n , r ) = ( c , m , r ) (c,m,n) \times (c,n,r) = (c, m, r) (c,m,n)×(c,n,r)=(c,m,r)
4维张量点积要求
( z , c , m , n ) × ( z , c , n , r ) = ( z , c , m , r ) (z,c,m,n) \times (z,c,n,r) = (z,c, m, r) (z,c,m,n)×(z,c,n,r)=(z,c,m,r)
以此类推,可以扩展到任意维张量。

举个例子
[ [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ] [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ] ] ⋅ [ [ 1 2 ] [ 1 2 ] [ 1 2 ] ] = [ [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ] [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ] ] ⋅ [ [ [ 1 2 ] [ 1 2 ] [ 1 2 ] ] [ [ 1 2 ] [ 1 2 ] [ 1 2 ] ] ] \begin{bmatrix} \begin{bmatrix} [1 \enspace2\enspace 3]\\ [4\enspace 5\enspace 6]\\ [7\enspace 8\enspace 9] \end{bmatrix}\\ \begin{bmatrix} [1\enspace 2\enspace 3]\\ [4\enspace 5\enspace 6]\\ [7\enspace 8\enspace 9] \end{bmatrix}\\ \end{bmatrix}\sdot \begin{bmatrix} [1\enspace 2]\\ [1\enspace 2]\\ [1\enspace 2] \end{bmatrix}= \begin{bmatrix} \begin{bmatrix} [1 \enspace2\enspace 3]\\ [4\enspace 5\enspace 6]\\ [7\enspace 8\enspace 9] \end{bmatrix}\\ \begin{bmatrix} [1\enspace 2\enspace 3]\\ [4\enspace 5\enspace 6]\\ [7\enspace 8\enspace 9] \end{bmatrix}\\ \end{bmatrix}\sdot \begin{bmatrix} \begin{bmatrix} [1 \enspace 2]\\ [1\enspace 2]\\ [1\enspace 2] \end{bmatrix}\\ \begin{bmatrix} [\textcolor{red}{1\enspace 2}]\\ [\textcolor{red}{1\enspace 2}]\\ [\textcolor{red}{1\enspace 2}] \end{bmatrix}\\ \end{bmatrix} ​ ​[123][456][789]​ ​ ​[123][456][789]​ ​​ ​⋅ ​[12][12][12]​ ​= ​ ​[123][456][789]​ ​ ​[123][456][789]​ ​​ ​⋅ ​ ​[12][12][12]​ ​ ​[12][12][12]​ ​​ ​
上面例子中,张量 A \mathcal{A} A 的形状为 ( 2 , 3 , 3 ) (2,3,3) (2,3,3),矩阵 B B B 的形状为 ( 3 , 2 ) (3,2) (3,2)。截至目前,最后两个维度是符合点积乘法条件的。只需要将一个维度添加到 B B B,在该维度上 Broadcasting ( 3 , 2 ) (3, 2) (3,2) 矩阵到 ( 2 , 3 , 2 ) (2, 3, 2) (2,3,2) 的形状。因此实例中点积结果为 ( 2 , 3 , 3 ) × ( 2 , 3 , 2 ) = ( 2 , 3 , 2 ) (2, 3, 3) \times (2, 3, 2) = (2, 3, 2) (2,3,3)×(2,3,2)=(2,3,2)。

上面的示例用 PyTorch 实现如下:

A = torch.tensor([[[1, 2, 3],[4, 5, 6],[7, 8, 9]],[[1, 2, 3],[4, 5, 6],[7, 8, 9]]])B = torch.tensor([[1, 2], [1, 2], [1, 2]])A @ B # A.matmul(B)
# Output: tensor([[[ 6, 12],
#                  [15, 30],
#                  [24, 48]],
#
#                 [[ 6, 12],
#                  [15, 30],
#                  [24, 48]]])

总结

Broadcasting 还是很好理解的,并且在实际开发中机器学习框架和库会自动处理,但了解 Broadcasting 的机制对理解代码实现非常有益,因此建议大家还是要了解一下 Broadcasting 。

【白话机器学习系列】白话Broadcasting相关推荐

  1. 白话机器学习-用白话的方式通俗易懂的学习机器学习算法

    白话机器学习 监督学习算法 基础模型 算法理论+实战之K近邻算法 算法理论+实战之决策树 算法理论+实战之朴素贝叶斯 算法理论+实战之支持向量机(SVM) 集成模型 算法理论+实战之Xgboost算法 ...

  2. 【白话机器学习系列】白话向量点积

    白话向量点积 点积(Dot Product)是机器学习中最常见的向量操作.本文将通过简洁易懂的语言配合大量图形为大家介绍点积运算及其背后的数学意义. 文章目录 背景知识 几何视角 向量的大小 Cosi ...

  3. 【白话机器学习系列】白话张量

    白话张量 张量(Tensor)是向量和矩阵向 n n n 维的推广.向量是一维张量,矩阵是二维张量.张量作为数值容器,是机器学习,尤其是深度学习中最基础的操作对象,以至于 Google 的机器学习框架 ...

  4. 【白话机器学习系列】白话 Dropout

    白话 Dropout 文章目录 什么是Dropout 理解缩放 举个例子 什么是Dropout Dropout 是神经网络的一种正则化技术,它在训练时以指定的概率 p p p(常见值为 p = 0.5 ...

  5. 【白话机器学习】算法理论+实战之LightGBM算法

    1. 写在前面 如果想从事数据挖掘或者机器学习的工作,掌握常用的机器学习算法是非常有必要的,在这简单的先捋一捋, 常见的机器学习算法: 监督学习算法:逻辑回归,线性回归,决策树,朴素贝叶斯,K近邻,支 ...

  6. 【白话机器学习】算法理论+实战之Xgboost算法

    1. 写在前面 如果想从事数据挖掘或者机器学习的工作,掌握常用的机器学习算法是非常有必要的,在这简单的先捋一捋, 常见的机器学习算法: 监督学习算法:逻辑回归,线性回归,决策树,朴素贝叶斯,K近邻,支 ...

  7. 【白话机器学习】算法理论+实战之PageRank算法

    1. 写在前面 如果想从事数据挖掘或者机器学习的工作,掌握常用的机器学习算法是非常有必要的,常见的机器学习算法: 监督学习算法:逻辑回归,线性回归,决策树,朴素贝叶斯,K近邻,支持向量机,集成算法Ad ...

  8. 【白话机器学习】算法理论+实战之关联规则

    1. 写在前面 如果想从事数据挖掘或者机器学习的工作,掌握常用的机器学习算法是非常有必要的,常见的机器学习算法: 监督学习算法:逻辑回归,线性回归,决策树,朴素贝叶斯,K近邻,支持向量机,集成算法Ad ...

  9. 【白话机器学习】算法理论+实战之EM聚类

    1. 写在前面 如果想从事数据挖掘或者机器学习的工作,掌握常用的机器学习算法是非常有必要的,常见的机器学习算法: 监督学习算法:逻辑回归,线性回归,决策树,朴素贝叶斯,K近邻,支持向量机,集成算法Ad ...

最新文章

  1. [动态dp]线段树维护转移矩阵
  2. mysql里制造一个错误
  3. PHP用CURL伪造IP和来源
  4. JDK 13中的JEP 355文本块
  5. 信号与系统 chapter10 系统的初值问题与系数匹配法
  6. php软件开发--sphinx索引静态化及伪静态
  7. java下载配置步骤_Java环境构建-JDK下载,安装和配置步骤
  8. 禅道的下载和安装教程(Linux版)
  9. win 7 双击themepack主题包没反应的完美解决方法!
  10. 解决magicdraw16.8无法在win8.1下破解使用
  11. IDEA更改主题颜色
  12. w ndows 10画图,如何在Windows 10中打开和使用画图
  13. 如何在阿里云服务器部署程序并用域名直接访问
  14. 缓冲区,缓存,fflush(stdin)如何使用?
  15. java 发送 邮件通知 HTML模板 个性邮件 (十分钟内完成集成与调试)
  16. RUN 文件安装 postgresql8.4.12
  17. intptr_t详解
  18. Elliptical Grid Mapping(椭圆映射法)
  19. springboot毕设项目养老平台的设计与实现u8sua(java+VUE+Mybatis+Maven+Mysql)
  20. ssh隧道原理及三种隧道转发模式

热门文章

  1. (HttpClient技术)(Hotmail和outlook系列)Hotmail和outlook的邮箱注册破解
  2. 国内各地图API坐标系统比较
  3. Azkaban (二) --------- Azkaban 入门
  4. 固定资产设备管理系统
  5. 千锋教育python2104期总结day5
  6. 2021-10-21千锋教育学习日志
  7. 蜜罐php,PHP表单 – 带验证蜜罐
  8. DNSPOD服务商吴洪声爆料:CSDN数据库被人爆了,密码是明文存储的....
  9. DNSPod十问黑湖智造:让工厂数字化如搭积木一样简单
  10. 最“笨”的方法—蛮力法