通过分配项相乘Numpy数组
我有两个一维的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 个回答
你可以利用广播功能。这是一个非常强大的概念,一旦我理解了它,就为我打开了很多大门。这个想法是,当你用两个数组进行简单的操作(比如加、减、乘、除等)时,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()
我想知道你为什么认为 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]])
使用 numpy.outer 和 numpy.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])