Julia 如何快速重塑阵列

Julia 如何快速重塑阵列,julia,Julia,在下面的代码中,我使用Julia Optim包来寻找关于目标函数的最优矩阵。 不幸的是,提供的优化函数只支持向量,因此我必须在将矩阵传递给优化函数之前将其转换为向量,并且在目标函数中使用时将其转换回 function opt(A0,X) I1(A) = sum(maximum(X*A,1)) function transform(A) # reshape matrix to vector return reshape(A,prod(size(A)

在下面的代码中,我使用Julia Optim包来寻找关于目标函数的最优矩阵。 不幸的是,提供的优化函数只支持向量,因此我必须在将矩阵传递给优化函数之前将其转换为向量,并且在目标函数中使用时将其转换回

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

我认为Julia每次都在为此分配新的空间,而且感觉很慢,那么解决这个问题的更有效的方法是什么呢?

只要数组包含被认为是不可变的元素,其中包括所有原语,那么数组的元素就包含在一个大的连续的内存块中。因此,您可以打破维度规则,简单地将二维数组视为一维数组,这就是您想要做的。所以你不需要重塑,但我不认为重塑是你的问题

数组是列主数组和连续数组 考虑以下函数

function enumerateArray(a)
   for i = 1:*(size(a)...)
      print(a[i])
   end
end
该函数将a的所有维度相乘,然后假设a是一维的,从1循环到该数字

当您将

julia> a = [ 1 2; 3 4; 5 6]
3x2 Array{Int64,2}:
 1  2  
 3  4
 5  6
结果是

julia> enumerateArray(a)
135246
这说明了两件事

  • 是的,它确实有效
  • 矩阵以列主格式存储
  • 重塑 所以,问题是为什么重塑不使用这个事实?是的。这是julia在中重塑的来源

    因此,是的,创建了一个新数组,但仅创建了新的维度信息,它指向未复制的原始数据。您可以这样简单地进行验证:

     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的第四个元素将设置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()输出的。此外,Optim中的大多数方法实际上允许您提供数组,而不仅仅是向量。您可以将
    nelder\u mead
    函数概括为同样的功能。

    是否应该有类似于重塑函数的功能,而不是创建/复制到一个新对象,只是为已经存在的数据提供一个重塑的接口?它确实为现有数据提供了一个接口,但是因为
    Array{Float64,1}
    是与
    数组{Float64,2}不同的类型
    ,即使基础数据相同,也必须有一个新对象作为包装器。
    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