отбрасывая синглтон размеры в юли - PullRequest
0 голосов
/ 25 сентября 2018

Просто поиграем с Джулией (1.0), и одна вещь, которую мне нужно много использовать в Python / numpy / matlab, - это функция squeeze для отбрасывания измерений синглтона.

Я обнаружил, что однаДжулия может сделать это следующим образом:

a = rand(3, 3, 1);
a = dropdims(a, dims = tuple(findall(size(a) .== 1)...))

Вторая строка кажется немного громоздкой и не легко читаемой и разбираемой сразу (это также может быть моим уклоном, который я привнес с других языков).Тем не менее, мне интересно, это канонический способ сделать это в Юлии?

Ответы [ 4 ]

0 голосов
/ 26 сентября 2018

Позвольте мне просто добавить, что "неконтролируемое" dropdims (отбрасывание любого одноэлементного измерения) является частым источником ошибок.Например, предположим, что у вас есть какой-то цикл, который запрашивает массив данных A из какого-то внешнего источника, и вы запускаете R = sum(A, dims=2) для него, а затем избавляетесь от всех одноэлементных измерений.Но затем предположим, что один раз из 10000 ваш внешний источник возвращает A, для которого size(A, 1) оказывается равным 1: бум, внезапно вы отбрасываете больше измерений, чем планировали, и, возможно, рискует сильно ошибочно интерпретировать ваши данные.

Если вы зададите эти размеры вручную (например, dropdims(R, dims=2)), то вы защищены от ошибок, подобных этим.

0 голосов
/ 26 сентября 2018

Фактический ответ на этот вопрос меня удивил.То, что вы спрашиваете, можно перефразировать как:

почему dropdims(a) не удаляет все измерения синглтона?

Я собираюсь процитировать Тима Холи из соответствующая проблема здесь:

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

Помимо стабильности типов, есть и другие удивительные последствия того, что вы написали.Например, обратите внимание, что:

julia> f(a) = dropdims(a, dims = tuple(findall(size(a) .== 1)...))
f (generic function with 1 method)

julia> f(rand(1,1,1))
0-dimensional Array{Float64,0}:
0.9939103383167442

В итоге, включение такого метода в Base Джулия побудит пользователей использовать его, что приведет к потенциально нестабильному типу кода, который при некоторых обстоятельствах не будетбыстро (чего-то, что разработчики ядра усиленно пытаются избежать).В таких языках, как Python, строгая стабильность типов не применяется, и поэтому вы найдете такие функции.

Конечно, ничто не мешает вам определить свой собственный метод, как у вас.И я не думаю, что вы найдете значительно более простой способ написать это.Например, предложение для Base, которое не было реализовано, было методом:

function squeeze(A::AbstractArray)
    singleton_dims = tuple((d for d in 1:ndims(A) if size(A, d) == 1)...)
    return squeeze(A, singleton_dims)
end

Просто помните о возможных последствиях его использования.

0 голосов
/ 26 сентября 2018

Я немного удивлен откровением Колина;что-то, что полагается на «изменение формы», является стабильным типом?(плюс, в качестве бонуса, возвращает представление, а не копию).

julia> function squeeze( A :: AbstractArray )
         keepdims = Tuple(i for i in size(A) if i != 1);
         return reshape( A, keepdims );
       end;

julia> a = randn(2,1,3,1,4,1,5,1,6,1,7);

julia> size( squeeze(a) )
(2, 3, 4, 5, 6, 7)

Нет?

0 голосов
/ 26 сентября 2018

Вы можете избавиться от tuple в пользу запятой ,:

dropdims(a, dims = (findall(size(a) .== 1)...,))
...