简体   繁体   English

numpy-矩阵乘法

[英]Numpy - Matrix multiplication

I spent about 2 hours trying to figure out what's going on, but for the life of me I can't figure out why switching the order of matrices when multiplying doesn't seem to work: 我花了大约2个小时试图弄清楚到底发生了什么,但是对于我一生来说,我无法弄清楚为什么在乘法时切换矩阵的顺序似乎不起作用:

Using Python 2.7x: 使用Python 2.7x:

import numpy as np
num_segments = 25
num_vintages = 24
# Create a 3d matrix 25 deep x 24r x 24c
mx_loans_new_loans = np.zeros((num_segments, num_vintages, num_vintages))

# Create the multiplication vector - same as the first dimension of 3d matrix
mult_vector = np.arange(10,35)
len(mult_vector)

The intent is to fill in the matrix on the diagonal with the mult_vector . 目的是用mult_vector填充对角线上的mult_vector Here is the part I can't wrap my head around. 这是我无法缠绕的部分。

This version does not fulfill the intent: 此版本不符合以下意图:

for (i, x) in enumerate(mx_loans_new_loans):
    np.fill_diagonal(x, 1)
    x = x * mult_vector[i]

The results still spit out just the original matrix with 1's on the diagonal. 结果仍然只吐出对角线为1的原始矩阵。

This version, however, does work. 但是,此版本确实有效。 All I've done is reverse the matrices in the enumerate : 我所要做的就是颠倒enumerate的矩阵:

for (i, x) in enumerate(mult_vector):
    np.fill_diagonal(mx_loans_new_loans[i], 1)
    mx_loans_new_loans[i] = mx_loans_new_loans[i] * x

Sidenote: I've since realized a more optimized version fills the intent: 旁注:从那以后,我意识到更优化的版本可以满足您的意图:

for (i, x) in enumerate(mx_loans_new_loans):
    np.fill_diagonal(x, mult_vector[i])

But does anyone know why the first version doesn't work, but the second version does? 但是有人知道为什么第一个版本不起作用,而第二个版本却起作用吗? What am I missing? 我想念什么? Is this a broadcasting problem or something simpler? 这是广播问题还是更简单的东西?

mx_loans_new_loans is 3d, (25,24,24). mx_loans_new_loans是3d(25,24,24)。 x in the loop is (24,24). 循环中的x为(24,24)。 multi_vector is (25,); multi_vector是(25,); multivector[i] a scalar. multivector[i]标量。

The fill_diagonal sets the 1s in x (in place). fill_diagonalx设置为1(在适当位置)。 But x = x * mult_vector[i] , replaces x with a new array, and doesn't change the original. 但是x = x * mult_vector[i] ,将x替换为新数组,并且不更改原始数组。 That is, it reassigns variable x . 即,它重新分配变量x

x *= mult_vector[i]

should change the diagonals in the original array. 应该更改原始数组中的对角线。

mx_loans_new_loans[i] = ... changes this subarray in place. mx_loans_new_loans[i] = ...更改此子mx_loans_new_loans[i] = ...位置。 Again mx_loans_new_loans[i] *= ... should work as well. 同样, mx_loans_new_loans[i] *= ...应该工作。

With zip we can iterate on both arrays: 使用zip我们可以在两个数组上进行迭代:

In [44]: Z=np.zeros((4,3,3),int)
In [45]: for i,j in zip(Z,np.arange(10,14)):
    ...:     np.fill_diagonal(i,j)
    ...:     
In [46]: Z
Out[46]: 
array([[[10,  0,  0],
        [ 0, 10,  0],
        [ 0,  0, 10]],

       [[11,  0,  0],
        [ 0, 11,  0],
        [ 0,  0, 11]],

       [[12,  0,  0],
        [ 0, 12,  0],
        [ 0,  0, 12]],

       [[13,  0,  0],
        [ 0, 13,  0],
        [ 0,  0, 13]]])

We can view all the diagonals as set in the loop with: 我们可以使用以下命令查看循环中设置的所有对角线:

In [47]: Z[:,np.arange(3),np.arange(3)]
Out[47]: 
array([[10, 10, 10],
       [11, 11, 11],
       [12, 12, 12],
       [13, 13, 13]])

And modify them with (not quite right): 并用(不太正确)修改它们:

In [48]: Z[:,np.arange(3),np.arange(3)]=np.arange(20,23)
In [49]: Z
Out[49]: 
array([[[20,  0,  0],
        [ 0, 21,  0],
        [ 0,  0, 22]],

       [[20,  0,  0],
        [ 0, 21,  0],
        [ 0,  0, 22]],

       [[20,  0,  0],
        [ 0, 21,  0],
        [ 0,  0, 22]],

       [[20,  0,  0],
        [ 0, 21,  0],
        [ 0,  0, 22]]])

better: 更好:

In [50]: Z[:,np.arange(3),np.arange(3)]=np.arange(20,24)[:,None]
In [51]: Z
Out[51]: 
array([[[20,  0,  0],
        [ 0, 20,  0],
        [ 0,  0, 20]],

       [[21,  0,  0],
        [ 0, 21,  0],
        [ 0,  0, 21]],

       [[22,  0,  0],
        [ 0, 22,  0],
        [ 0,  0, 22]],

       [[23,  0,  0],
        [ 0, 23,  0],
        [ 0,  0, 23]]])

Another example of how assignment changes arrays (or not): 分配如何更改(或不更改)数组的另一个示例:

In [97]: x = np.zeros((2,3),int)

y is a view , a way of looking at one row of x : y是一个view ,是view x一行的一种方式:

In [99]: y = x[0]
In [100]: id(y)
Out[100]: 2877147400

In-place change to y appears as a change to x : y的就地更改显示为x的更改:

In [101]: y += 3
In [102]: y
Out[102]: array([3, 3, 3])
In [103]: x
Out[103]: 
array([[3, 3, 3],
       [0, 0, 0]])

But a y= change to y breaks the connection. 但是将y=更改为y会断开连接。 y is no longer a view (row) of x , but rather a whole new array. y不再是x的视图(行),而是一个全新的数组。

In [104]: y = y + 3
In [105]: y
Out[105]: array([6, 6, 6])
In [106]: x
Out[106]: 
array([[3, 3, 3],
       [0, 0, 0]])
In [107]: id(y)
Out[107]: 2876795264

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM