Algorytmy genetyczne: jak ewolucja rozwiązuje trudne problemy

Ewolucja stworzyła oko, skrzydło i układ odpornościowy bez żadnego projektanta kierującego procesem. Algorytmy genetyczne zapożyczają ten trik — kodując kandydujące rozwiązania jako cyfrowe chromosomy i pozwalając selekcji, krzyżowaniu i mutacji przeszukiwać ogromne przestrzenie, w których przeszukiwanie brute-force byłoby obliczeniowo beznadziejne.

Ewolucja jako optymalizacja

W 1975 roku informatyk John Holland opublikował pracę Adaptation in Natural and Artificial Systems, kładąc teoretyczne podwaliny algorytmów genetycznych. Jego kluczowa spostrzeżenie było eleganckie: dobór naturalny jest algorytmem przeszukiwania. Ewolucja nie podąża za planem ani gradientem — utrzymuje populację kandydujących rozwiązań, testuje każde wobec środowiska i pozwala rozmnażać się najlepszym, podczas gdy reszta wymiera. Z pokolenia na pokolenie ten ślepy proces znajduje niezwykle wyrafinowane rozwiązania niezwykle złożonych problemów.

Paralela do optymalizacji komputerowej jest bezpośrednia. Zdefiniuj funkcję przystosowania — miarę tego, jak dobre jest dane rozwiązanie. Zacznij od losowej populacji kandydujących rozwiązań. Wielokrotnie wybieraj lepiej przystosowane osobniki do rozmnażania, łącz ich „materiał genetyczny", wprowadzaj okazjonalne losowe zmiany i oceniaj nowe pokolenie. Powtarzaj, aż pojawi się wystarczająco dobre rozwiązanie.

Pochodna nie jest potrzebna. Gładki krajobraz nie jest zakładany. Wcześniejsza wiedza o strukturze rozwiązania nie jest wymagana. Algorytm przeszukuje, próbując różnych rzeczy, zachowując to, co działa, i odrzucając to, co nie działa — dokładnie tak samo, jak cztery miliardy lat ewolucji biologicznej wytworzyły różnorodność życia na Ziemi.

Kodowanie rozwiązań jako chromosomów

Zanim ewolucja może zadziałać na jakimś problemie, problem ten musi zostać przetłumaczony na formę, na której ewolucja może działać. W ewolucji biologicznej chromosom to sekwencja nukleotydów kodująca instrukcje budowy organizmu. W algorytmach genetycznych chromosom to ciąg bitów, liczb lub symboli kodujący kandydujące rozwiązanie.

Wybór kodowania nie jest trywialny — dramatycznie kształtuje to, co algorytm może znaleźć i jak szybko to znajduje. Rozważmy problem komiwojażera: mając listę miast, znajdź najkrótszą trasę odwiedzającą każde z nich dokładnie raz i wracającą do punktu startu. Naturalnym kodowaniem jest permutacja indeksów miast — dla pięciu miast chromosom mógłby wyglądać jak [3, 1, 4, 2, 5], co oznacza „odwiedź miasto 3, potem 1, potem 4, potem 2, potem 5". Funkcja przystosowania jest po prostu odwrotnością całkowitej długości trasy: krótsze trasy mają wyższe przystosowanie.

Inne style kodowania pasują do innych problemów. Problemy optymalizacji ciągłej często wykorzystują chromosomy o wartościach rzeczywistych. Architektury sieci neuronowych można zakodować jako ciągi określające rozmiary warstw i wzorce połączeń. Problemy harmonogramowania kodują chromosomy jako uporządkowane listy zadań. W każdym przypadku kodowanie musi umożliwiać sensowną rekombinację — mieszanie dwóch dobrych rozwiązań powinno mieć rozsądną szansę na wytworzenie kolejnego dobrego rozwiązania, a nie losowego szumu.

Operatory genetyczne

Poszukiwanie ewolucyjne napędzają trzy operacje:

Razem te trzy operatory realizują przeszukiwanie równoległe: cała populacja jednocześnie eksploruje przestrzeń rozwiązań, a informacja o dobrych obszarach jest przekazywana przez krzyżowanie w każdym pokoleniu.

Zbieżność i różnorodność

Centralne napięcie w każdym algorytmie genetycznym to eksploracja kontra eksploatacja. Populacja, która zbiega się zbyt szybko — wszystkie osobniki stają się niemal identyczne — utyka w tym lokalnym optimum, które znalazła jako pierwsze, nie mogąc odkryć lepszych rozwiązań gdzie indziej w przestrzeni przeszukiwania. Nazywa się to przedwczesną zbieżnością i jest to najczęstszy tryb awarii algorytmów genetycznych.

Kilka technik pomaga utrzymać różnorodność. Dzielenie przystosowania (fitness sharing) karze osobniki zbyt podobne do innych w populacji, rozprzestrzeniając poszukiwanie na wiele szczytów w krajobrazie przystosowania. Modele wyspowe uruchamiają kilka subpopulacji równolegle z okazjonalną migracją między nimi — każda wyspa może zbiegać niezależnie, ale migranci zapobiegają całkowitej izolacji. Niszowanie jawnie rezerwuje w populacji miejsce dla rozwiązań z różnych obszarów przestrzeni przeszukiwania.

Właściwa równowaga zależy od problemu. Dla problemów z pojedynczym globalnym optimum w stosunkowo gładkim krajobrazie dobrze sprawdza się agresywna selekcja i niska mutacja. Dla silnie multimodalnych problemów z wieloma lokalnymi optimami o podobnym przystosowaniu utrzymanie różnorodności ma kluczowe znaczenie — celem jest zmapowanie krajobrazu, a nie tylko wspinaczka na najbliższe wzgórze.

Zobacz, jak populacje ewoluują w czasie rzeczywistym: nasz Symulator ewolucyjnej teorii gier pozwala zasiać populację różnymi strategiami i obserwować dobór naturalny — współpracę, zdradę i wszystko pomiędzy — rozgrywający się na przestrzeni pokoleń. Dynamika zbieżności i różnorodności jest natychmiast widoczna.

Zastosowania w świecie rzeczywistym

Algorytmy genetyczne wytworzyły rozwiązania problemów inżynierskich, których ludzcy projektanci nie mogliby łatwo znaleźć — a w niektórych przypadkach nawet nie mogliby sobie wyobrazić:

Algorytmy genetyczne kontra inne metody optymalizacji

Algorytmy genetyczne nie zawsze są właściwym narzędziem. Spadek gradientowy — koń pociągowy uczenia maszynowego — jest znacznie szybszy, gdy krajobraz przystosowania jest gładki i różniczkowalny, ponieważ może bezpośrednio podążać za gradientem do lokalnego optimum. AG wymagają wielu ocen przystosowania i są wolniejsze w porównaniu z nim w problemach, gdzie zastosowanie ma rachunek różniczkowy.

Ale AG błyszczą w sytuacjach, gdzie metody gradientowe zawodzą:

Symulowane wyżarzanie rozwiązuje niektóre z tych samych problemów co AG — może uciekać z lokalnych optimów, okazjonalnie akceptując gorsze rozwiązania, z prawdopodobieństwem malejącym z czasem jak chłodzący się metal. Ale operuje na pojedynczym rozwiązaniu, a nie na populacji, tracąc przewagę przeszukiwania równoległego. Optymalizacja rojem cząstek wykorzystuje populację podobnie jak AG, ale aktualizuje rozwiązania za pomocą wektorów prędkości zamiast operatorów genetycznych, doskonale sprawdzając się w problemach optymalizacji ciągłej.

Trwałą lekcją algorytmów genetycznych nie jest to, że zawsze wygrywają — lecz to, że ewolucja jako algorytm jest znacznie bardziej ogólna i potężna, niż się wydaje. Mając jedynie funkcję przystosowania i wystarczająco dużo pokoleń, potrafi wspiąć się na góry złożoności, których żaden inżynier nie zdobyłby samodzielnie.

Najczęściej zadawane pytania

Czym jest algorytm genetyczny?

Algorytm genetyczny (AG) to technika optymalizacji i przeszukiwania inspirowana ewolucją biologiczną. Utrzymuje populację kandydujących rozwiązań, ocenia każde z nich za pomocą funkcji przystosowania, a następnie tworzy nowe pokolenia poprzez selekcję (faworyzując lepiej przystosowane osobniki), krzyżowanie (łączenie rozwiązań rodziców) i mutację (losowe zmiany). Z pokolenia na pokolenie populacja ewoluuje w kierunku lepszych rozwiązań.

Czym jest funkcja przystosowania?

Funkcja przystosowania ocenia, jak dobrze każde kandydujące rozwiązanie rozwiązuje problem. Przypisuje każdemu osobnikowi w populacji liczbowy wynik — wyższe przystosowanie oznacza lepsze rozwiązanie. Funkcja przystosowania koduje cel optymalizacji: dla problemu komiwojażera może to być ujemna łączna długość trasy; dla uczenia maszynowego — dokładność predykcji.

Czym jest krzyżowanie w algorytmach genetycznych?

Krzyżowanie (rekombinacja) łączy materiał genetyczny dwóch rodzicielskich rozwiązań, by wytworzyć potomstwo. W krzyżowaniu jednopunktowym losowy punkt podziału dzieli chromosom każdego z rodziców; potomek otrzymuje pierwszą część od rodzica A, a drugą od rodzica B. Inne warianty obejmują krzyżowanie dwupunktowe, krzyżowanie jednorodne (każdy gen wybierany niezależnie od jednego z rodziców) oraz operatory specyficzne dla problemu przy kodowaniach strukturalnych.

Jak działa selekcja w algorytmach genetycznych?

Selekcja określa, które osobniki się rozmnażają. Popularne metody obejmują: selekcję turniejową (losowo wybiera się k osobników, rozmnaża się najlepiej przystosowany), selekcję metodą koła ruletki (prawdopodobieństwo proporcjonalne do przystosowania), selekcję rangową (prawdopodobieństwo oparte na randze przystosowania, a nie surowej wartości) oraz elityzm (najlepsze osobniki są zawsze zachowywane w następnym pokoleniu). Presja selekcyjna określa, jak szybko algorytm się zbiega.

Czym jest mutacja w algorytmach genetycznych i dlaczego jest ważna?

Mutacja losowo zmienia jeden lub więcej genów osobnika z niewielkim prawdopodobieństwem (zwykle 0,1–5%). Zapobiega przedwczesnej zbieżności do lokalnych optimów, wprowadzając nowy materiał genetyczny nieobecny w bieżącej populacji. Bez mutacji algorytm może eksplorować jedynie kombinacje istniejących wzorców i może na stałe utknąć w rozwiązaniach suboptymalnych.

Czym jest programowanie genetyczne i czym różni się od algorytmów genetycznych?

Programowanie genetyczne (PG) ewoluuje programy lub wyrażenia symboliczne (zwykle reprezentowane jako drzewa), a nie ciągi o stałej długości. Podczas gdy AG optymalizują ustalony zestaw parametrów, PG może odkryć strukturę rozwiązania — znaleźć formę równania, drzewa decyzyjnego lub programu. PG wykorzystywano do ponownego odkrywania praw fizyki i automatycznego projektowania obwodów elektronicznych.

Jakie są ograniczenia algorytmów genetycznych?

AG mają kilka ograniczeń: wymagają wielu ocen przystosowania (kosztowne przy wolnych symulacjach), kodowanie rozwiązania jako chromosomu jest nietrywialne dla złożonych problemów, mogą przedwcześnie zbiegać się do lokalnych optimów, dostrajanie hiperparametrów (rozmiar populacji, współczynnik mutacji, współczynnik krzyżowania) znacząco wpływa na wydajność, i nie dają gwarancji zbieżności, w przeciwieństwie do metod gradientowych dla problemów wypukłych.

Czym jest schemat w teorii algorytmów genetycznych?

Schemat (liczba mnoga: schematy) to szablon reprezentujący podzbiór chromosomów dzielących określone wartości na niektórych pozycjach. Twierdzenie o schematach (Holland, 1975) opisuje, jak krótkie schematy o ponadprzeciętnym przystosowaniu i niskim prawdopodobieństwie zakłócenia pozycyjnego rosną w częstości wykładniczo z pokolenia na pokolenie. Ta hipoteza bloków budulcowych wyjaśnia, dlaczego AG działają: krótkie wzorce o wysokim przystosowaniu łączą się, tworząc dłuższe, jeszcze lepiej przystosowane wzorce.

Jak algorytmy genetyczne wypadają w porównaniu ze spadkiem gradientowym?

Spadek gradientowy efektywnie optymalizuje gładkie, ciągłe, różniczkowalne funkcje, podążając za gradientem w dół. AG działają bez informacji o gradiencie, radząc sobie z nieróżniczkowalnymi, nieciągłymi lub zaszumionymi krajobrazami przystosowania, problemami kombinatorycznymi i funkcjami multimodalnymi. AG eksplorują szeroko (przeszukiwanie globalne), podczas gdy spadek gradientowy eksploatuje lokalnie. Podejścia hybrydowe łączą eksplorację AG z lokalnym dopracowaniem gradientowym.

Jakie są udane zastosowania algorytmów genetycznych w świecie rzeczywistym?

Godne uwagi zastosowania AG obejmują: wyewoluowane projekty anten NASA (nieregularne, ale bardzo wydajne kształty), optymalizację harmonogramów linii lotniczych i tras załóg, projektowanie cząsteczek leków i zwijanie białek, sztuczną inteligencję w grach (wyewoluowane strategie do Dooma, Tetrisa), przeszukiwanie architektury sieci neuronowych dla głębokiego uczenia, optymalizację portfela w finansach oraz projektowanie inżynierskie (łopatki turbin, optymalizację topologii konstrukcji).