Search
\[ \def\_#1{\mathbf{#1}} \def\x{\times} \def\R{\mathbb{R}} \def\mat#1{\begin{bmatrix}#1\end{bmatrix}} \def\matr#1{\begin{bmatrix*}[r]#1\end{bmatrix*}} \def\dist{\mathop{\text{dist}}} \]
Tento úkol navazuje na úkol prokládání bodů kružnicí , kde jsme se snažili proložit body tak, aby minimalizovali součet čtverců jejich algebraických vzdáleností a doufali jsme, že řešení bude zhruba podobné, jako kdybychom minimalizovali součet čtverců vzdáleností bodů od kružnice. V tomto úkolu už budete hledat parametry kružnice, které minimalizují součet čtverců vzdáleností \begin{equation}\label{objective} f(x_0,y_0,r) = \sum_{i=1}^n \dist(x_i,y_i,x_0,y_0,r)^2, \end{equation} kde $(x_i, y_i)$, $i,\dots,n$ jsou body kterými prokládáme kružnici, $(x_0, y_0)$ je její střed a $r$ její poloměr.
Budeme minimalizovat $f$ pomocí iteračních metod. Použijeme gradientní metodu a protože je $f$ ve tvaru nelineárních nejmenších čtverců, můžeme použít i Gauss-Newtonovu a Levenberg-Marquardtovu metodu.
Napište funkce vykonávajíní jednu iteraci Levenberg-Marquardtovy metody, Gauss-Newtonovy metody a gradientní metody na optimalizaci funkce $f$. U gradientní metody musíme volit délku kroku. K tomu můžeme použít line-search. Tomu se v této úloze věnovat nebudeme a délku kroku dostane vaše funkce jako argument. Vyzkoušejte si sami, jaký vliv má tato délka kroku na konvergenci metody.
Pokud budete prakticky chtít řešit nějakou optimalizační úlohu, typicky na to použijete nějaký solver (z tohoto kurzu třeba na nejmenší čtverce, svd rozklad, lineární programování). Čím specializovanější je to solver, tím větší instance úlohy umí řešit v rozumném čase. Pokud ale máte malou úlohu, často stačí obecný solver, kterému dáte jako argument účelovou funkci a vrátí optimální řešní. Vyzkoušejte i tento přístup.
Jako úkoly napište tyto funkce:
[x y r success] = LM_iter(X, x0, y0, r0, mu)
success
[x y r] = GN_iter(X, x0, y0, r0)
[x y r] = grad_iter(X, x0, y0, r0, a)
f = get_objective_function(X)
f
c = [x0, y0, r]
f( c )
f([1,2,3])
f([1,2,3]) == sum(dist(X, 1, 2, 3).^2)
f([1,2,3]) == sum(dist(X, 1, 2, 3)**2)
Budete potřebovat funkci d = dist(X, x0, y0, r), kterou jste už napsali, kde X je matice která má v řádcích body, x0, y0, r0 jsou parametry kružnice před iterací, x, y, r jsou parametry po vykonání iterace, mu je parameter LM-metody a a je délka kroku pro gradientní metody.
d = dist(X, x0, y0, r)
X
x0, y0, r0
x, y, r
mu
a
Templaty, včetně skriptu pro testování si stáhněte zde: template pro matlab, template pro python. Pro python spouštějte skript nlls.py, pro matlab nlls.m. Animace se pauzuje po každém kroku, musíte klikat pro další iterace.
nlls.py
nlls.m
V řídícím skriptu se přijme krok gradientní metody pouze pokud se zlepší účelová funkce a na základě toho se upraví délka kroku, podobně jako u LM. Nenechte se tím zmást, tímto zaručujeme konvergenci metody. Více to diskutujeme v úkolech pro radost.