Как найти минимум нелинейной многомерной функции с помощью метода Ньютона (код не линейной алгебры)
Я пытаюсь сделать некоторую оценку параметров и хочу выбрать оценки параметров, которые минимизируют квадратную ошибку в предсказанном уравнении более 30 переменных. Если бы уравнение было линейным, я бы просто вычислил 30 частных производных, установил бы их все в ноль и использовал бы решатель линейных уравнений. Но, к сожалению уравнение нелинейное и его производные.
Если бы уравнение было над одной переменной, я бы просто использовал метод Ньютона (также известный как Ньютона-Рафсона). Сеть богата примерами и кодом для реализации метода Ньютона для функций одной переменной.
учитывая, что у меня около 30 переменных,Как я могу запрограммировать численное решение этой проблемы с помощью метода? У меня есть уравнение в закрытой форме и я могу вычислить первую и вторую производные, но я не знаю, как из этого исходить. Я нашел большое количество процедуры в интернете, но они быстро попадают в тяжелые матричные обозначения. Я нашел что-то умеренно полезным в Википедии, но у меня возникли проблемы с переводом его в код.
где я беспокоюсь о разрушении, это матричная алгебра и матричные инверсии. Я могу инвертировать матрицу с помощью решателя линейных уравнений, но я беспокоюсь о том, чтобы получить правильные строки и столбцы, избежать ошибок транспозиции и т. д.
вполне бетон:
Я хочу работать с таблицами, отображающими переменные в их значения. Я могу написать функцию такой таблицы, которая возвращает квадратную ошибку, заданную такой таблицей как аргумент. Я также могу создавать функции, возвращающие частичную производную по любой заданной переменной.
У меня есть разумная начальная оценка для значений в таблице, поэтому я не беспокоюсь о сходимости.
Я не уверен, как чтобы написать цикл, который использует оценку (таблицу значений для каждой переменной), функцию и таблицу функций с частичной производной для получения новой оценки.
Это последнее, с чем я хотел бы помочь. Любая прямая помощь или указатели на хорошие источники будут тепло оценены.
Edit: поскольку у меня есть первая и вторая производные в закрытой форме, я хотел бы воспользоваться ими и избежать более медленных сходящихся методов, таких как симплекс поиски.
4 ответов
вы можете найти то, что вам нужно, на числовых рецептах на веб-странице C. Есть бесплатная версия доступна онлайн. здесь (PDF)-это глава, содержащая метод Ньютона-Рафсона, реализованный в C. Вы также можете посмотреть, что доступно в библиотека netlib (LINPack, et. Эл.).
ссылка на числовые рецепты была наиболее полезной. Я закончил символически дифференцировать мою оценку ошибки, чтобы получить 30 частных производных, а затем использовал метод Ньютона, чтобы установить их все в ноль. Вот основные моменты кода:
__doc.findzero = [[function(functions, partials, point, [epsilon, steps]) returns table, boolean
Where
point is a table mapping variable names to real numbers
(a point in N-dimensional space)
functions is a list of functions, each of which takes a table like
point as an argument
partials is a list of tables; partials[i].x is the partial derivative
of functions[i] with respect to 'x'
epilson is a number that says how close to zero we're trying to get
steps is max number of steps to take (defaults to infinity)
result is a table like 'point', boolean that says 'converged'
]]
-- See Numerical Recipes in C, Section 9.6 [http://www.nrbook.com/a/bookcpdf.php]
function findzero(functions, partials, point, epsilon, steps)
epsilon = epsilon or 1.0e-6
steps = steps or 1/0
assert(#functions > 0)
assert(table.numpairs(partials[1]) == #functions,
'number of functions not equal to number of variables')
local equations = { }
repeat
if Linf(functions, point) <= epsilon then
return point, true
end
for i = 1, #functions do
local F = functions[i](point)
local zero = F
for x, partial in pairs(partials[i]) do
zero = zero + lineq.var(x) * partial(point)
end
equations[i] = lineq.eqn(zero, 0)
end
local delta = table.map(lineq.tonumber, lineq.solve(equations, {}).answers)
point = table.map(function(v, x) return v + delta[x] end, point)
steps = steps - 1
until steps <= 0
return point, false
end
function Linf(functions, point)
-- distance using L-infinity norm
assert(#functions > 0)
local max = 0
for i = 1, #functions do
local z = functions[i](point)
max = math.max(max, math.abs(z))
end
return max
end
в качестве альтернативы использованию метода Ньютона Симплексный метод Nelder-Mead идеально подходит для этой проблемы и ссылается в числовых Recpies в C.
Роб