更改 scipy 稀疏矩阵的对角线或数据属性也会更改该矩阵的所有副本
Changing diagonal or data attribute of a scipy sparse matrix also changes all copies of that matrix
我在一个 variable
中有一个 scipy 稀疏矩阵,我将其复制到另一个新的 variable
。如果我现在更改新 variable
中稀疏矩阵的对角线,则原始 variable
中的稀疏矩阵也会更新。如果我更改数据 attribute
,也会发生同样的情况。我不明白为什么会这样,这种行为是否有我看不到的目的,或者我是否以无意的方式做某事?
我想要的是我从一个稀疏矩阵开始,复制它的几个副本,并以足够的方式修改对角线或所有条目以用于这些副本。但是我的修改影响了所有副本。
我发现如果我使用创建稀疏矩阵副本的方法,如 power()
或使用 @ 进行矩阵乘法,则不会出现该问题。
我想要的一个修改是稀疏矩阵的副本,我在其中取所有条目的绝对值。如果我直接在稀疏矩阵上使用 abs()
,它会根据需要创建一个副本,一切都很好。但是,如果我将所有条目的绝对值写入稀疏矩阵的数据 attribute
中,它也会影响稀疏矩阵的所有其他副本。我发现后一种方法要快得多,这就是我更愿意使用它的原因。
问题与稀疏矩阵格式无关(除了 lil 或 dok 格式的数据属性)。
我在 Spyder 3.3.1 中使用 Python 3.5.2
和 Python 3.7.3
(两台不同的计算机)进行了尝试,我使用的是 scipy 版本 1.3.0。
假设我有一个稀疏矩阵
from scipy.sparse import csc_matrix as spmat
Msp = spmat(ar([[0.,-3.],[2.,-4.]]))
然后我复制了一些(我也可以随时复制 Msp,这没什么区别)
M1 = Msp
M2 = M1
如果我现在做
M2.data = abs(M2.data)
或
M1.setdiag([1,1])
它还会更改所有其他副本,例如应用以上两个操作后:
Msp.toarray()
array([[1., 3.],
[2., 1.]])
M1 和 M2 也一样
我早有预料
M2.toarray()
array([[ 0., 3.],
[ 2., 4.]])
和
M1.toarray()
array([[1., -3.],
[2., 1.]])
和
Msp.toarray()
array([[ 0., -3.],
[ 2., -4.]])
另一方面,如果我执行以下类型的操作
M2 = abs(M2)
M2 = M2.power(2)
M2 = M2@M2
它只影响 M2,而没有影响 M1 和 Msp,正如我所期望的那样。
通过更改以下行:
M1 = Msp
M2 = M1
至:
M1 = Msp.copy()
M2 = M1.copy()
您给出的示例将按预期工作。
Numpy 数组是可变的,因此对对象的更改将影响引用该对象的所有变量。
换句话说:
通过设置 M2 = M1
,M2 只是对 M1 的引用,因此如果 M1 发生变化,它也将采用 M1 的值。另一方面,M2 = M1.copy()
将 M1('values')的副本传递给 M2,此后独立于 M1 的更改。
最后给出的示例只影响 M2 的原因是许多 numpy 函数 return 独立于作为参数传递的数组的新数组。
我在一个 variable
中有一个 scipy 稀疏矩阵,我将其复制到另一个新的 variable
。如果我现在更改新 variable
中稀疏矩阵的对角线,则原始 variable
中的稀疏矩阵也会更新。如果我更改数据 attribute
,也会发生同样的情况。我不明白为什么会这样,这种行为是否有我看不到的目的,或者我是否以无意的方式做某事?
我想要的是我从一个稀疏矩阵开始,复制它的几个副本,并以足够的方式修改对角线或所有条目以用于这些副本。但是我的修改影响了所有副本。
我发现如果我使用创建稀疏矩阵副本的方法,如 power()
或使用 @ 进行矩阵乘法,则不会出现该问题。
我想要的一个修改是稀疏矩阵的副本,我在其中取所有条目的绝对值。如果我直接在稀疏矩阵上使用 abs()
,它会根据需要创建一个副本,一切都很好。但是,如果我将所有条目的绝对值写入稀疏矩阵的数据 attribute
中,它也会影响稀疏矩阵的所有其他副本。我发现后一种方法要快得多,这就是我更愿意使用它的原因。
问题与稀疏矩阵格式无关(除了 lil 或 dok 格式的数据属性)。
我在 Spyder 3.3.1 中使用 Python 3.5.2
和 Python 3.7.3
(两台不同的计算机)进行了尝试,我使用的是 scipy 版本 1.3.0。
假设我有一个稀疏矩阵
from scipy.sparse import csc_matrix as spmat
Msp = spmat(ar([[0.,-3.],[2.,-4.]]))
然后我复制了一些(我也可以随时复制 Msp,这没什么区别)
M1 = Msp
M2 = M1
如果我现在做
M2.data = abs(M2.data)
或
M1.setdiag([1,1])
它还会更改所有其他副本,例如应用以上两个操作后:
Msp.toarray()
array([[1., 3.],
[2., 1.]])
M1 和 M2 也一样
我早有预料
M2.toarray()
array([[ 0., 3.],
[ 2., 4.]])
和
M1.toarray()
array([[1., -3.],
[2., 1.]])
和
Msp.toarray()
array([[ 0., -3.],
[ 2., -4.]])
另一方面,如果我执行以下类型的操作
M2 = abs(M2)
M2 = M2.power(2)
M2 = M2@M2
它只影响 M2,而没有影响 M1 和 Msp,正如我所期望的那样。
通过更改以下行:
M1 = Msp
M2 = M1
至:
M1 = Msp.copy()
M2 = M1.copy()
您给出的示例将按预期工作。
Numpy 数组是可变的,因此对对象的更改将影响引用该对象的所有变量。
换句话说:
通过设置 M2 = M1
,M2 只是对 M1 的引用,因此如果 M1 发生变化,它也将采用 M1 的值。另一方面,M2 = M1.copy()
将 M1('values')的副本传递给 M2,此后独立于 M1 的更改。
最后给出的示例只影响 M2 的原因是许多 numpy 函数 return 独立于作为参数传递的数组的新数组。