numpy的深复制与浅复制的区别_numpy使用broadcast进行数学运算

broadcast讲的是numpy在进行数学运算的时候,当shape中的维度不同时,numpy是如何运算的。

我们知道, 在通常情况下,两个数组要进行element-by-element的计算的时候,是需要完全一致的shape的,例如

>>> from numpy import array
>>> a = array([1.0, 2.0, 3.0])
>>> b = array([2.0, 2.0, 2.0])
>>> a * b
array([ 2.,  4.,  6.])

这个很容易理解,对应位置的元素直接进行了相乘

shape(1, 3) * shape(1, 3) = shape(1, 3)。

但是numpy对这种限制进行了放宽,要求shape中的dim未必要完全的一致的。例如

>>> from numpy import array
>>> a = array([1.0,2.0,3.0])
>>> b = 2.0
>>> a * b
array([ 2.,  4.,  6.])

在这里, b只是一个标量值,而不是一个数组。但是他跟shape(1,3)的b得到了同样的结果。那么它是如何处理的呢?

我们可以这么理解:

在跟a进行数学运算的时候,numpy将标量b进行了拉伸,或者称之为扩展、复制。类似于分身一样,为了兼容a,b创建了跟a一样多的自己来跟a进行适配,伟大的b!

883bcb47563bd2af1ccd315f2196e5c9.gif

也就是说,numpy将数组的数学运算不仅仅的局限在了一模一样的shape情况下,而是将其进行了扩展,允许某些数组将自己进行扩展、复制,来适应整个运算。

这个运算规则总结一下就是:

In order to broadcast, the size of the trailing axes for 
both arrays in an operation must either be the same size 
or one of them must be one.

也就是说要进行运算的对应的维度,要么一致,要么其中一个是1。 这种情况下,是可以计算的。

如果不符合这个运算规则的话,就会抛出 ValueError('frames are not aligned') 的异常。如果符合,跑出的结果是:一致的维度,还是不变;不一致的维度的值,取不是1的那个值。

也要注意到,这个结论里面并没有提到shape数完全一致,也就是说shape即使不一致也可以进行这个运算,只要运算的时候,数组都从最低位的维度开始对应,对应的维度满足上面的要求即可。

例如:

6ef8d1501c20fd5bad21812be80b58ad.png

shape(8,1,6,1) * shape(7,1,5) = shape(8,7,6,5)。

我们可以看下下面的代码

>>> from numpy import array
>>> a = array([[ 0.0,  0.0,  0.0],
...            [10.0, 10.0, 10.0],
...            [20.0, 20.0, 20.0],
...            [30.0, 30.0, 30.0]])
>>> b = array([1.0, 2.0, 3.0])
>>> a + b
array([[  1.,   2.,   3.],
       [ 11.,  12.,  13.],
       [ 21.,  22.,  23.],
       [ 31.,  32.,  33.]])

shape(3,3) * shape(1, 3) = shape(3, 3)

他们是按照下面的方法进行运算的:

c0b023f285f6679c394b1af830e68936.png

b把自己进行了复制,从而可以进行计算了。

但是如果b不满足上面的计算条件

678f2d5426811f38c860ced158453b2a.png

这种情况下, b完全不知道该怎么复制自己,因为怎么复制都match不了a,因此是无效的。

理解了上述原理之后, 可以知道, broadcast可以很方便的做外积,例如

>>> from numpy import array, newaxis
>>> a = array([0.0, 10.0, 20.0, 30.0])
>>> b = array([1.0, 2.0, 3.0])
>>> a[:,newaxis] + b
array([[  1.,   2.,   3.],
       [ 11.,  12.,  13.],
       [ 21.,  22.,  23.],
       [ 31.,  32.,  33.]])

可以通过下面的方法来理解:

dfb4f1ab2338dab1581d3ebe618f3733.png

用这种方式,很容易来做一些向量的计算。在tensorflow中,也是这么做的。


ref

(broadcasting介绍)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NumPy中的broadcast_to函数是用来将数组广播到指定形状的函数。广播是一种在不进行复制的情况下,使用较小的数组来操作较大的数组的机制。该函数接受两个参数,第一个参数是要广播的数组,第二个参数是目标形状。广播的规则是,将较小的数组在某些维度上进行复制,使得两个数组可以进行元素级别的操作。最终,较小的数组将会被复制到与较大的数组具有相同形状的位置上。 下面是一个使用broadcast_to函数的示例代码: ```python import numpy as np a = np.array([[1, 2, 3]]) b = np.broadcast_to(a, (3, 3)) print("原数组 a:") print(a) print("调用 broadcast_to 函数之后的数组 b:") print(b) ``` 运行结果如下: ``` 原数组 a: [[1 2 3]] 调用 broadcast_to 函数之后的数组 b: [[1 2 3] [1 2 3] [1 2 3]] ``` 在这个示例中,我们创建了一个形状为(1, 3)的数组a,然后使用broadcast_to函数将其广播到形状为(3, 3)的数组b。由于广播的规则,数组a在第一个维度上被复制了3次,最终得到了与数组b具有相同形状的结果。 (出处: Python numpy.broadcast_to函数方法的使用) (出处: Python numpy.expand_dims函数方法的使用) (出处: Python numpy.squeeze函数方法的使用)<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Python numpy.broadcast_to函数方法的使用](https://blog.csdn.net/a991361563/article/details/119977132)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Python-Numpy多维数组--数组操作](https://blog.csdn.net/Odyssues_lee/article/details/85252366)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值