通过分配项相乘Numpy数组

1 投票
3 回答
660 浏览
提问于 2025-04-18 01:35

我有两个一维的numpy数组,分别保存在文件里。

第一个数组叫'test1',里面有两个数字,内容是(2,3)。

第二个数组叫'test2',里面有三个数字,内容是(5,6,7)。

我想把这两个数组相乘,得到的结果是

t=(10, 12, 14, 15, 18, 21)

我正在使用这个程序

import numpy as np

a=open('test1')
b=open('test2')
c=open('test3','w+')
t1=np.loadtxt(a)
t2=np.loadtxt(b)
t=t1*t2

print >> c, t

但是当我运行这个程序时,出现了一个错误..

ValueError: 操作数的形状不匹配,无法一起进行广播,形状分别是(2)和(3)

我该怎么做才能得到想要的结果呢?

3 个回答

1

你可以利用广播功能。这是一个非常强大的概念,一旦我理解了它,就为我打开了很多大门。这个想法是,当你用两个数组进行简单的操作(比如加、减、乘、除等)时,numpy会逐个元素地进行计算。这意味着这两个数组必须有相同的形状(每个维度的元素数量要一样)。比如,A的形状是(3,4),B的形状也是(3,4),那么你可以做A*B,这样会得到一个新的数组,形状也是(3,4),其中每个元素都是A和B在相同位置的元素相乘的结果。

a = ones((3,4))*2
b = ones((3,4))*3
c = a*b
print c.shape
> (3,4)

根据这个规则,有一个聪明的例外:当一个数组在某个维度上只有一个元素时,这个维度会被广播。这意味着这个维度会沿着这个轴“扩展”,复制出足够多的相同元素,以便与另一个数组兼容。

a = ones((3,4))*2
b = ones((1,4))*3
c = a*b
print c.shape
> (3,4)

好吧,对于你的问题,你可以通过在数组中添加一个维度来使用这个功能:比如你有a.shape = (2,),你想变成(2,1);而b.shape = (3,),你想变成(1,3)。这样在对它们进行操作时,就会进行广播,每个a中的元素都会和b中的每个元素相乘。你可以通过在数组中添加np.newaxis来实现这一点。

a = np.array((2,3))[:,np.newaxis]
b = np.array((5,6,7))[np.newaxis,:]
print a.shape 
> (2,1)
print b.shape
> (1,3)
c = a*b
> (2,3)

现在你会得到一个形状为(2,3)的数组,但你想要的是一个一维数组,所以你可以使用flatten()来实现。

a = np.array((2,3))[:,np.newaxis]
b = np.array((5,6,7))[np.newaxis,:]
c = (a[:,np.newaxis]*b[np.newaxis,:]).flatten()
1

我想知道你为什么认为 t1*t2 会得到你想要的结果?

如果我写了:

[x,y,z]*[a,b]

你觉得答案是什么?为什么?

有一些可能的情况:

[x*a, y*b, z*??]
[x*???, y*a, z*b]
[[x*a, y*a, z*a],[x*b,y*b,z*b]]
[[x*a, x*b],[y*a, y*b],[z*a,z*b]]
[x*a, y*a, z*a, x*b, y*b, z*b]
etc

将两个数字列表混合搭配的多种方式。简单来说,numpy 会逐个元素进行匹配,但因为有一个 z 没有匹配上,所以它不知道该怎么处理这个不匹配的元素,结果就报错了。

这里还有另一种方法可以得到“扁平”的外积:

(t1.reshape(2,1)*t2).reshape(6)

在 Python 的命令行中,试着分开运行这个(和其他建议),这样可以更好地理解发生了什么。

在最后的 reshape 之前,这会产生一个二维矩阵。这是理解你想如何组合这两个向量的关键。

array([[10, 12, 14],
       [15, 18, 21]])
4

使用 numpy.outernumpy.ravel

>>> import numpy as np
>>> a = np.array((2,3))
>>> b = np.array((5,6,7))
>>> np.outer(a,b).ravel()
array([10, 12, 14, 15, 18, 21])

补充:

减法:我们不能使用 numpy.outer,但可以使用 numpy.newaxis

>>> (a[:, np.newaxis] - b).ravel()
array([-3, -4, -5, -2, -3, -4])

撰写回答