注意:我对"只使用for for循环"这个形式的答案不感兴趣,我想以笨拙的方式做到这一点.
我是Python的初学者,我想使用numpy ndarray执行以下操作:给定一个数字t
序列和另一个数字序列b
,对于每个t[i]
我想要计算列表t[i]*b
并将其存储为最终数组中的新行.例:
t = [3,4] b = [1,2,3,4]
然后结果应该是某种形式的列表编码
[ [3,6,9,12], # 3 * the array of b's [4,8,12,16] # 4 * the array of b's ]
在我最近看到的一个程序中,这完全成功,但是当我想自己做的时候,它会引发一个错误:运行
import numpy t = numpy.linspace(3,4,2)[:, None] t = t.T # filled with some garbage numbers b = numpy.ndarray(shape=(4,1), dtype=numpy.float64, order='C') res = numpy.dot(t,b)
在python(版本3.4)给出
Traceback (most recent call last): File "C:\Daten\LiClipse_workspace\TestProject\MainPackage\PlayGround.py", line 9, inres = numpy.dot(t,b) ValueError: shapes (1,2) and (4,1) not aligned: 2 (dim 1) != 4 (dim 0)
题:
如何使这项工作?
首先,简单(并且可以说是"正确")的方式来做你想做的事:使用numpy.outer()
,而不是numpy.dot()
.
>>> import numpy >>> t = [3,4] >>> b = [1,2,3,4] >>> numpy.outer(t, b) array([[ 3, 6, 9, 12], [ 4, 8, 12, 16]])
此函数计算两个1D数组的分量乘积 - 换句话说,它将一个数组的每个元素乘以另一个数组的每个元素 - 并返回带有结果的2D数组.
考虑到Numpy显示结果的方式,您可以将其视为在矩形顶部写入第一个向量,在左侧写入第二个向量,并填充乘法表.
| 1 2 3 4 -+---------------- 3| 3 6 9 12 4| 4 8 12 16
该函数对向量实现了一个常见的数学运算,称为外积,张量积或Kronecker积.请注意,外部产品不是可交换的; 换句话说,根据您给出参数的顺序,您会得到不同的结果.将上述结果与此进行比较:
>>> numpy.outer(b, t) array([[ 3, 4], [ 6, 8], [ 9, 12], [12, 16]])
再次,您可以将此描述为在第一个参数中写入第一个参数,第二个参数在旁边,并乘以:
| 3 4 -+--------- 1| 3 4 2| 6 8 3| 9 12 4| 12 16
dot()
另一方面,Numpy的功能在应用于1D阵列时实现点积,或在应用于2D阵列时实现矩阵乘法,或在应用于更高维数组时实现矩阵乘法的通用版本,但我会忽略这种情况,因为理解它有点棘手.
对于两个1D阵列,dot()
将两个第一个元素相乘,将两个第二个元素相乘,等等,并将它们全部加起来,得到一个数字.
>>> numpy.dot([1,2,3], [4,5,6]) 32
因为1*4+2*5+3*6 == 32
.所以基本上,它迭代每个数组的索引,将相应的元素相乘,然后将它们相加.显然,两个数组必须具有相同的长度.
您可以以类似的方式将其可视化outer()
,但不是沿着边缘写入1D阵列,而是将它们垂直于边缘写入.您也应该切换订单,原因稍后会变得清晰(但它确实是一个实现选择):在左边写第一个,在顶部写第二个.一个例子将证明:
| 4 | 5 | 6 ---------+---- 1 2 3| 32
为了计算32,我将该单元格上方列中相应位置的元素与其旁边的行相乘.1*4
,, 2*5
和3*6
,然后将它们全部添加.
对于两个2D数组,dot()
迭代每个数组的一个轴,将相应的元素相乘,然后将它们相加.迭代的轴是第一个数组的最后一个,第二个数组的第一个(实际上,倒数第二个).显然,这两个轴必须具有相同的长度.
从图中可以很容易地理解这个操作,所以我会直接去那个:假设你想要计算矩阵乘积
array([[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9]])
和
array([[10, 11], [12, 13], [14, 15]])
以该顺序.再次,只需在矩形的一侧写下第一个参数,然后在顶部写下第二个参数,然后你就可以乘法和加法来填充每个单元格,就像我在1D示例中所做的那样.
| 10 11 | 12 13 | 14 15 ----------+-------- 1 2 3| 76 82 4 5 6| 184 199 7 8 9| 292 316
因为,例如,4*10+5*12+6*14 == 184
.
现在,您可能会注意到您可以使用该dot()
函数执行与函数相同的操作outer()
- 但是您的数组是2D并且具有长度为1的维度.这就是为什么您必须跳过一些箍(如[:, None]
索引)原始代码示例使其工作.它也必须是正确的维度:它必须是第一个数组的最后一个维度,以及第二个数组的倒数第二个维度.因此,在您的具体示例中,您想要计算外部产品的位置,[3,4]
并且按此[1,2,3,4]
顺序,您需要将第一个列表转换为形状数组(2,1)
,将第二个列表转换为形状数组(1,4)
.如果你这样做,当你传递它们时dot()
,它会有效地构造这个图并填充单元格:
|[[ 1, 2, 3, 4]] -----+------------------ [[3],| 3 6 9 12 [4]]| 4 8 12 16
我添加了一些括号,以帮助您将这些要求与Numpy语法联系起来.
您在问题(numpy.dot(t, b)
)中的代码示例中尝试执行的操作将与此图对应:
| [[1], | [2], | [3], | [4]] --------+------------------ [[3, 4]]| ?
当你尝试将乘法和加法过程应用于此时,它不起作用,因为你在一个数组中有两个元素而在另一个数组中有四个元素,你不能将它们配对做乘法.这是Numpy向您展示的错误的根源.
当你颠倒订单时numpy.dot(b, t)
,你得到这个图:
|[[ 3, 4]] -----+---------- [[1],| 3 4 [2],| 6 8 [3],| 9 12 [4]]| 12 16
这确实给你一个明智的结果,但要小心它是否真的是你想要的那个.这是一个形状的数组(4,2)
,而如果你以最直接的方式修复另一个过程,你会得到一个形状的结果(1,1)
,或者实际上只是一个数字.在任何给定的情况下,这些选项中只有一个(最多)可以工作.而且,您在评论中发布logistic
的屏幕截图中的功能似乎是期望从该dot()
功能中输出一个数字; 它不适用于更大的矩阵.(好吧,它可能,但它不会做你的想法.)