我有一个使用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返回的稀疏矩阵中每行的数值。获得常规将是最好的。非常感谢任何帮助。
答案 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