【问题标题】:How to multiply multi-dimensional arrays/matrices in Julia如何在 Julia 中乘以多维数组/矩阵
【发布时间】:2015-12-17 13:55:45
【问题描述】:

将两个多维数组相乘,例如,一个 1 维数组与一个 3 维数组:

[1 2] * reshape(1:8,2,2,2)

给我错误信息:

LoadError: MethodError: `*` has no method matching *(::Array{Int64,2}, ::Array{Int64,3})
Closest candidates are:
  *(::Any, ::Any, !Matched::Any, !Matched::Any...)
  *{TA,TB}(::Union{DenseArray{TA,1},DenseArray{TA,2},SubArray{TA,1,A<:DenseArray{T,N},I<:Tuple{Vararg{Union{Colon,Int64,Range{Int64}}}},LD},SubArray{TA,2,A<:DenseArray{T,N},I<:Tuple{Vararg{Union{Colon,Int64,Range{Int64}}}},LD}}, !Matched::Base.LinAlg.AbstractTriangular{TB,S<:AbstractArray{T,2}})
  *{TA,TQ,N}(::Union{DenseArray{TA,N},SubArray{TA,N,A<:DenseArray{T,N},I<:Tuple{Vararg{Union{Colon,Int64,Range{Int64}}}},LD}}, !Matched::Union{Base.LinAlg.QRCompactWYQ{TQ,M<:AbstractArray{T,2}},Base.LinAlg.QRPackedQ{TQ,S<:AbstractArray{T,2}}})
  ...
while loading In[167], in expression starting on line 1

 in Ac_mul_B at operators.jl:157

使用多维矩阵代数的数学定义进行(1 乘 2)*(2 乘 2 乘 2)矩阵/数组的乘法。

一个更一般的例子可以是 A*B = C 表示 sum_k A_{i,j,k} B_{k,l,m} = C_{i,j,l,m},其中 A 是 3 -索引矩阵,或者你喜欢的张量,B 是一个 3 索引的,结果 C 是一个四索引矩阵/张量,但是,一般来说,可以有任意数量的维度,一个维度可以有任意大小(在合理范围内)。查看有关matrix producttensor contraction 定义的更多信息。

在 Julia 中这个乘法的正确语法是什么?

【问题讨论】:

  • 使用.* 而不是*
  • “多维矩阵代数的数学定义”是什么意思。张量积?矩阵之间的张量积由kron得到。还是元素乘积.*
  • @mschauer 为了使其足够通俗易懂,A*B = CI 表示 sum_k A_{i,j,k} B_{k,l,m} = C_{i,j,l ,m},其中 A 是一个 3 索引矩阵,或者你喜欢的张量,B 是一个 3 索引矩阵,结果 C 是一个四索引矩阵/张量。有关矩阵乘积的定义,请参见:en.wikipedia.org/wiki/…。我上面的定义只是对 n>2 的 n 维矩阵的概括。如果你熟悉Matlab,这个操作是由*那里完成的。
  • @Vincent Zoonekynd 没错!

标签: arrays matrix julia matrix-multiplication


【解决方案1】:

矩阵乘法:使用 *

矩阵元素乘法:使用 .*

如果您想将两个矩阵相乘A*B,则两者的大小必须很大:例如 A 的大小 (a1,a2), B的大小(b1, b2); 为了使乘法可行a2必须与b1相同

在你的情况下:

julia> A=[1 2]
1x2 Array{Int64,2}:
 1  2

julia> size(A) #remember that size(A') is (2,1)
(1,2)

julia> B=reshape(1:8,2,2,2)
2x2x2 Array{Int64,3}:
[:, :, 1] =
 1  3
 2  4

[:, :, 2] =
 5  7
 6  8

julia> size(B)
(2,2,2)

julia> size(B[:,:,1])
(2,2)   

julia> A*B[:,:,1]
1x2 Array{Int64,2}:
 5  11

julia> A*B[:,:,2]
1x2 Array{Int64,2}:
 17  23

编辑:“一次”中的乘法(为清楚起见分开):

julia> A*B[:,:,1]
1x2 Array{Int64,2}:
 5  11

julia> A*B[:,:,2]
1x2 Array{Int64,2}:
 17  23

julia> C=A*B[:,:]
1x4 Array{Int64,2}:
 5  11  17  23

julia> size(C)
(1,4)

julia> D1 = reshape(C, 2,2)
2x2 Array{Int64,2}:
  5  17
 11  23

julia> D2 = reshape(C, 2,2)'
2x2 Array{Int64,2}:
  5  11
 17  23

真正一口气:

julia> D = reshape(A*B[:,:], 2,2)
2x2 Array{Int64,2}:
  5  17
 11  23

【讨论】:

  • 是的,这些是我期望 AB 的两层的数字,但我不知道如何像 AB 那样“一次性”进行这种乘法而不是做 AB[:,:,1] 和 AB[:,:,2]。
  • 我已经更新了答案。老实说,很难给你答案,因为我不明白整个问题:)
  • 在问题后查看我的评论以获得准确的定义:)
  • 如果你这么说,我很高兴:)
  • 好吧,至少 D1 是这个特定示例的解决方案。但是,如果事先不知道矩阵的大小,例如,Am1 by m2Bn1 by n2 by n3 矩阵,其中m1=n1 那么你需要使用矩阵的大小引入更多噪声:A = [1 2] B = reshape(1:12,2,2,3) reshape(A*B[:,:],size(B,2),size(B,3))。但是可能有一种方法可以为此类矩阵运算重新定义 * 运算符。
【解决方案2】:

您可以使用reshape将多维数组转换为矩阵, 将它们相乘,然后将结果转换回多维数组。

A = [1 2]
B = reshape(1:8,2,2,2)
reshape( reshape(A,2,1)' * reshape(B,2,4), 2, 2 )

(在这个例子中,由于A已经是一个矩阵,实际上不需要对其进行整形。)

【讨论】:

  • 这是最快的方法吗?也就是说,编译器将足够聪明,reshape 操作是零成本的?
  • reshape 应该很便宜。 github.com/JuliaMath/TensorCore.jl 有一个简洁的版本(注意伴随向量等),你可以用它写A ⊡ B
猜你喜欢
  • 1970-01-01
  • 2023-01-04
  • 2017-08-16
  • 2018-11-01
  • 2014-02-28
  • 1970-01-01
  • 2017-03-20
  • 2019-09-18
  • 1970-01-01
相关资源
最近更新 更多