используя Julia 1.0 findmax эквивалент numpy.argmax - PullRequest
3 голосов
/ 10 апреля 2019

В Джулии я хочу найти индекс столбца матрицы для максимального значения в каждой строке, в результате чего получается Vector{Int}. Вот как я это делаю в настоящее время (Samples имеет 7 столбцов и 10000 строк):

mxindices = [ i[2] for i in findmax(Samples, dims = 2)[2]][:,1]

Это работает, но кажется довольно неуклюжим и многословным. Интересно, есть ли лучший способ.

Ответы [ 3 ]

2 голосов
/ 11 апреля 2019

Еще проще: у Юлии есть функция argmax, а у Юлии 1.1+ - итератор eachrow. Таким образом:

map(argmax, eachrow(x))

Простой, читаемый и быстрый - он соответствует производительности f3 и f4 Колина в моих быстрых тестах.

1 голос
/ 10 апреля 2019

ОБНОВЛЕНИЕ: Ради полноты я добавил отличное решение Мэтта Б. в набор тестов (и также заставил transpose в f4 сгенерировать новыйматрица, а не ленивый вид).

Вот несколько разных подходов (ваш базовый случай f0):

f0(x) = [ i[2] for i in findmax(x, dims = 2)[2]][:,1]
f1(x) = getindex.(argmax(x, dims=2), 2)
f2(x) = [ argmax(vec(x[n,:])) for n = 1:size(x,1) ]
f3(x) = [ argmax(vec(view(x, n, :))) for n = 1:size(x,1) ]
f4(x) = begin ; xt = Matrix{Float64}(transpose(x)) ; [ argmax(view(xt, :, k)) for k = 1:size(xt,2) ] ; end
f5(x) = map(argmax, eachrow(x))

Используя BenchmarkTools, мы можем проверить эффективностькаждый (я установил x = rand(100, 200)):

julia> @btime f0($x);
  76.846 μs (13 allocations: 4.64 KiB)

julia> @btime f1($x);
  76.594 μs (11 allocations: 3.75 KiB)

julia> @btime f2($x);
  53.433 μs (103 allocations: 177.48 KiB)

julia> @btime f3($x);
  43.477 μs (3 allocations: 944 bytes)

julia> @btime f4($x);
  73.435 μs (6 allocations: 157.27 KiB)

julia> @btime f5($x);
  43.900 μs (4 allocations: 960 bytes)

Так что подход Мэтта - довольно очевидный победитель, так как он выглядит просто как синтаксически более чистая версия моего f3 (эти два, вероятно, компилируются вчто-то очень похожее, но я думаю, что это было бы излишним, чтобы проверить это).

Я надеялся, что f4 может иметь преимущество, несмотря на временное создание, созданное путем создания экземпляра transpose, поскольку он может работать настолбцы матрицы, а не строки (Юлия является основным языком столбцов, поэтому операции со столбцами всегда будут выполняться быстрее, поскольку элементы синхронизированы в памяти).Но этого, по-видимому, недостаточно, чтобы преодолеть недостаток временного.

Обратите внимание, если вам когда-либо понадобится полный CartesianIndex, то есть индекс строки и столбцамаксимум в каждой строке, то, очевидно, подходящее решение просто argmax(x, dims=2).

0 голосов
/ 10 апреля 2019

Функция Mapslices также является отличным вариантом для этой проблемы:

julia> Samples = rand(10000, 7);

julia> res = mapslices(row -> findmax(row)[2], Samples, dims=[2])[:,1];

julia> res[1:10]
10-element Array{Int64,1}:
 3
 1
 3
 5
 4
 4
 1
 4
 5
 3

Хотя это намного медленнее, чем предлагал Колин выше, для некоторых людей оно может быть более читабельным.По сути, это тот же код, с которого вы начинали, но вместо списочных пониманий используется mapslices.

...