CI/CD/ML
480
08_ci_cd_uczenie_maszynowe.ipynb
Normal file
@ -0,0 +1,480 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
|
||||
"<div class=\"alert alert-block alert-info\">\n",
|
||||
"<h1> Przygotowanie do projektu badawczo-rozwojowego</h1>\n",
|
||||
"<h2> 8. <i>Ciągła integracja i ewaluacja w projektach opartych na uczeniu maszynowym </i>[wykład]</h2> \n",
|
||||
"<h3>Filip Graliński (2021)</h3>\n",
|
||||
"</div>\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"
|
||||
]
|
||||
}
|
||||
],
|
||||
"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
|
||||
}
|
BIN
obrazy/cd.drawio.png
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
obrazy/ci.drawio.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
obrazy/gonito-platform.png
Normal file
After Width: | Height: | Size: 131 KiB |
BIN
obrazy/meta-eval.png
Normal file
After Width: | Height: | Size: 126 KiB |
BIN
obrazy/mlops.drawio.png
Normal file
After Width: | Height: | Size: 107 KiB |
BIN
obrazy/mlops2.drawio.png
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
obrazy/seul-metro.png
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
obrazy/utility.jpg
Normal file
After Width: | Height: | Size: 20 KiB |