gpt4 book ai didi

algorithm - 在 Theano 中循环(或向量化)可变长度矩阵

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:45:30 24 4
gpt4 key购买 nike

我有一个矩阵列表 L,其中每个项目 M 都是一个 x*n 矩阵(x 是一个变量,n 是一个常量)。

我想为 L 中的所有项目计算 M'*M 的总和(M' 的转置M) 就像下面的 Python 代码一样:

for M in L:
res += np.dot(M.T, M)

实际上我想在 Theano 中实现这个(它不支持可变长度的多维数组),我不想将所有矩阵填充到相同的大小,因为那样会浪费太多空间(有些矩阵可以非常大)。

有更好的方法吗?

编辑:

L 在 Theano 编译之前是已知的。

编辑:

收到来自@DanielRenshaw 和@Divakar 的两个优秀答案,情绪上很难选择一个接受。

最佳答案

鉴于矩阵的数量在需要进行 Theano 编译之前是已知的,因此可以简单地使用 Theano 矩阵的常规 Python 列表。

这是一个完整的示例,显示了 numpy 和 Theano 版本之间的区别。

此代码已更新,包括与@Divakar 的向量化方法的比较,后者性能更好。 Theano 有两种向量化方法,一种是 Theano 执行串联,另一种是 numpy 执行串联,然后将结果传递给 Theano。

import timeit
import numpy as np
import theano
import theano.tensor as tt


def compile_theano_version1(number_of_matrices, n, dtype):
assert number_of_matrices > 0
assert n > 0
L = [tt.matrix() for _ in xrange(number_of_matrices)]
res = tt.zeros(n, dtype=dtype)
for M in L:
res += tt.dot(M.T, M)
return theano.function(L, res)


def compile_theano_version2(number_of_matrices):
assert number_of_matrices > 0
L = [tt.matrix() for _ in xrange(number_of_matrices)]
concatenated_L = tt.concatenate(L, axis=0)
res = tt.dot(concatenated_L.T, concatenated_L)
return theano.function(L, res)


def compile_theano_version3():
concatenated_L = tt.matrix()
res = tt.dot(concatenated_L.T, concatenated_L)
return theano.function([concatenated_L], res)


def numpy_version1(*L):
assert len(L) > 0
n = L[0].shape[1]
res = np.zeros((n, n), dtype=L[0].dtype)
for M in L:
res += np.dot(M.T, M)
return res


def numpy_version2(*L):
concatenated_L = np.concatenate(L, axis=0)
return np.dot(concatenated_L.T, concatenated_L)


def main():
iteration_count = 100
number_of_matrices = 20
n = 300
min_x = 400
dtype = 'float64'
theano_version1 = compile_theano_version1(number_of_matrices, n, dtype)
theano_version2 = compile_theano_version2(number_of_matrices)
theano_version3 = compile_theano_version3()
L = [np.random.standard_normal(size=(x, n)).astype(dtype)
for x in range(min_x, number_of_matrices + min_x)]

start = timeit.default_timer()
numpy_res1 = np.sum(numpy_version1(*L)
for _ in xrange(iteration_count))
print 'numpy_version1', timeit.default_timer() - start

start = timeit.default_timer()
numpy_res2 = np.sum(numpy_version2(*L)
for _ in xrange(iteration_count))
print 'numpy_version2', timeit.default_timer() - start

start = timeit.default_timer()
theano_res1 = np.sum(theano_version1(*L)
for _ in xrange(iteration_count))
print 'theano_version1', timeit.default_timer() - start

start = timeit.default_timer()
theano_res2 = np.sum(theano_version2(*L)
for _ in xrange(iteration_count))
print 'theano_version2', timeit.default_timer() - start

start = timeit.default_timer()
theano_res3 = np.sum(theano_version3(np.concatenate(L, axis=0))
for _ in xrange(iteration_count))
print 'theano_version3', timeit.default_timer() - start

assert np.allclose(numpy_res1, numpy_res2)
assert np.allclose(numpy_res2, theano_res1)
assert np.allclose(theano_res1, theano_res2)
assert np.allclose(theano_res2, theano_res3)


main()

当运行这个打印时(类似的东西)

numpy_version1 1.47830819649
numpy_version2 1.77405482179
theano_version1 1.3603150303
theano_version2 1.81665318145
theano_version3 1.86912039489

断言通过,表明 Theano 和 numpy 版本都以高精度计算相同的结果。显然,如果使用 float32 而不是 float64,这种精度会降低。

时序结果表明向量化方法可能并不可取,这取决于矩阵大小。在上面的例子中,矩阵很大,非串联方法更快,但是如果在 main 函数中更改了 nmin_x 参数小得多,然后连接方法更快。在 GPU 上运行时可能会出现其他结果(仅限 Theano 版本)。

关于algorithm - 在 Theano 中循环(或向量化)可变长度矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34511680/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com