【问题标题】:Hstacking features somehow causes an extra slowdown in predictionHstacking 特征以某种方式导致预测的额外减慢
【发布时间】:2013-11-20 19:26:01
【问题描述】:

当我使用 CountVectorizer 等生成的一些稀疏矩阵的scipy.sparse.hstack 时,我想将它们合并以用于回归,但不知何故它们速度较慢:

  • X1 有 10000 个来自 analyse="char" 的特征
  • X2 有 10000 个来自 analyse="word" 的特征
  • X3 有 20000 个来自 analyse="char" 的特征
  • X4 有 20000 个来自 analyse="word" 的特征

您会期望当您对 X1 和 X2 进行 hstack 时,它的速度与 X3 或 X4 大致相同(功能数量相同)。但这似乎还没有接近:

from scipy.sparse import hstack
>>> a=linear_model.Ridge(alpha=30).fit(hstack((X1, X2)),y).predict(hstack((t1,t2)))
time:  57.85
>>> b=linear_model.Ridge(alpha=30).fit(X1,y).predict(t1)
time:  6.75
>>> c=linear_model.Ridge(alpha=30).fit(X2,y).predict(t2)
time:  7.33
>>> d=linear_model.Ridge(alpha=30).fit(X3,y).predict(t3)
time:  6.80
>>> e=linear_model.Ridge(alpha=30).fit(X4,y).predict(t4)
time:  11.67

我什至注意到,当我 hstack 只有一个功能时,模型也会变慢。什么可能导致这种情况,我做错了什么,当然还有什么可以改进的?

值得注意的编辑:

我想介绍一种我认为可以解决它的方法,即构建一个词汇表并使用它来适应:

feats = []
method = CountVectorizer(analyzer="word", max_features=10000, ngram_range=(1,3))
method.fit(train["tweet"])
X = method.fit(...)
feats.extend(method.vocabulary_.keys())
method = CountVectorizer(analyzer="char", max_features=10000, ngram_range=(4,4))
method.fit(train["tweet"])
X2 = method.fit(...)
feats.extend(method.vocabulary_.keys())
newm = CountVectorizer(vocabulary=feats)
newm.fit(train["tweet"])
X3 = newm.fit(...)

当我适合这些时,存储的项目数量会发生一些奇怪的事情(我对没有 20,000 个特征并不感到惊讶,因为可能会有重叠)。怎么会有这么少的“一”?

X
<49884x10000 sparse matrix of type '<class 'numpy.int64'>'
    with 927131 stored elements in Compressed Sparse Row format>
X2
<49884x10000 sparse matrix of type '<class 'numpy.int64'>'
    with 3256162 stored elements in Compressed Sparse Row format>
X3
<49884x19558 sparse matrix of type '<class 'numpy.int64'>'
    with 593712 stored elements in Compressed Sparse Row format>

【问题讨论】:

  • 它们是什么类型的稀疏矩阵? (例如 CSR、CRC、BSR、COO 等)操作的性能将在很大程度上取决于您使用的稀疏结构的类型。有这么多不同的类型是有充分理由的。每个人都有优点和缺点。
  • 企业社会责任。我假设只有 CSR 和 CRC 存在......
  • 但是,当 CSR 被 hstacked 时,这里确实出现了其他变化?

标签: python scipy scikit-learn python-3.3


【解决方案1】:

Hstacking 将其转换为 COO 格式:

>>> hstack((csr_matrix([1]), csr_matrix([2])))
<1x2 sparse matrix of type '<type 'numpy.int64'>'
    with 2 stored elements in COOrdinate format>

也许做hstack(...).tocsr() 来检查它是否加快了速度。

【讨论】:

  • 既然你是 scipy 开发团队的一员,你知道为什么这种堆叠方案用于稀疏矩阵吗?通过连接内部描述数组,hstacking CSC 矩阵或 vstacking CSR 矩阵可以比 scipy 更快地完成。
  • 在最新型号上:没有 tocsr() = 77.83 秒,附加 .tocsr() 需要 59.12 秒,所以这肯定是一个改进。
  • 模型分别运行 33 秒和 6 秒,所以我希望我还缺少其他东西。
  • @Jaime:为什么会这样,是因为原作者是这样写的。原作者已经很多年没有在 Scipy 项目中活跃了,所以我不能说它在 is is 的原因。如果您想改善行为,欢迎使用补丁。
【解决方案2】:

您可以轻而易举地hstack 两个 CSC 矩阵,保持输出 CSC:

In [1]: import scipy.sparse as sps

In [2]: a = sps.csc_matrix(np.arange(25).reshape(5, 5))

In [3]: b = sps.csc_matrix(np.arange(25).reshape(5, 5))

In [4]: data = np.concatenate((a.data, b.data))

In [5]: indices = np.concatenate((a.indices, b.indices))

In [7]: indptr = np.concatenate((a.indptr[:-1], b.indptr + a.indptr[-1]))


In [10]: c = sps.csc_matrix((data, indices, indptr),
...                         shape = (a.shape[0], a.shape[1]+b.shape[1]))

In [11]: c.A
Out[11]: 
array([[ 0,  1,  2,  3,  4,  0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19, 15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24, 20, 21, 22, 23, 24]])

完全相同的代码,将csc 替换为csr,将vstack 两个CSR 矩阵。

您需要进行一些计时,但在大多数情况下,我认为将您的矩阵转换为 CSR 或 CSC 会更快,具体取决于您要进行的堆叠,按上述方式进行堆叠,然后将结果转换为随心所欲,而不是使用内置的堆叠功能。

【讨论】:

  • 将纯 CSR 或纯 CSC 操作的快速路径添加到 scipy.sparse.bmat 可能相当容易。在不久的将来我不一定有时间自己处理这个问题,所以如果其他人想解决它,go ahead
  • @pv。如果我的孩子们给我一些周末时间,我一定会亲自调查一下。感谢你们为此付出的伟大工作!
  • 如果您有时间,非常感谢!仅仅看代码并不容易找到这种加速,但需要一些实际使用。
  • @pv。我添加了快速路径,但没有添加到bmatgithub.com/scipy/scipy/pull/3057(抱歉偷了你的风头,@Jaime)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多