Сообщения об ошибках ForwardDiff.jl и ReverseDiff.jl, связанные с::getfield()
Я пытаюсь использовать библиотеки ForwardDiff.jl и / или ReverseDiff.jl для вычисления градиента в задаче оптимизации.
Оба этих пакета дают мне сообщение об ошибке, относящееся к:: getfield ().
ReverseDiff дает мне LoadError:
MethodError: no method matching (::getfield(CalibrationModule, Symbol("#f#4"))
{AlgorithmParameters,ModelParameters,Guess,Array{Float64,1}})
(::ReverseDiff.TrackedArray{Float64,Float64,1,Array{Float64,1},Array{Float64,1}})
ForwardDiff дает мне LoadError:
MethodError: no method matching (::getfield(CalibrationModule, Symbol("#f#10"))
{AlgorithmParameters,ModelParameters,Guess,Array{Float64,1}})
(::Array{ForwardDiff.Dual{ForwardDiff.Tag{getfield(CalibrationModule,
Symbol("#f#10"))
{AlgorithmParameters,ModelParameters,Guess,Array{Float64,1}},Float64},Float64,6},1})
Я понятия не имею, как понять это сообщение об ошибке. Мой код слишком сложен, чтобы публиковать здесь, но, насколько я могу судить, я не использую библиотеки, написанные не на Джулии. Я широко использую пользовательские типы данных (изменяемые структуры), но не понимаю, почему это может вызвать проблемы...
2 ответа
Действительно трудно сказать без кода, но:
Распечатка как (::getfield(CalibrationModule, Symbol(...)){...}(...)
так Юлия отображает анонимные функции и замыкания. Вы получаете ошибку метода, что эта анонимная функция или закрытие не поддерживает подпись, которая принимает Array
либо с Dual
или же Tracked
номера. У вас, вероятно, есть функция, аналогичная:
function main()
...
f(A::Array{Float64}) = # ... some closure
...
f(...)
end
Но и ForwardDiff, и ReverseDiff требуют запуска вашей программы с двойными или отслеживаемыми числами - которые не являются Float64
, Итак, вы получаете ошибку метода, которую ваше закрытие назвало f
не принимает массивы этих двойных или отслеживаемых номеров.
Уменьшите специфику вашего f
закрытие для самой широкой вещи, которую он может поддерживать - вероятно, что-то вроде f(A::AbstractArray{<:Number}) = ...
, Обратите внимание, что две библиотеки делают это немного по-разному - ForwardDiff создает массив Duals, тогда как ReverseDiff создает отслеживаемый массив чисел с плавающей запятой. Таким образом, вы хотите оба ::AbstractArray
поддерживать больше, чем просто Array
s (вы должны почти всегда делать это, если вы не вызываете C), и вы хотите ослабить тип элемента, чтобы он был любым подтипом Number
, Я бы порекомендовал пойти еще дальше и не заботиться о типе элемента - вам часто не нужно заботиться об этом.
Из документов Джулии MethodError: no method matching
генерируется, когда нет метода с совпадающей сигнатурой типа тому, который вы вызываете. У Джулии есть динамическая система типов, но она позволяет создавать аннотации типов, которые выдают исключение, если значение не относится к ожидаемому типу. Так как вы широко используете пользовательские типы данных, может случиться так, что вы передаете значение пользовательского типа данных методу в ForwardDiff/ReverseDiff, который ожидает другой тип - трудно подтвердить, не видя код, но именно здесь я ' буду искать.