得到numpy稀疏矩阵行的规范

时间:2013-11-23 22:47:42

标签: python arrays numpy matrix norm

我有一个使用Sklearn的TfidfVectorizer对象获得的稀疏矩阵:

vect = TfidfVectorizer(sublinear_tf=True, max_df=0.5, analyzer='word', vocabulary=my_vocab, stop_words='english')
tfidf = vect.fit_transform([my_docs])

稀疏矩阵是(取出一般性的数字):

<sparse matrix of type '<type 'numpy.float64'>'
with stored elements in Compressed Sparse Row format>]

我正在尝试为每一行获取一个数值,告诉我文档有多高我所要求的术语。我真的不在乎它包含哪些词,我只是想知道它包含了多少。所以我想得到每个或行* row.T的标准。但是,我很难与numpy一起工作来获得这个。

我的第一个方法就是简单地做:

tfidf[i] * numpy.transpose(tfidf[i])

但是,numpy显然不会转置少于一维的数组,因此只会对向量求平方。所以我试着这样做:

tfidf[i] * numpy.transpose(numpy.atleast_2d(tfidf[0]))

但是numpy.transpose(numpy.atleast_2d(tfidf [0]))仍然不会转置该行。

我继续尝试获得行的规范(无论如何,这种方法可能更好)。我最初的方法是使用numpy.linalg。

numpy.linalg.norm(tfidf[0])

但这给了我一个“尺寸不匹配”的错误。所以我试着手动计算规范。我开始只是设置一个等于稀疏矩阵的numpy数组版本的变量并打印出第一行的len:

my_array = numpy.array(tfidf)
print my_array
print len(my_array[0])

它正确打印出my_array,但是当我尝试访问len时它会告诉我:

IndexError: 0-d arrays can't be indexed

我只是想获得fit_transform返回的稀疏矩阵中每行的数值。获得常规将是最好的。非常感谢任何帮助。

3 个答案:

答案 0 :(得分:7)

一些简单的假数据:

a = np.arange(9.).reshape(3,3)
s = sparse.csr_matrix(a)

要从稀疏中获取每一行的范数,您可以使用:

np.sqrt(s.multiply(s).sum(1))

重整化s将是

s.multiply(1/np.sqrt(s.multiply(s).sum(1)))

或在重新规范化之前保持稀疏:

s.multiply(sparse.csr_matrix(1/np.sqrt(s.multiply(s).sum(1))))

要从中获取普通矩阵或数组,请使用:

m = s.todense()
a = s.toarray()

如果你有足够的内存用于密集版本,你可以通过以下方式获得每行的标准:

n = np.sqrt(np.einsum('ij,ij->i',a,a))

n = np.apply_along_axis(np.linalg.norm, 1, a)

要标准化,您可以

an = a / n[:, None]

或者,为了规范化原始数组:

a /= n[:, None]

[:, None]基本上将n转换为垂直数组。

答案 1 :(得分:6)

scipy.sparse是一个很棒的软件包,每次发布都会越来越好,但很多东西仍然只有一半,如果你自己实现一些算法,你可以获得很大的性能提升。例如,使用scipy函数比@ askewchan的实现提高了7倍:

In [18]: a = sps.rand(1000, 1000, format='csr')

In [19]: a
Out[19]: 
<1000x1000 sparse matrix of type '<type 'numpy.float64'>'
    with 10000 stored elements in Compressed Sparse Row format>

In [20]: %timeit a.multiply(a).sum(1)
1000 loops, best of 3: 288 us per loop

In [21]: %timeit np.add.reduceat(a.data * a.data, a.indptr[:-1])
10000 loops, best of 3: 36.8 us per loop

In [24]: np.allclose(a.multiply(a).sum(1).ravel(),
    ...:             np.add.reduceat(a.data * a.data, a.indptr[:-1]))
Out[24]: True

您可以类似地对阵列进行规范化,执行以下操作:

norm_rows = np.sqrt(np.add.reduceat(a.data * a.data, a.indptr[:-1]))
nnz_per_row = np.diff(a.indptr)
a.data /= np.repeat(norm_rows, nnz_per_row)

如果您打算经常使用稀疏矩阵,请阅读the wikipedia page on compressed sparse formats,您会发现比默认值更好的方法。

答案 2 :(得分:0)

如何使用本地scipy API scipy.sparse.linalg.norm

更多信息,请访问https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.linalg.norm.html