在下面的代码中,我使用Julia Optim软件包来查找与目标函数相关的最优矩阵。 遗憾的是,提供的优化函数仅支持向量,因此我必须先将矩阵转换为向量,然后再将其传递给optimize函数,并在目标函数中使用它时将其转换回来。
function opt(A0,X)
I1(A) = sum(maximum(X*A,1))
function transform(A)
# reshape matrix to vector
return reshape(A,prod(size(A)))
end
function transformback(tA)
# reshape vector to matrix
return reshape(tA, size(A0))
end
obj(tA) = -I1(transformback(tA))
result = optimize(obj, transform(A0), method = :nelder_mead)
return transformback(result.minimum)
end
我认为朱莉娅每次都会为此分配新的空间而感觉很慢,那么解决这个问题的方法会更有效?
答案 0 :(得分:6)
只要数组包含被认为是不可变的元素(包括所有基元),那么数组的元素就包含在1个 连续的 内存块中。因此,您可以打破维度规则,只需将二维数组视为一维数组,这就是您想要做的。所以你不需要重塑,但我不认为重塑是你的问题
考虑以下功能
function enumerateArray(a)
for i = 1:*(size(a)...)
print(a[i])
end
end
此函数将 a 的所有维度相乘,然后从1到该数字循环,假设 a 是一维。
将a定义为以下
julia> a = [ 1 2; 3 4; 5 6]
3x2 Array{Int64,2}:
1 2
3 4
5 6
结果是
julia> enumerateArray(a)
135246
这说明了一些事情。
那么,问题是为什么不重塑这个事实呢?它确实如此。这是array.c
中重塑的julia来源a = (jl_array_t*)allocobj((sizeof(jl_array_t) + sizeof(void*) + ndimwords*sizeof(size_t) + 15)&-16);
所以是的,创建了一个新数组,但只创建了新的维度信息,它指向未复制的原始数据。您可以像这样验证这一点:
b = reshape(a,6);
julia> size(b)
(6,)
julia> size(a)
(3,2)
julia> b[4]=100
100
julia> a
3x2 Array{Int64,2}:
1 100
3 4
5 6
因此设置 b 的第4个元素会设置 a 的(1,2)元素。
总体缓慢
I1(A) = sum(maximum(X*A,1))
将创建一个新数组。
您可以使用几个宏来跟踪 @profile 和 @time 。时间将另外记录分配的内存量,并且可以放在任何表达式之前。
例如
julia> A = rand(1000,1000);
julia> X = rand(1000,1000);
julia> @time sum(maximum(X*A,1))
elapsed time: 0.484229671 seconds (8008640 bytes allocated)
266274.8435928134
@profile 记录的统计信息使用 Profile.print()
输出答案 1 :(得分:1)
此外,Optim中的大多数方法实际上允许您提供数组,而不仅仅是Vector。您可以概括nelder_mead
函数来执行相同的操作。