如何检查 Flux.jl 中模型的输入维度?

How to check the input dimensions of a model in Flux.jl?

我有一个正在使用的 resnet 模型。我最初使用批量图像训练模型。现在它已经过训练,我想对单个图像(224x224,具有 3 个颜色通道)进行推理。但是,当我通过 model(imgs[:, :, :, 2]) 将图像传递给我的模型时,我得到:

DimensionMismatch("Rank of x and w must match! (3 vs. 4)")

Stacktrace:
  [1] DenseConvDims(x::Array{Float32, 3}, w::Array{Float32, 4}; kwargs::Base.Iterators.Pairs{Symbol, Any, NTuple{4, Symbol}, NamedTuple{(:stride, :padding, :dilation, :groups), Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}, Tuple{Int64, Int64}, Int64}}})
    @ NNlib ~/.julia/packages/NNlib/P9BhZ/src/dim_helpers/DenseConvDims.jl:58
  [2] (::Conv{2, 2, typeof(identity), Array{Float32, 4}, Vector{Float32}})(x::Array{Float32, 3})
    @ Flux ~/.julia/packages/Flux/ZnXxS/src/layers/conv.jl:162
...
...

作为参考,imgs[:, :, :, 2] 给出:

224×224×3 Array{Float32, 3}:
[:, :, 1] =
 0.4       0.419608  0.482353  0.490196  …  0.623529  0.611765  0.627451
 0.423529  0.478431  0.513726  0.486275     0.65098   0.65098   0.65098
 0.419608  0.47451   0.541176  0.54902      0.682353  0.670588  0.639216
 0.52549   0.529412  0.568627  0.564706     0.588235  0.592157  0.572549
 0.556863  0.541176  0.513726  0.505882     0.603922  0.635294  0.654902
 0.486275  0.490196  0.521569  0.537255  …  0.635294  0.654902  0.65098
 0.529412  0.513726  0.533333  0.537255     0.603922  0.596078  0.596078
 0.521569  0.52549   0.505882  0.513726     0.580392  0.576471  0.572549
...
...

知道我在这里遗漏了什么吗?模型在推理过程中是否需要与训练时相同的维度?有没有办法检查这个以确保我提供了正确的输入尺寸?

更新:我意识到我需要传递图像的数量(在本例中是一张),所以我做了:

img1 = cat(imgs[:, :, :, 1]; dims = ndims(imgs[:, :, :, 1]) + 1 )
img1
model(img1)

按预期工作。如果有人对有关检查输入暗淡的原始问题有答案,我将保留此问题。

抱歉,我真的不是专家,但这不是imgs[:, :, :, 2] crates a 3-dimensional tensor 的问题吗?可能 imgs[:, :, :, 2:2] 会起作用,因为它使最后一个维度等于一的四维张量(因为你有一个图像)

如您所见,NNlib.jl(为 Flux 实现卷积的库)期望输入具有批量维度。如果您正在通过单个图像,则可以填充单个尺寸。有几种方法可以实现这一点。

一、问题:

julia> size(x[:, :, :, 1])
(3, 3, 16)

彩色图像应为 4D(宽度 x 高度 color/depth 按批处理)。

填充批量维度的一个选项是使用索引范围:

julia> size(x[:, :, :, 1:1])
(3, 3, 16, 1)

如果给定单个图像作为 3D 数组,另一种选择是使用 Flux.unsqueeze:

julia> size(Flux.unsqueeze(x[:, :, :, 1], ndims(x)))
(3, 3, 16, 1)

julia> all(Flux.unsqueeze(x[:, :, :, 1], ndims(x)) .== x[:, :, :, 1])
true

我们将要填充的维度作为参数传递给 unsqueeze。在我们的例子中,这应该是 x 的最后一个维度(即批量维度),我们可以在 Julia 中使用 ndims(x).

获得它

这两个答案都是正确的,真的。一个简单的 reshape(x, size(x)..., 1) 也应该可以解决问题,假设 x 是您在索引到 batch

时获得的 3 维图像张量