我试图用Julia编写一个函数,该函数采用多维数组(数据立方体),并将每个条目从0缩放到1。但是,每当我在原子中运行代码时,都会出现错误>
LoadError: MethodError: no method matching -(::Array{Float64,2}, ::Float64)
Closest candidates are:
-(::Float64, ::Float64) at float.jl:397
-(::Complex{Bool}, ::Real) at complex.jl:298
-(::Missing, ::Number) at missing.jl:97
...
Stacktrace:
[1] rescale_zero_one(::Array{Float64,2}) at D:\Julio\Documents\Michigan_v2\CS\EECS_598_Data_Science\codex\Codex_3\svd_video.jl:40
[2] top-level scope at D:\Julio\Documents\Michigan_v2\CS\EECS_598_Data_Science\codex\Codex_3\svd_video.jl:50 [inlined]
[3] top-level scope at .\none:0
in expression starting at D:\Julio\Documents\Michigan_v2\CS\EECS_598_Data_Science\codex\Codex_3\svd_video.jl:48
我具有函数必须执行的操作的基本知识,但是我真的不理解某些表示法以及错误说明或解决方法。
function rescale_zero_one(A::Array)
B = float(A)
B -= minimum(B)
B /= maximum(B)
return B
end
m,n,j = size(movie_cube)
println(j)
C = Array{Float64}(UndefInitializer(),m,n,j)
for k in 1:j
println(k)
C[:,:,j] = rescale_zero_one(movie_cube[:,:,j])
end
变量movie_cube是Float64条目的3维数据数组,我只想将条目从零重新缩放为一。但是,我提到的错误不断出现。我非常感谢您提供此代码的帮助!
答案 0 :(得分:1)
尝试使用点语法在数组中执行某些操作!
function rescale_zero_one(A::Array)
B = float.(A)
B .-= minimum(B)
B ./= maximum(B)
return B
end
答案 1 :(得分:1)
这段代码更快,更简单(它只对输入矩阵进行两次传递,而不是先前答案中的五次传递):
function rescale(A::Matrix)
(a, b) = extrema(A)
return (A .- a) ./ (b - a)
end
这可以概括为三个维度,因此您不需要C
中的维度上的外部循环。警告:此解决方案实际上有点慢,因为使用extrema
关键字时maximum
/ minimum
/ dims
的速度很慢,这很奇怪:
function rescale(A::Array{T, 3}) where {T}
mm = extrema(A, dims=(1,2))
a, b = first.(mm), last.(mm)
return (A .- a) ./ (b .- a)
end
现在您可以只写C = rescale(movie_cube)
。您甚至可以进一步概括:
function rescale(A::Array{T, N}; dims=ntuple(identity, N)) where {T,N}
mm = extrema(A, dims=dims)
a, b = first.(mm), last.(mm)
return (A .- a) ./ (b .- a)
end
现在,您可以按照自己喜欢的任何维度对多维数组进行标准化。当前行为变为
C = rescale(movie_cube, dims=(1,2))
重新缩放每一行是
C = rescale(movie_cube, dims=(1,))
默认行为是重新缩放整个数组:
C = rescale(movie_cube)
还有一件事,这有点奇怪:
C = Array{Float64}(UndefInitializer(),m,n,j)
没错,但是更短更优雅的方式更常见:
C = Array{Float64}(undef, m, n, j)
您还可以考虑简单地写:C = similar(movie_cube)
或C = similar(movie_cube, Float64)
。
编辑:另一个通用的解决方案是不在rescale
函数中实现尺寸处理,而要利用mapslices
。然后:
function rescale(A::Array)
(a, b) = extrema(A)
return (A .- a) ./ (b - a)
end
C = mapslices(rescale, A, dims=(1,2))
由于我不了解的原因,这也不是最快的解决方案。我真的认为这应该很快,并且可能会在Julia的未来版本中加快。