Moduł 05 · uczące się

Sieci neuronowe

MLP, MDN, IKFlow, diffusion, multi-modalne odwracanie f: Q → SE(3).

Trochę inaczej niż dotychczas

Do tej pory rozwiązywaliśmy IK przez jawne wzory matematyczne, albo zamknięte (moduł 1), albo iteracyjne (moduły 3 i 4). Teraz spróbujemy czegoś zupełnie innego: nauczyć komputer rozwiązywać IK przez pokazywanie mu tysięcy poprawnych przykładów. Zamiast programować algorytm, dostarczamy dane, a komputer sam odkrywa prawidłowości.

Wyobraź sobie, że uczysz dziecko rozpoznawać psy i koty. Nie tłumaczysz definicji („pies ma długi pysk i…"), pokazujesz tysiąc zdjęć z podpisami „pies" i „kot". Po jakimś czasie dziecko samo zaczyna rozpoznawać. Dokładnie tak działają sieci neuronowe: są to programy, które uczą się funkcji „wejście → wyjście" przez przykłady. Dla nas „wejście" = poza T, a „wyjście" = kąty q.

Co siedzi w środku sieci?, animacja krok po kroku

Zanim przejdziemy do skomplikowanych architektur, zobaczmy, jak działa najprostsza sieć neuronowa, wielowarstwowy perceptron (MLP). Animacja niżej przeprowadzi Cię przez jeden forward pass, czyli jedno przejście danych od wejścia do wyjścia. Naciśnij ▶ odtwórz albo klikaj dalej →:

krok 0/8: Start
WejścieWarstwa ukryta (tanh)Wyjście0.6x1 =-0.2x2 =0.5x3 =h1h2h3h4y1= q1y2= q2

Mała sieć MLP, 3 wejścia, 4 neurony ukryte, 2 wyjścia.

Naciśnij ▶ odtwórz albo dalej → żeby przejść przez forward pass krok po kroku. W każdym kroku zobaczysz, co dokładnie się dzieje.

Zauważ, w środku sieci nie ma żadnej magii. Każdy neuron to po prostu kalkulator, który robi trzy rzeczy:

  1. Bierze wartości z poprzedniej warstwy.
  2. Mnoży każdą przez przypisaną wagę i sumuje.
  3. Wynik puszcza przez prostą funkcję nieliniową (np. tanh).

Cała tajemnica sieci jest w tym, jakie dokładnie wagi siedzą przy strzałkach. Tych wag może być setki tysięcy. Nikt ich nie wpisuje ręcznie, uczą się same na danych treningowych. To jest właśnie uczenie (training).

Schemat sieci, dwa widoki

Po lewej, wersja specjalna dla naszego zadania (poza T → kąty q). Niżej, kanoniczny schemat z literatury. Obie pokazują to samo: warstwy neuronów połączone wagami.

xyz·······q₁q₂q₃q₄q₅q₆wejściepoza T (6 liczb)warstwa 164 neurony, tanhwarstwa 264 neurony, tanhwyjściekąty (6 liczb)Każda linia = jedna waga (parametr).waga dodatniawaga ujemnagrubość ≈ |waga|MLP: liczby wchodzą z lewej, wychodzą z prawej, w środku, mnożenia i dodawania
Klasyczny schemat MLP
Klasyczny diagram MLP, warstwa wejściowa, warstwy ukryte, warstwa wyjściowa. Każda strzałka to jeden parametr (waga).
Źródło: Wikimedia Commons · autor: Sky99 · licencja: CC BY-SA 3.0

Trening, jak komputer uczy się wag?

Trening sieci neuronowej to dokładnie ten sam problem optymalizacyjny co w module 4, tylko że tu zmiennymi są wagi, a kosztem jest średni błąd predykcji na danych treningowych:

θ=argminθ  1Ni=1Nfθ(xi)yi2\theta^* = \arg\min_\theta \; \frac{1}{N} \sum_{i=1}^{N} \big\|f_\theta(x_i) - y_i\big\|^2

Procedura w pseudokodzie:

  1. Inicjuj wagi losowo (małe wartości z gaussowskiego rozkładu).
  2. Bierz przykład (xi,yi)(x_i, y_i) z datasetu.
  3. Forward pass: oblicz y^=fθ(xi)\hat{y} = f_\theta(x_i).
  4. Sprawdź błąd: y^yi2\|\hat{y} - y_i\|^2.
  5. Backpropagation, algorytm wyliczający, jak każdą wagę przesunąć, żeby błąd zmalał (to jest tylko gradient z modułu 4, sprytnie zorganizowany).
  6. Przesuń wagi w tym kierunku (SGD albo Adam).
  7. Wróć do 2. Powtarzaj miliony razy.

Po skończonym treningu sieć, przy odrobinie szczęścia, daje sensowne predykcje także dla nowych danych, których nie widziała. To zjawisko nazywa się generalizacją. Jeśli sieć nauczyła się tylko zapamiętać dane treningowe i nie umie odpowiadać na nowe, mówimy o przetrenowaniu (overfitting).

SGD i Adam, co to za algorytmy?

W kroku 6 procedury napisałem „przesuń wagi w tym kierunku (SGD albo Adam)". Co to dokładnie?

SGD, Stochastic Gradient Descent, stochastyczny gradient descent. To po prostu zwykły gradient descent z modułu 4, ale z jedną sprytną modyfikacją: zamiast liczyć gradient na całym datasecie (co dla milionów przykładów zajmuje wieczność), liczymy go na jednym losowo wybranym przykładzie albo małym mini-batchu (zazwyczaj 32, 64 lub 128 przykładów):

θk+1=θkαLi(θk),iUniform(1,N)\theta_{k+1} = \theta_k - \alpha\,\nabla L_i(\theta_k), \quad i \sim \text{Uniform}(1, N)

Gradient z jednego przykładu jest niedokładnym oszacowaniem prawdziwego gradientu (stąd „stochastic", losowy), ale jest milion razy szybszy do policzenia. W praktyce: zaszumiona ścieżka mimo wszystko prowadzi do dobrego rozwiązania, a często nawet pomaga uciec z płytkich lokalnych minimów. „Wagi chodzą małymi krokami w mniej-więcej dobrym kierunku".

Adam, Adaptive Moment Estimation (Kingma & Ba, 2014). Ulepszony SGD, który adaptuje krok osobno dla każdej wagi. Pomysł:

  1. Dla każdej wagi pamiętamy średnią ruchomą gradientów (kierunek dotychczasowych aktualizacji, momentum).
  2. Pamiętamy też średnią ruchomą kwadratów gradientów (jak duże były ostatnie aktualizacje).
  3. Krok dla danej wagi: kierunek z (1) podzielony przez pierwiastek z (2). Wagi, które otrzymują często duże gradienty, dostają mniejszy krok; te które rzadko się aktualizują, większy.
mt=β1mt1+(1β1)gt,vt=β2vt1+(1β2)gt2m_t = \beta_1 m_{t-1} + (1-\beta_1) g_t, \quad v_t = \beta_2 v_{t-1} + (1-\beta_2) g_t^2
θt+1=θtαm^tv^t+ε\theta_{t+1} = \theta_t - \alpha \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \varepsilon}

(z dodatkową korektą obciążenia m^t=mt/(1β1t)\hat{m}_t = m_t/(1-\beta_1^t), v^t=vt/(1β2t)\hat{v}_t = v_t/(1-\beta_2^t)). Domyślne hiperparametry: β1=0,9\beta_1 = 0{,}9, β2=0,999\beta_2 = 0{,}999, α=103\alpha = 10^{-3}.

Dlaczego Adam wyparł czysty SGD w deep learningu?

  • Mniej strojenia kroku, domyślne α=103\alpha = 10^{-3} zwykle działa od razu, bez szukania.
  • Stabilniejszy, adaptacja kroku dla każdej wagi tłumi oscylacje.
  • Szybciej zbiega, szczególnie na początku treningu (momentum przyspiesza ruch w stałym kierunku).
  • Działa „od razu" dla różnych architektur (CNN, transformerów, MLP itd.).

Kiedy SGD bywa lepszy? Dla bardzo dużych modeli i długich treningów SGD z momentum daje czasem lepszą generalizację (model „bardziej wygładzony", mniej overfitujący). Stąd np. ResNet'y w ImageNecie często trenuje się SGD-em, a transformerów (BERT, GPT), Adamem (a właściwie Adam-W, wariantem z popraw lepszą regularyzacją).

W naszej aplikacji (sekcja „Laboratorium" niżej) używamy Adama, dzięki temu trening MLP w przeglądarce jest stabilny i kończy się w kilkunastu sekundach bez ręcznego strojenia α\alpha.

Krok 1

Naiwny MLP, najprostsza próba (i dlaczego nie wystarcza)

Pomysł: wytrenuj MLP, który dla danej pozy TT (6 liczb: pozycja + RPY) zwraca 6 kątów qq. Trenujesz na milionach par (T,q)(T, q) wygenerowanych losowo przez FK.

Brzmi sensownie, ale jest jeden zasadniczy problem.

Problem: jedna poza, kilka prawidłowych odpowiedzi

Pamiętasz z modułu 2, że dla Pumy ta sama poza może być osiągnięta na do 8 sposobów (shoulder L/R, elbow U/D, wrist flip)? W datasecie treningowym ta sama poza pojawia się więc kilka razy z różnymi kątami. A funkcja kosztu MSE każe sieci „minimalizuj średni kwadrat błędu", więc sieć uczy się średniej wszystkich poprawnych odpowiedzi.

Tylko że średnia ośmiu różnych prawidłowych konfiguracji nie jest żadną prawidłową konfiguracją. To jak byś zapytał ośmiu osób o najkrótszą drogę do biura, jedna mówi „przez most", druga „przez tunel", ich „średnia" („zjedź do rzeki i zatrzymaj się w połowie") to nonsens.

q (kąt przegubu)-2-1012q*1q*2MLPśrednia = błędna!Dla jednej pozy T istnieją DWIE poprawne wartości q. MLP uczy się ich średniej.prawdziwy rozkład p(q|T)predykcja MLP (jedna liczba)

Czerwona kropka to predykcja MLP, średnia dwóch niebieskich „dzwonków" prawdziwych odpowiedzi. Średnia trafia dokładnie tam, gdzie żadna z odpowiedzi nie była. To nie jest błąd implementacji ani za małej sieci, to fundamentalna pułapka uśredniania.

Praktyczny ratunek: hybryda NN → DLS

Mimo wad, naiwny MLP ma jedną zaletę, daje dobry punkt startowy (warm start). Pomysł hybrydy:

qseed=fθ(T)      kilka iteracji DLS      q (dokładne)q_{\text{seed}} = f_\theta(T) \;\;\xrightarrow{\;\text{kilka iteracji DLS}\;}\;\; q^* \text{ (dokładne)}

Sieć daje przybliżenie (błąd ~5 cm), DLS dopina do precyzji maszynowej w 2–3 iteracjach. Sieć daje szybkość, klasyczny solver, dokładność. Tak właśnie wygląda większość produkcyjnych systemów IK z neural-warmem.

Niżej, laboratorium. Trenujemy MLP od zera (bez zewnętrznych bibliotek ML, ~200 linii TypeScriptu) i porównujemy surową predykcję z hybrydą NN → DLS.

Krok 2

MDN, uczymy sieć, że poprawnych odpowiedzi może być wiele

Pomysł w jednym zdaniu: zamiast jednej liczby niech sieć zwraca listę możliwych odpowiedzi z prawdopodobieństwami.

Analogia: wyobraź sobie prognozę pogody. Możliwe podejścia:

  • Prognoza punktowa (jak naiwny MLP): „jutro będzie 10°C". Jeśli model się myli, masz pecha.
  • Prognoza probabilistyczna (jak MDN): „jutro: 70% szans 8°C ± 2°, 30% szans 15°C ± 2°" (dwa możliwe scenariusze). Może się okazać bardzo użyteczne, wiesz na co się przygotować.

Mixture Density Network (Bishop, 1994) to właśnie sieć, która zwraca prognozę probabilistyczną. Konkretnie , parametry kilku „dzwonków" (gaussianów):

  • Wagi αk(T)\alpha_k(T), jak prawdopodobny jest k-ty „garb"
  • Środki μk(T)\mu_k(T), gdzie ten garb leży
  • Szerokości Σk(T)\Sigma_k(T), jak szeroki jest garb

Suma wszystkich garbów daje rozkład prawdopodobieństwa p(qT)p(q\,|\,T), sieć mówi nie „q to 1.5", ale „q to z 50% szansy 1.5, z 50% szansy −1.5":

q (kąt przegubu)-2-1012komponent 1α₁ = 0.5, μ₁ = −1.5komponent 2α₂ = 0.5, μ₂ = +1.5MDN: zamiast zwracać jedną liczbę, zwraca DWA garby, po jednym na każdą poprawną odpowiedź.prawdziwy rozkład p(q|T)predykcja MDN (suma garbów)

Po wytrenowaniu sieć z K = 8 komponentami dla Pumy naturalnie odkrywa 8 gałęzi rozwiązania, bo to jest matematycznie optymalna liczba „garbów" dla tych danych.

Jak tego używać:

  • Najlepsze rozwiązanie, wybierz garb z największą wagą (α\alpha), weź jego środek (μ\mu).
  • Próbkowanie, losuj garb z prawdopodobieństwem proporcjonalnym do α\alpha, potem losuj punkt z gaussa wokół μ\mu. Daje różnorodne, ale poprawne odpowiedzi.
  • Ocena, dla danej kandydackiej wartości qq sieć zwraca jej prawdopodobieństwo. Można porównywać hipotezy.

Wady MDN: trening jest niestabilny (małe potknięcia inicjalizacji powodują, że wszystkie garby zlewają się w jeden); wybór K (ile garbów?) wymaga eksperymentów.

Krok 3

Normalizing Flows / IKFlow, sieć która umie losować

Pomysł w jednym zdaniu: nauczmy sieć przekształcać losowy szum w poprawne odpowiedzi.

Analogia: kreatywny artysta dostaje plamy atramentu z butelki (czyli losowy szum), patrzy na nie i rysuje z nich konkretne obrazy. Każdy losowy układ plam → inny prawidłowy obraz. Im lepszy artysta, tym ciekawsze i bardziej różnorodne wyniki.

IKFlow (Ames et al., 2022) jest takim artystą, siecią neuronową, która zamienia szum w poprawne kąty robota:

IKFlow: sieć uczy się odwracać losowy szum w poprawne rozwiązania IKz ~ N(0, I)gaussowski szumsieć IKFlowg_θ(z; T)(warunkowa na pozie T)q = g_θ⁻¹(z; T)poprawne rozwiązania IKshoulder Rshoulder L

Po lewej, chmurka punktów z prostego gaussowskiego szumu (każdy punkt to losowy 6-wymiarowy wektor z rozkładu normalnego). Po prawej, te same punkty po przejściu przez sieć IKFlow: wszystkie spadły do jednego z wyraźnych klastrów, każdy klaster odpowiada jednej gałęzi rozwiązania IK (shoulder R i shoulder L). Sieć „wie", którą gałąź ma trafić każdy konkretny punkt szumu, bo jest warunkowa na pozie TT.

Praktyczne użycie:

  1. Wylosuj zN(0,I)z \sim \mathcal{N}(0, I), zwykły gaussowski wektor 6-wymiarowy.
  2. Podaj parę (zz, TT) do sieci.
  3. Sieć zwraca q=gθ1(z;T)q = g_\theta^{-1}(z; T), jedną z gałęzi rozwiązania.
  4. Powtórz z innym zz, dostaniesz inną gałąź.

Siła tego podejścia: jedna sieć, dowolnie wiele różnych poprawnych rozwiązań. Wyniki publikowane (KUKA, Baxter, Atlas): próbkowanie w pojedynczych ms, błąd pozycji rzędu mm.

Konkretny przykład, manipulator 2R

Weźmy najprostszego robota, na którym można zobaczyć IKFlow w akcji: planarne ramię z dwoma ogniwami obrotowymi (dwa segmenty o długości 1, sterowane kątami q1,q2q_1, q_2). Cel, czerwona kropka, możemy osiągnąć na dwa sposoby: elbow up (łokieć w górę) albo elbow down (łokieć w dół).

Niżej: dwanaście niezależnych zapytań do (symulowanej) sieci IKFlow. Dla każdego losujemy 2-wymiarowy gaussowski szum, sieć przekształca go w parę kątów. Naciśnij wylosuj, zobaczysz, że część sampli daje rozwiązanie „elbow up" (zielone), część, „elbow down" (fioletowe). Wszystkie trafiają końcówką w czerwoną kropkę:

seed = 10 elbow up · 0 elbow down

Cel TCP (x, y) = (1.2, 0.7), czerwona kropka. Każdy mały robot poniżej to jeden sample z (uproszczonej) sieci IKFlow: bierzemy losowy gaussowski szum z, „sieć" przekształca go w parę kątów (q₁, q₂). Wszystkie roboty trafiają w ten sam cel, ale używają różnych gałęzi rozwiązania.

⚠ Uwaga: w tym demie „sieć" to skrót, używamy znaku z₁ żeby przypisać gałąź. Prawdziwa wytrenowana sieć IKFlow uczy się tych granic sama z danych. Czytaj wyjaśnienie pod demem.

To jest cała magia normalizing flow w jednym demie: jedna sieć, jedno wywołanie, ale za każdym razem inna poprawna gałąź. Z 8 gałęzi Pumy zrobiłoby się analogicznie 8 klastrów; tu mamy 2 (bo robot 2R ma tylko dwa rozwiązania). Każde losowanie z gaussa to jeden „zaczerpnięty z kapelusza" kandydat.

Praktyczne zastosowanie: w planowaniu ruchu robot sięga po przedmiot. Jeden klaster może być zablokowany kolizją z ścianą, dzięki IKFlow generujemy dziesięć kandydatów, sprawdzamy kolizje i wybieramy ten, który przejdzie. Algorytm nie musi „wiedzieć" o ścianie a priori, wystarczy że po prostu produkuje różnorodne rozwiązania.

Uczciwie, co upraszcza powyższe demo?

Mogłeś zauważyć, że w demie powyżej znak z1z_1 bezpośrednio decyduje o gałęzi: z[0] > 0 ? "up" : "down". Wygląda to jak gdybym z góry „kazał" sieci wybrać konkretne rozwiązanie. Tak, w demie tak jest. Symuluję jedynie efekt już wytrenowanej sieci, bez całego treningu.

Prawdziwa sieć IKFlow działa inaczej:

  1. Nikt jej z góry nie mówi „lewy obszar szumu prowadzi do elbow up, prawy do elbow down". Sieć ma wyjść z tym sama.
  2. Trening: sieć dostaje miliony par (T,q)(T, q) z datasetu (przez FK z losowych konfiguracji robota). W każdym kroku optymalizator przesuwa wagi tak, żeby rozkład wyjść sieci dla danej pozy TT pasował do rozkładu rzeczywistych qq w danych. Mówiąc dokładniej: minimalizujemy negatywny log-likelihood obserwowanych qq przy danym TT.
  3. Co z tego wynika geometrycznie: po treningu w przestrzeni szumu Rn\mathbb{R}^n wyłaniają się regiony. Każdy region trafia (po przejściu przez sieć) do jednej z gałęzi rozwiązania. Granica między regionami jest gładka i, kluczowe, zależy od pozy TT. Ten sam punkt szumu z=(0.3,0.7)z = (0.3, -0.7) dla pozy T1T_1 może trafić do elbow up, a dla pozy T2T_2, do elbow down.
  4. Coupling layers (warstwy odwracalne) to techniczny trick, dzięki któremu sieć jest matematycznie odwracalna i ma policzalny jakobian. Pozwala to wytrenować ją przez maximum likelihood (potrzebujemy logp(qT)\log p(q|T), co przy odwracalnym mapowaniu liczy się jawnie).
  5. Proporcje gałęzi również wynikają z treningu. W danych mamy ~50% przykładów z elbow up i ~50% z elbow down (dla pozycji w obszarze, gdzie istnieją obie). Sieć dopasowuje wielkość regionów w przestrzeni szumu tak, żeby częstość trafień odpowiadała częstości w danych.

Inaczej mówiąc: nie programujemy podziału. Podział wyłania się jako efekt uboczny minimalizacji błędu na danych. Sieć „sama odkrywa", że czasem trzeba dwóch rozwiązań, czasem ośmiu, bo dane treningowe ją do tego zmuszają.

Dlaczego nie zrobiłem prawdziwego IKFlow w demie? Wymagałby wytrenowania sieci z coupling layers (~kilkaset linii kodu + kilkanaście minut treningu na GPU + przygotowane dane). W naszym module pokazujemy ideę, efekt, który student powinien zrozumieć, bez angażowania pełnej infrastruktury ML. Naiwny MLP w sekcji „Laboratorium" niżej jest natomiast prawdziwy i trenujemy go od zera w przeglądarce.

Magia matematyczna w środku, żeby sieć była odwracalna i żeby umiała przekształcać dowolny rozkład w inny, używa się specjalnych warstw (coupling layers) z obliczalnym wyznacznikiem jakobianu. Szczegóły są dla zaawansowanych, tu wystarczy intuicja: sieć uczy się gładkiego, odwracalnego mapowania szum ↔ rozwiązania.

Implementacja IKFlow wymaga GPU i bibliotek typu FrEIA albo nflows, w naszej aplikacji pokazujemy ideę, nie pełny model. Literatura: Ames, Limb & Srinivasa, „IKFlow: Generating Diverse Inverse Kinematics Solutions", IROS 2022.

Krok 4

Diffusion models, odzyskiwanie odpowiedzi z szumu

Pomysł w jednym zdaniu: zacznij od czystego szumu i stopniowo go „odszumiaj" w wiele małych kroków, aż wyłoni się prawidłowa odpowiedź.

Analogia: wyobraź sobie zaszumione, prawie nieczytelne zdjęcie. Aplikacja w telefonie powoli usuwa ziarno, krok po kroku obraz staje się wyraźniejszy. Po 50 krokach widać twarz. Diffusion models robią to samo, tylko zamiast obrazu odzyskują kąty robota.

Przesuń poniższy slider od 0 do 50. Zobaczysz, jak losowe punkty (szum) stopniowo przesuwają się ku swoim klastrom (rozwiązania IK):

krok dyfuzji:0/50

Krok 0: czysty losowy szum. Sieć dostaje te kropki na wejściu.

Diffusion: krok po kroku usuwamy szum, aż wyłonią się prawidłowe qq

Krok 0: czysty szum, kropki rozproszone wszędzie. Krok 50: kropki uformowały dwa wyraźne klastry, to są dwie gałęzie rozwiązania. Sieć diffusion, w każdym z 50 kroków, robi tylko jedno: zgaduje, jak trochę przesunąć każdy punkt, żeby było mniej szumu. Dziesiątki kolejnych takich małych kroków sumują się w pełny ruch z szumu do prawdziwej odpowiedzi.

Konkretny przykład, manipulator 2R z animacją

Trochę bardziej namacalna wersja, sześć egzemplarzy tego samego robota 2R (dwa ogniwa obrotowe). Każdy startuje z innego losowego ułożenia (czysty szum w kątach q1,q2q_1, q_2). Slider 0 → 50 to kroki dyfuzji. W każdym kroku model robi mały „krok odszumiania", kąty zbliżają się do jednej z dwóch poprawnych konfiguracji.

krok dyfuzji:0/50

Krok 0: czysty losowy szum. Każdy z sześciu robotów ma losowe (q₁, q₂), koniec ramienia jest gdzieś w przestrzeni, ale nie na celu.

Przesuń slider od 0 do 50 i obserwuj. Krok 0: każdy robot leży inaczej, końcówki rozproszone losowo, kolory blade (model nie wie jeszcze, w którą stronę pójdzie). Mniej więcej przy kroku 20–30 widać, że pewne roboty już idą w stronę elbow up (zielone), a inne, elbow down (fioletowe). Krok 50: wszystkie sześć trafiło końcówką w czerwoną kropkę.

Kluczowa obserwacja: diffusion nie zna celu z góry, tylko przez wiele małych kroków „szlifuje" odpowiedź. To jest jak rzeźba odsłaniana z bryły kamienia: każde uderzenie dłutem usuwa odrobinę zbędnego materiału. Po dziesiątkach uderzeń wyłania się postać.

Dla Pumy z 8 gałęziami wyglądałoby to identycznie, tylko z sześcioma kątami zamiast dwóch i ośmioma możliwymi „celami" zamiast dwóch. Czas inferencji: 50 forward passów × ~0.3 ms = 15 ms na zapytanie, wolniejsze niż IKFlow, ale wciąż w czasie rzeczywistym.

Plusy:

  • Bardzo wyraziste, radzą sobie z niezwykle skomplikowanymi rozkładami (multi-modalność wszelkiego rodzaju).
  • Stabilny trening, łatwiej niż MDN czy GAN-y.
  • State-of-the-art w generatywnym modelowaniu obrazów (DALL·E 2, Stable Diffusion), wideo (Sora) i robotyce (planowanie ruchu).

Minusy:

  • Sampling jest iteracyjny, ~50 forward passów na jedną odpowiedź. Pojedyncze IK trwa kilkanaście milisekund (vs ~mikrosekund dla IKFlow).
  • Dla zwykłego IK to zbyt drogie, IKFlow wystarcza.
  • Diffusion „odgrywa swoje" w planowaniu trajektorii, gdzie generujemy całą sekwencję ruchów q1:Tq_{1:T} naraz, wtedy iteracyjny sampling przestaje być wadą.

Literatura: Janner et al. „Planning with Diffusion", ICML 2022; Pearce et al. „Imitating Human Behaviour with Diffusion Models", ICLR 2023.

Laboratorium, MLP od zera

Trenujemy najprostszą sieć MLP w czystym TypeScripcie, bez zewnętrznych bibliotek ML. Cała implementacja (~200 linii kodu) w src/lib/ml/mlp.ts: forward pass, backpropagation, optymalizator Adam. Po treningu oceniamy predykcję na bieżącej pozie TT^* i porównujemy z wynikiem hybrydy NN → DLS.

Konfiguracja przegubów

θ₁2.8°
θ₂-77.7°
θ₃6.8°
θ₄8.5°
θ₅-19.3°
θ₆172.0°

Poza efektora (T₀⁶)

Pozycja [m]
x = 0.5000
y = 0.1500
z = 0.3000
Orientacja RPY [°]
R = 0.00
P = 90.00
Y = 0.00

Poza docelowa T*

Pozycja [m]
Orientacja RPY [°]

Hiperparametry treningu

Krótka ściągawka, która metoda do czego?

MetodaIdea w jednym zdaniuKiedy używać
Naiwny MLPSieć zwraca jedną odpowiedźGdy potrzebujesz tylko warm startu (potem dopinanie DLS-em)
MDNSieć zwraca rozkład gaussowski (kilka „garbów")Gdy chcesz znać wszystkie warianty + ich prawdopodobieństwa
IKFlowSieć przekształca szum w poprawne odpowiedziStandard nowoczesnego learning-based IK; szybkie, multi-modalne
DiffusionStopniowe odszumianie szumu w odpowiedźPlanowanie trajektorii; gdy IKFlow nie radzi sobie z trudnymi rozkładami

Praktyczne wnioski

  • Naiwny MLP sam w sobie jest edukacyjny, nie produkcyjny, błąd pozycji 102\sim 10^{-2} m po krótkim treningu. W praktyce nie używa się go samodzielnie.
  • Hybryda NN → klasyczny solver, łączy szybkość wnioskowania sieci z dokładnością iteracji. Warm start często zmienia trudne przypadki DLS w trywialne.
  • MDN / IKFlow, niezbędne, jeśli zależy nam na różnorodności rozwiązań (np. planowanie sięgania w ciasnych przestrzeniach, gdzie jedno rozwiązanie może być zablokowane kolizją).
  • Trening, jakość sieci w IK silnie zależy od jakości datasetu. Losowe konfiguracje qq dają pokrycie konfiguracji, ale nierównomierne pokrycie przestrzeniSE(3)SE(3). Profesjonalne podejścia uzupełniają: próbkowanie warstwowe, importance sampling, augmentacja syntetyczna (trajektorie, kolizje).

Limitacja modułu, co byłoby w wersji produkcyjnej

Moduł pokazuje trenowalnego MLP w przeglądarce bez GPU. W realnej dydaktyce dodatkowo:

  • Zbiór ewaluacyjny (holdout) z osobnych poz; mierzona success rate, nie tylko MSE.
  • Porównanie z IKFlow jako golden baseline (mały wstępnie wytrenowany model w ONNX, uruchamiany przez ONNX Runtime Web).
  • Trening architektur alternatywnych (transformer w wejściu poz, rezydualne bloki).