Python 手动设置scipy稀疏矩阵形状的含义

Python 手动设置scipy稀疏矩阵形状的含义,python,numpy,scipy,sparse-matrix,reshape,Python,Numpy,Scipy,Sparse Matrix,Reshape,我需要在TF-IDF模型上进行在线培训。我发现那个西皮的 TfidfVectorizer不支持在线时尚培训,因此我正在实现自己的CountVectorizer来支持在线培训,然后在语料库中输入预定义数量的文档后,使用scipy的TfidfTransformer来更新tf idf值 我发现您不应该向numpy数组添加行或列,因为需要复制所有数据,以便将其存储在连续的内存块中 但后来我还发现,事实上,使用scipy稀疏矩阵可以 努比说: 在不复制数据的情况下,不可能总是更改数组的形状。如果希望在复制

我需要在TF-IDF模型上进行在线培训。我发现那个西皮的
TfidfVectorizer
不支持在线时尚培训,因此我正在实现自己的
CountVectorizer
来支持在线培训,然后在语料库中输入预定义数量的文档后,使用scipy的
TfidfTransformer
来更新tf idf值

我发现您不应该向numpy数组添加行或列,因为需要复制所有数据,以便将其存储在连续的内存块中

但后来我还发现,事实上,使用scipy稀疏矩阵可以

努比说:

在不复制数据的情况下,不可能总是更改数组的形状。如果希望在复制数据时引发错误,则应将新形状指定给数组的形状属性

由于稀疏矩阵的“重塑”是通过指定一个新形状来完成的,所以可以安全地说数据没有被复制吗?这样做意味着什么?效率高吗

代码示例:

matrix = sparse.random(5, 5, .2, 'csr') # Create (5,5) sparse matrix
matrix._shape = (6, 6) # Change shape to (6, 6)
# Modify data on new empty row
我还想扩展我的问题,询问一些方法,例如
vstack
,这些方法允许一个人(与添加一行相同)。
vstack
是否正在复制整个数据,以便将其存储为我在第一个链接中所述的连续内存块?那么
hstack


编辑: 所以,下面我实现了一个方法来改变稀疏矩阵中一行的值

现在,将添加新空行的想法与修改现有值的想法混合在一起,我得出以下结论:

matrix = sparse.random(5, 3, .2, 'csr')
matrix._shape = (6, 3)
# Update indptr to let it know we added a row with nothing in it.
matrix.indptr = np.hstack((matrix.indptr, matrix.indptr[-1]))

# New elements on data, indices format
new_elements = [1, 1]
elements_indices = [0, 2] 

# Set elements for new empty row
set_row_csr_unbounded(matrix, 5, new_elements, elements_indices)
在同一执行过程中,我运行了上述代码几次,没有出现错误。但是,只要我尝试添加一个新列(那么就不需要更改
indptr
),当我尝试更改值时,就会出现一个错误。关于为什么会发生这种情况有线索吗

既然
set\u row\u csr\u unbounded
在下面使用
numpy.r\ucode>,我想我最好使用
lil\u矩阵。即使所有元素一旦添加也无法修改。我说得对吗


我认为
lil\u matrix
将是ebtter,因为我假设
numpy.r\u
正在复制数据

numpy
中,重塑
意味着以保持相同数字元素的方式更改
形状。所以形状项的乘积不能改变

最简单的例子是

np.arange(12).reshape(3,4)
x = np.arange(12).reshape(3,4).T
x.reshape(3,4)   # ok, but copy
x.shape = (3,4)  # raises error
分配方法为:

x = np.arange(12)
x.shape = (3,4)
方法
(或
np.reformate(…)
)返回一个新数组。
形状
分配在适当的位置工作

文档中指出,在执行以下操作时,您引用的内容起作用

np.arange(12).reshape(3,4)
x = np.arange(12).reshape(3,4).T
x.reshape(3,4)   # ok, but copy
x.shape = (3,4)  # raises error
为了更好地理解这里发生了什么,请在不同阶段打印数组,并查看原始
0,1,2,…
连续性是如何变化的。(这是留给读者的练习,因为它不是更大问题的核心。)

有一个
resize
函数和方法,但使用不多,它在视图和副本方面的行为也很棘手

np.concatenate
(以及类似
np.stack
np.vstack
)的变体)创建新数组,并从输入复制所有数据

列表(和对象数据类型数组)包含指向元素(可能是数组)的指针,因此不需要复制数据

稀疏矩阵以不同格式的各种属性存储其数据(以及行/列索引)
coo
csr
csc
有3个1d阵列
lil
有两个包含列表的对象数组
dok
是一个字典子类

lil_矩阵
实现了一种
重塑
方法。其他格式则不然。与
np一样,重塑
尺寸的乘积不能改变

理论上,稀疏矩阵可以“嵌入”到一个更大的矩阵中,只需最少的数据复制,因为所有新值都是默认的0,并且不占用任何空间。但对于任何一种格式,该操作的细节都尚未确定

sparse.hstack
sparse.vstack
(不要在稀疏矩阵上使用
numpy
版本)通过组合输入的
coo
属性来工作(通过
sparse.bmat
)。因此,是的,他们制作了新的数组(
数据

制作更大稀疏矩阵的一个最小示例:

In [110]: M = sparse.random(5,5,.2,'coo')
In [111]: M
Out[111]: 
<5x5 sparse matrix of type '<class 'numpy.float64'>'
    with 5 stored elements in COOrdinate format>
In [112]: M.A
Out[112]: 
array([[0.        , 0.80957797, 0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.        , 0.        , 0.        ],
       [0.        , 0.23618044, 0.        , 0.91625967, 0.8791744 ],
       [0.        , 0.        , 0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.        , 0.7928235 , 0.        ]])
In [113]: M1 = sparse.coo_matrix((M.data, (M.row, M.col)),shape=(7,5))
In [114]: M1
Out[114]: 
<7x5 sparse matrix of type '<class 'numpy.float64'>'
    with 5 stored elements in COOrdinate format>
In [115]: M1.A
Out[115]: 
array([[0.        , 0.80957797, 0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.        , 0.        , 0.        ],
       [0.        , 0.23618044, 0.        , 0.91625967, 0.8791744 ],
       [0.        , 0.        , 0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.        , 0.7928235 , 0.        ],
       [0.        , 0.        , 0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.        , 0.        , 0.        ]])
In [116]: id(M1.data)
Out[116]: 139883362735488
In [117]: id(M.data)
Out[117]: 139883362735488
您的新形状方法(确保
indptr
dtype
不变):

数据
属性为共享,至少在视图意义上:

In [113]: M[0,1]=14
In [114]: M1[0,1]
Out[114]: 14
但是如果我通过添加一个非零值来修改
M1

In [117]: M1[5,0]=10
...
  SparseEfficiencyWarning)
矩阵之间的链接中断:

In [120]: M[0,1]=3
In [121]: M1[0,1]
Out[121]: 14

谢谢你的回答,我有一个问题,假设我创建一个
csr\u矩阵
,例如,使用shape
(3,5)
,然后我创建
矩阵。_shape=(3,6)
,因为所有新元素都是0,它不会占用任何额外的空间,但只要我为另一个值修改这些0,它就会占用更多的空间,对吗?如果是这样的话,它会在这样做时复制所有数据吗?你会得到一个效率警告,问题是,它不会,我已经按照图中所示进行了尝试,但没有得到警告更改私有属性
\u shape
不会给出警告,但添加新值会给出警告。当你开始直接修改矩阵属性时,你需要了解它们。许多SO答案建议直接使用
indptr
对行进行快速迭代,但这是用于不改变稀疏性的计算。当您开始直接更改稀疏度(添加或删除非零值)时,您正在冒险。我自己没有尝试过这样做,尽管我可能可以调试代码。
In [117]: M1[5,0]=10
...
  SparseEfficiencyWarning)
In [120]: M[0,1]=3
In [121]: M1[0,1]
Out[121]: 14