Этот код немного быстрее и проще (он делает только два прохода по входной матрице, а не пять в предыдущем ответе):
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))
Это тоже не самое быстрое решение, по причинам, которые я не понимаю.Я действительно думаю, что это должно быть быстро и может быть ускорено в будущей версии Джулии.