1

我有一个简单的问题,我希望已经在网上找到了一个简单的答案,但我没有。

由于矩阵运算,我有一个 python 项目可以与 numpy 一起使用。我想加快代码速度,所以我做了一些分析以找出适合这项工作的工具。原来开销不是python,而是矩阵运算。因此我认为我应该使用 Theano(特别是考虑到我正在实现机器学习算法的情况,这就是为之而生的)。

我项目的大部分开销都在一个函数中,我想知道是否有可能只用 theano 重写该函数,然后从中取出 numpy 数组并像往常一样继续计算。

这再次只是为了测试在不承诺更改大量代码的情况下我将获得多少速度。

谢谢!

编辑:万一是这个功能

def backprop(weights, layerValues, finalLayerErrors, activationFunctions):
  nrLayers = len(weights) + 1
  deDw = []
  deDbias = []
  upperLayerErrors = finalLayerErrors

  for layer in xrange(nrLayers - 1, 0, -1):
    deDz = activationFunctions[layer - 1].derivativeForLinearSum(
                        upperLayerErrors, layerValues[layer])
    upperLayerErrors = np.dot(deDz, weights[layer - 1].T)

    dw = np.einsum('ij,ik->jk', layerValues[layer - 1], deDz)

    dbias = deDz.sum(axis=0)

    # Iterating in decreasing order of layers, so we are required to
    # append the weight derivatives at the front as we go along
    deDw.insert(0, dw)
    deDbias.insert(0, dbias)

return deDw, deDbias
4

2 回答 2

5

您无需更改所有脚本即可使用 Theano。你可以用 Theano 重新实现你的部分代码,它会工作的。Theano 默认将 numpy ndarray 作为输入并返回 numpy ndarray 作为输出。所以使用 numpy 很容易集成。

Theano 没有实现 einsum。因此,我建议您首先将其替换为帕特里克所说的对 dot 的调用。我多次看到和听到 einsum 在某些情况下比调用 dot 慢。如果速度不够好,Theano 可以帮助您。如果您只是将点调用移动到 Theano,如果 Theano 和 NumPy 链接到同一个 BLAS 库,Theano 将不会更快。但是如果你将更多的计算转移到 Theano 上,它应该会让你的编码速度更快。但这并不完美,与 NumPy 相比,某些情况下没有加速,极少数情况下会减速(主要是当输入形状不够大时,如标量)

关于 Patrick 的回答,您无需使用 Theano 的符号渐变即可从 Theano 中受益。但是如果要使用符号梯度,Theano 只能在 Theano 中完成的计算图中计算符号梯度。因此,您需要将该部分完全转换为 Theano。但是由于您的代码已经可以工作,这意味着您已经手动实现了 grad。这很好,不会引起任何问题。您可以将 grad 的手动实现移动到 Theano,而无需使用符号渐变。

关于帕特里克对 GPU 的评论。不要忘记,数据的传输 CPU/GPU 是 GPU 上成本最高的操作。它可以在很多情况下完全取消 GPU 加速。因此,不确定只在 GPU 上做点会有所帮助。在 Theano 中,我们将重量放在 GPU 上,如果不这样做,我认为您无法从 GPU 上获得加速(这曾经是 gnumpy/Theano/其他东西)。仅在 GPU 上执行 DOT 仍会加快速度的情况是使用巨大的矩阵。

于 2014-01-24T02:24:03.667 回答
-2

如果你有在 Numpy 中运行的代码,将它翻译成 Theano 并不会让它变得神奇地更快,而且它会花费大量的编码工作。

Theano 非常好,但选择它更多的是设计时的决定——你想要拥有符号微分的所有细节,这样你就不必为反向传播手动计算梯度,所以你使用那个框架。

如果您已经准备好 Numpy 代码,只需优化瓶颈,在您的情况下必须是那个点积。我会尝试使用点函数代替 einsum,即代替:

dw = np.einsum('ij,ik->jk', layerValues[layer - 1], deDz)

尝试:

dw = layerValues[layer-1].T.dot(deDz)

有时 einsum 是愚蠢的,所以可能会更快。如果没有,请考虑

  1. 使用 GPU 进行矩阵向量乘法,通过 gnumpy
  2. 使用比普通的旧梯度下降收敛更快的更好的算法(我假设这是你正在使用的):adagrad 或二阶优化算法 - lbfgs,比如说 -
于 2014-01-23T22:08:51.633 回答