{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n", "
\n", "

Przygotowanie do projektu badawczo-rozwojowego

\n", "

8. Ciągła integracja i ewaluacja w projektach opartych na uczeniu maszynowym [wykład]

\n", "

Filip Graliński (2022)

\n", "
\n", "\n", "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ciągła integracja i ewaluacja w projektach opartych na uczeniu maszynowym" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Dobre praktyki w tradycyjnej inżynierii oprogramowania\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Ciągła integracja\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ciągła integracja (*continuous integration*, *CI*) to praktyka\n", "stosowana w tworzeniu oprogramowania polegają na częstym integrowaniu\n", "kodu opracowywanego przez programistów, zautomatyzowanym budowaniu\n", "oprogramowania i poddawaniu go testom.\n", "\n", "![img](./obrazy/ci.drawio.png \"Schemat procesu ciągłej integracji\")\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Ciągłe wdrażanie\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ciągłe wdrażanie (*continuous deployment*, *CD*)\n", "automatyzuje również proces wdrażania oprogramowania. Oznacza to, że\n", "również procedura wdrażania musi zostać wyrażona jako kod\n", "przechowywany w systemie kontroli wersji.\n", "\n", "![img](./obrazy/cd.drawio.png \"Schemat procesu ciągłego wdrażania\")\n", "\n", "Ciągła integracja/ciągłe wdrożenie zazwyczaj współwystępuje z metodyką **DevOps**.\n", "\n", "CI/CD/DevOps w jednym zdaniu: robię to tak często, że to „nic takiego”.\n", "\n", "![img](./obrazy/seul-metro.png \"Przykład — budowa metra, źródło Wikipedia\")\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### CI/CD a uczenie maszynowe\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dodanie do systemu modułów opartych na uczeniu maszynowym bardzo\n", "komplikuje proces CI/CD:\n", "\n", "- modele uczenia maszynowego (np. sieci neuronowe) powstają na bazie kodu źródłowego odpowiedzialnego za uczenie **i** danych uczących,\n", "- osobny kod jest odpowiedzialny za inferencję,\n", "- choć kod odpowiedzialny za uczenie i inferencję w miarę możliwości powinny podlegać standardowej metodologii testowania (np. testy jednostkowe), to ostatecznie testy systemów opartych na uczeniu maszynowym nie mają postaci zerojedynkowej\n", "- … raczej system może uzyskać lepszy albo gorszy wynik,\n", "- wdrożenie (a przynajmniej uczenie) wymaga często dużych zasobów obliczeniowych i specjalnego sprzętu (karty graficzne).\n", "\n", "Przy czym chcielibyśmy zachować „złote” zasady CI/CD.\n", "\n", "Wprowadzenie uczenia maszynowego do oprogramowania na tyle zmienia\n", "sytuację, że mówi się o **MLOps** zamiast DevOps.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Proces CI/CD rozszerzony o uczenie maszynowe\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![img](./obrazy/mlops.drawio.png \"Schemat CI/CD rozszerzony o MLOps\")\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Testowanie systemów opartych na uczeniu maszynowym\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podobnie jak w wypadku tradycyjnego oprogramowania testowanie modeli\n", "uczenia maszynowego przyjmuje wiele form:\n", "\n", "- testy jednostkowe fragmentu kodu odpowiedzialnego za uczenie i inferencję,\n", "- testy uczenia i inferencji na spreparowanych danych\n", " - *corner cases*\n", " - uczenia „w kółko” na jednym przykładzie (czy funkcja kosztu spada do zera?)\n", "- testy inferencji na danych „śmieciowych” (czy system jest w stanie „przetrwać” wszystko?)\n", "- testy efektywności, przepustowości itp.\n", "- … lecz ostatecznie najistotniejsza jest odpowiedź na pytanie, jak dobry jest wynik na danych zbliżonych do rzeczywistych (**ewaluacja**)\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ewaluacja\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Rodzaje ewaluacji:\n", "\n", "- testy „na ludziach”,\n", " - testy A/B, analiza zachowania użytkownika\n", " - ewaluacja **manualna**, np. test MOS (*mean-opinion score*)\n", "- ewaluacja **automatyczna**\n", " - ewaluacja według wzoru\n", " - ewaluacja wyuczana przy użyciu uczenia maszynowego (!)\n", "\n", "Ostateczne kryterium ewaluacji: *money in the bank*, a właściwie\n", "*utility in the bank* (por. aksjomatyczna teoria użyteczności\n", "sformułowana przez Johna von Neumanna i Oskara Morgensterna).\n", "\n", "![img](./obrazy/utility.jpg \"Okładka książki „Theory of Games and Economic Behaviour”\")\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Psychologiczne pułapki oceniania\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- efekt **pierwszeństwa** — *błędy pojawiające się na początku wypracowania oceniane są surowiej niż błędy na końcu wypracowania*\n", "\n", "- efekt **świeżości**\n", "\n", "- efekt „aureoli” — *mamy skłonność do przypisywania innych pozytywnych cech ludziom atrakcyjnym fizycznie*\n", "\n", "- wpływ **nastroju** na ocenianie — *w pochmurne dni ludzie gorzej oceniają stan gospodarki niż w słoneczne*\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Słabości „potocznej” matematyki\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Czy symptom świadczy o chorobie?\n", "\n", " | | | choroba | |\n", " | | | obecna | nieobecna |\n", " |---------+-----------+---------+---------------|\n", " | symptom | obecny | 37 | 33 |\n", " | | nieobecny | 17 | 13 |\n", "\n", "85% przepytanych pielęgniarek doszło do wniosku, że istnieje związek między symptomem a chorobą.\n", "\n", "**Korelacja** jest przez ludzi przeceniana, **regresja do średniej** — niedoceniania\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Jak uniknąć pułapek oceniania?\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- stosować obiektywne miary,\n", "- najlepiej wymyślić syntetyczną funkcję oceny (pojedyncza liczba),\n", "- jeśli to możliwe, stosować automatyczną ewaluację.\n", "\n", "Konkretny sposób ewaluacji nazywamy **miarą** lub **metryką** ewaluacji.\n", "(Uwaga: nie ma nic wspólnego z terminami stosowanymi w matematyce!).\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Definicja metryki ewaluacji\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ewaluację przeprowadzamy na ciągu danych wejściowych $(x)_i$ biorąc\n", "pod uwagę oczekiwane wyjście $(y)_i$ i rzeczywiste wyjście z systemu\n", "$(\\hat{y})_i$. Funkcja (metryka, miara) ewaluacji $\\mu$ powinna\n", "zwrócić skalarną wartość określającą jakość systemu, innymi słowy:\n", "\n", "$$\\mu \\colon X^{n} \\times Y^{n} \\times \\hat{Y}^{n} \\to \\mathcal{R},$$\n", "\n", "gdzie $X$ jest zbiorem możliwych wejść, $Y$ — zbiorem możliwych\n", "specyfikacji oczekiwanych wyjść, $\\hat{Y}$ — zbiorem możliwych wyjść\n", "(na ogół $Y = \\hat{Y}$, ale mogą być sytuacje, gdzie specyfikacja\n", "oczekiwanego wyjścia jest bardziej skomplikowana).\n", "\n", "Olbrzymia większość metryk ewaluacji nie bierze pod uwagę wejścia,\n", "lecz jedynie porównuje wyjście z systemu z oczekiwanym wyjściem, a zatem schemat upraszcza się do:\n", "\n", "$$\\mu \\colon Y^{n} \\times \\hat{Y}^{n} \\to \\mathcal{R}.$$\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Metryka ewaluacji — przykłady\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Jedną z najprostszych metryk ewaluacji jest **dokładność** (*accuracy*)\n", "jest to po prostu odsetek przypadków, gdy wyjście z systemu jest identyczne z oczekiwanym wyjściem.\n", "\n", "Narzędzie ewaluacyjne GEval ma zaimplementowane kilkadziesiąt (!) metryk ewaluacji\n", "\n", " -m,--metric METRIC Metric to be used, e.g.:RMSE, MSE, MAE, SMAPE,\n", " Pearson, Spearman, Accuracy, LogLoss, Likelihood,\n", " F1.0, F2.0, F0.25, Macro-F1.0, Macro-F2.0,\n", " Macro-F0.25, MultiLabel-F1.0, MultiLabel-F2.0,\n", " MultiLabel-F0.25, Mean/MultiLabel-F1.0,\n", " Probabilistic-MultiLabel-F1.0,\n", " Probabilistic-MultiLabel-F2.0,\n", " Probabilistic-MultiLabel-F0.25,\n", " MultiLabel-Likelihood, MAP, NDCG@3, BLEU, GLEU\n", " (\"Google GLEU\" not the grammar correction metric),\n", " WER, CER (Character-Error Rate), WAR, CAR\n", " (Character-Accuracy Rate (1-CER)), NMI, ClippEU,\n", " LogLossHashed, LikelihoodHashed, PerplexityHashed,\n", " BIO-F1, BIO-Weighted-F1, BIO-F1-Labels,\n", " TokenAccuracy, SegmentAccuracy, Soft-F1.0, Soft-F2.0,\n", " Soft-F0.25, Probabilistic-Soft-F1.0,\n", " Probabilistic-Soft-F2.0, Probabilistic-Soft-F0.25,\n", " Probabilistic-Soft2D-F1.0, Probabilistic-Soft2D-F2.0,\n", " Probabilistic-Soft2D-F0.25, Soft2D-F1.0, Soft2D-F2.0,\n", " Soft2D-F0.25, Haversine, CharMatch, Improvement@0.5,\n", " MacroAvg/Likelihood, MSE-Against-Interval,\n", " RMSE-Against-Interval, MAE-Against-Interval,\n", " BLEU:lm<\\s+|[a-z0-9]+> (BLEU on lowercased strings,\n", " only Latin characters and digits considered)\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Jakie własności ma dobra miara ewaluacji?\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- spełnia zdroworozsądkowe aksjomaty\n", " - w szczególności dla przypadków brzegowych\n", " - jest stabilna\n", "\n", "- koreluje z ludzką oceną\n", " - a tak naprawdę z preferencjami użytkowników\n", "\n", "Ewaluacja ewaluacji! — czyli **metaewaluacja**\n", "\n", "![img](./obrazy/meta-eval.png \"Fragment artykułu o metaewaluacji\")\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Z powrotem do CI/CD\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ewaluację można zatem traktować jako rozszerzenie procesu testowania oprogramowania.\n", "Ewaluacja nigdy nie powinna być jednorazowym procesem, powinna być wpleciona w proces CI/CD.\n", "Możemy więc mówić o **ciągłej ewaluacji**.\n", "\n", "Potrzeba ciągłego procesu, by upewnić się, że nasz system oparty na uczeniu maszynowym:\n", "\n", "- jest lepszy od prostego punktu odniesienia (*naive baseline*),\n", "- jest lepszy od rozwiązań konkurencji,\n", "- jest lepszy od systemu, który mieliśmy wczoraj, tydzień temu, rok temu…\n", "\n", "![img](./obrazy/mlops2.drawio.png \"Schemat MLOps rozszerzony o ciągłą ewaluację\")\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Dobór metryki ewaluacji — tłumaczenie maszynowe\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Jaka metryka jest najlepsza do oceny systemu tłumaczenia maszynowego?\n", "\n", "To zależy!\n", "\n", "**Scanariusz A**. Automatyczne tłumaczenie jest używane przez osoby\n", "nieznające języka docelowego w celu zrozumienia oryginalnego tekstu.\n", "\n", "**Scenariusz B**. Oczekujemy bardzo dobrej jakości tłumaczenia.\n", "Tłumaczenia maszynowe są poprawiane przez profesjonalnych tłumaczy,\n", "tłumaczenie maszynowe służy do przyspieszenia procesu.\n", "\n", "W scenariuszu A można zastosować standardowe metryki tłumaczenia\n", "maszynowego sprawdzające, na ile w tłumaczeniu zachowane elementy\n", "tłumaczenia referencyjnego, np. BLEU albo — lepiej — COMET, natomiast\n", "w scenariuszu B lepiej zastosować odległość edycyjną w celu\n", "oszacowania kosztu korekty.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Przykład systemu ewaluacji — GEval i Gonito\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[GEval](https://gitlab.com/filipg/geval) to biblioteka w języku Haskell oraz narzędzie do ewaluacji uruchamiane z wiersza\n", "poleceń, zaś [Gonito](https://gitlab.com/filipg/gonito) to oparta na bibliotece GEval aplikacja webowa, platforma do ewaluacji wyzwań\n", "uczenia maszynowego.\n", "\n", "![img](./obrazy/gonito-platform.png \"Schemat platformy Gonito\")\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### System na produkcji, a my nie znamy oczekiwanych wartości!\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Estymacja jakości\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Uruchomiliśmy nasz system w wersji produkcyjnej, skąd wiemy, że system\n", "zachowuje się poprawnie?\n", "\n", "Można anotować lub poprawiać manualnie próbki danych produkcyjnych,\n", "rozszerzać w ten sposób zbiory testowe i dokonywać na nich ewaluacji.\n", "\n", "Można też stosować metody **estymacji jakości** (*quality estimation*),\n", "tzn. przewidywać jakość wyłącznie na podstawie wyjścia (bez znajomości\n", "oczekiwanego wyjścia). Na przykład w systemie tłumaczenia maszynowego\n", "można w tym celu stosować model języka docelowego.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Zadania proponowane na laboratoria\n", "\n", "### Zadanie 1.\n", "\n", "Skonfigurujcie minimalne zadanie uczenia maszynowego na dowolnym serwerze ciągłej integracji (Jenkins, GitLabCI, GitHub Actions itp.). Zadanie powinno obejmować wyuczenie prostego modelu i ewaluację.\n", "\n", "### Zadanie 2.\n", "\n", "Dokonajcie konwersji wybranego zbioru danych do standardu wyzwania [Gonito](https://gitlab.com/filipg/gonito). Zob. [szczegółowe instrukcje odnośnie do tworzenia wyzwania](https://gitlab.com/filipg/geval#preparing-a-gonito-challenge).\n", "\n", "### Zadanie 3.\n", "\n", "Dopiszcie nowe przypadki testowe dla wybranej metryki ewaluacji w programie [GEval](https://gitlab.com/filipg/geval). Zob. [przykład testów dla nowej metryki](https://gitlab.com/filipg/geval/-/commit/819fbecedc6f744a1a08f21c11067191837f87a2) (od pliku `test/Spec.hs`).\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.8" }, "org": null }, "nbformat": 4, "nbformat_minor": 1 }