Numpy - 矩阵乘法

时间:2017-09-29 01:50:53

标签: python numpy matrix

我花了大约2个小时试图弄清楚发生了什么,但对于我的生活,我无法弄清楚为什么在乘法似乎不起作用时改变矩阵的顺序:

使用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)

目的是用mult_vector填充对角线上的矩阵。 这是我无法绕过的部分。

此版本不符合意图:

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

结果仍然只是在对角线上的1' s原始矩阵吐出。

然而,这个版本确实有效。我所做的就是颠倒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

旁注: 我已经意识到更优化的版本填补了意图:

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

但有谁知道为什么第一个版本不起作用,但第二个版本呢?我错过了什么?这是广播问题还是更简单?

1 个答案:

答案 0 :(得分:2)

mx_loans_new_loans是3d,(25,24,24)。循环中的x是(24,24)。 multi_vector是(25,); multivector[i]标量。

fill_diagonal设置x中的1(就地)。但x = x * mult_vector[i]用新数组替换x,并且不会更改原始数据。也就是说,它会重新分配变量x

x *= mult_vector[i]

应该更改原始数组中的对角线。

mx_loans_new_loans[i] = ...更改此子阵列。同样mx_loans_new_loans[i] *= ...应该也可以。

使用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]]])

我们可以通过以下方式查看循环中设置的所有对角线:

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

用(不太正确)修改它们:

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]]])

更好:

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]]])

赋值如何更改数组(或不更改)的另一个示例:

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

yview,是查看x行的一种方式:

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

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]])

y=更改为y会破坏连接。 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