Przemysłowe uczenie maszynowe: 10 zasad projektowania

Przemysłowe uczenie maszynowe: 10 zasad projektowania

W dzisiejszych czasach codziennie powstają nowe usługi, aplikacje i inne ważne programy, które pozwalają tworzyć niesamowite rzeczy: od oprogramowania do sterowania rakietą SpaceX po interakcję z czajnikiem w sąsiednim pokoju za pośrednictwem smartfona.

A czasami każdy początkujący programista, czy to zapalony startupowiec, czy zwykły Full Stack czy Data Scientist, prędzej czy później dochodzi do wniosku, że istnieją pewne zasady programowania i tworzenia oprogramowania, które znacznie ułatwiają życie.

W tym artykule opiszę pokrótce 10 zasad programowania przemysłowego uczenia maszynowego tak, aby można je było łatwo zintegrować z aplikacją/usługą, w oparciu o metodologię 12-czynnikowej aplikacji. zaproponowane przez zespół Heroku. Moją inicjatywą jest zwiększenie świadomości na temat tej techniki, co może pomóc wielu programistom i osobom zajmującym się data science.

Ten artykuł jest prologiem do serii artykułów na temat przemysłowego uczenia maszynowego. Opowiem w nich dalej jak faktycznie wykonać model i uruchomić go na produkcji, stworzyć dla niego API, a także przykłady z różnych dziedzin i firm, które mają wbudowane ML w swoich systemach.

Zasada 1: Jedna baza kodu

Niektórzy programiści na pierwszych etapach, z lenistwa (lub z własnego powodu), zapominają o Gicie. Albo zupełnie zapominają o tym słowie, czyli wrzucają sobie pliki na dysk/po prostu wrzucają SMS-y/wysyłają gołębiami, albo nie przemyślają swojego przepływu pracy i przydzielają każdemu do własnego oddziału, a potem do gospodarz.

Zasada ta stanowi: mieć jedną bazę kodu i wiele wdrożeń.

Git może znaleźć zastosowanie zarówno w produkcji, jak i w badaniach i rozwoju (R&D), w których nie jest wykorzystywany tak często.

Przykładowo na etapie R&D możesz pozostawić zatwierdzenia z różnymi metodami i modelami przetwarzania danych, aby następnie wybrać najlepszy i bez problemu kontynuować z nim dalszą pracę.

Po drugie, na produkcji jest to rzecz niezastąpiona - będziesz musiał stale patrzeć, jak zmienia się Twój kod i wiedzieć, który model dał najlepsze wyniki, który kod ostatecznie zadziałał i co się stało, że przestał działać lub zaczął dawać nieprawidłowe wyniki . Po to właśnie są commity!

Można też stworzyć paczkę swojego projektu, umieszczając ją np. na Gemfury, a potem po prostu importując z niej funkcje do innych projektów, żeby nie przepisywać ich 1000 razy, ale o tym później.

Zasada 2: Jasno deklaruj i izoluj zależności

Każdy projekt ma inne biblioteki, które importujesz z zewnątrz, aby je gdzieś zastosować. Niezależnie od tego, czy są to biblioteki Pythona, czy biblioteki innych języków o różnym przeznaczeniu, czy też narzędzia systemowe – Twoim zadaniem jest:

  • Jasno zadeklaruj zależności, czyli plik, który będzie zawierał wszystkie biblioteki, narzędzia i ich wersje, które są używane w Twoim projekcie i które muszą zostać zainstalowane (na przykład w Pythonie można to zrobić za pomocą Pipfile lub require.txt. A link, który pozwala dobrze zrozumieć: realpython.com/pipenv-guide)
  • Izoluj zależności specjalnie dla swojego programu podczas programowania. Nie chcesz ciągle zmieniać wersji i instalować na nowo np. Tensorflow?

Dzięki temu programiści, którzy w przyszłości dołączą do Twojego zespołu, będą mogli szybko zapoznać się z bibliotekami i ich wersjami używanymi w Twoim projekcie, a Ty będziesz miał także możliwość zarządzania wersjami i samymi bibliotekami zainstalowanymi dla konkretnego projektu, co pomoże Ci uniknąć niekompatybilności bibliotek lub ich wersji.

Twoja aplikacja nie powinna także opierać się na narzędziach systemowych, które mogą być zainstalowane na konkretnym systemie operacyjnym. Narzędzia te muszą być również zadeklarowane w manifeście zależności. Jest to konieczne, aby uniknąć sytuacji, w których wersja narzędzi (jak również ich dostępność) nie odpowiada narzędziom systemowym konkretnego systemu operacyjnego.

Zatem nawet jeśli curl może być używany na prawie wszystkich komputerach, nadal powinieneś zadeklarować go w zależnościach, ponieważ podczas migracji na inną platformę może go tam nie być lub wersja nie będzie ta, której pierwotnie potrzebowałeś.

Na przykład plik wymagania.txt może wyglądać następująco:

# Model Building Requirements
numpy>=1.18.1,<1.19.0
pandas>=0.25.3,<0.26.0
scikit-learn>=0.22.1,<0.23.0
joblib>=0.14.1,<0.15.0

# testing requirements
pytest>=5.3.2,<6.0.0

# packaging
setuptools>=41.4.0,<42.0.0
wheel>=0.33.6,<0.34.0

# fetching datasets
kaggle>=1.5.6,<1.6.0

Zasada 3: Konfiguracje

Wielu słyszało historie o różnych programistach, którzy przypadkowo przesłali kod do GitHuba do publicznych repozytoriów wraz z hasłami i innymi kluczami z AWS, a następnego dnia budzili się z długiem wynoszącym 6000 50000, a nawet XNUMX XNUMX dolarów.

Przemysłowe uczenie maszynowe: 10 zasad projektowania

Oczywiście są to przypadki ekstremalne, ale bardzo istotne. Jeśli przechowujesz w kodzie swoje dane uwierzytelniające lub inne dane potrzebne do konfiguracji, popełniasz błąd i myślę, że nie ma potrzeby wyjaśniać dlaczego.

Alternatywą jest przechowywanie konfiguracji w zmiennych środowiskowych. Możesz przeczytać więcej o zmiennych środowiskowych tutaj.

Przykłady danych, które są zwykle przechowywane w zmiennych środowiskowych:

  • Nazwy domen
  • Adresy URL/URI API
  • Klucze publiczne i prywatne
  • Kontakty (poczta, telefony itp.)

W ten sposób nie musisz ciągle zmieniać kodu, jeśli zmienią się zmienne konfiguracyjne. Pomoże Ci to zaoszczędzić czas, wysiłek i pieniądze.

Na przykład, jeśli używasz API Kaggle do przeprowadzania testów (na przykład pobierasz oprogramowanie i uruchamiasz przez nie model, aby podczas uruchamiania sprawdzić, czy model działa dobrze), wówczas klucze prywatne z Kaggle, takie jak KAGGLE_USERNAME i KAGGLE_KEY, powinny być przechowywane w zmiennych środowiskowych.

Zasada 4: Usługi stron trzecich

Pomysł jest taki, aby stworzyć program w taki sposób, aby nie było różnicy pomiędzy zasobami lokalnymi i zasobami stron trzecich pod względem kodu. Na przykład możesz podłączyć zarówno lokalny MySQL, jak i MySQL innych firm. To samo dotyczy różnych interfejsów API, takich jak Google Maps lub Twitter API.

Aby wyłączyć usługę strony trzeciej lub podłączyć inną, wystarczy zmienić klucze w konfiguracji w zmiennych środowiskowych, o czym mówiłem w powyższym akapicie.

Czyli np. zamiast każdorazowo podawać w kodzie ścieżkę do plików ze zbiorami danych, lepiej skorzystać z biblioteki pathlib i zadeklarować ścieżkę do zbiorów danych w config.py, dzięki czemu bez względu na to, z jakiej usługi korzystasz (np. przykład CircleCI), program był w stanie znaleźć ścieżkę do zbiorów danych, biorąc pod uwagę strukturę nowego systemu plików w nowej usłudze.

Zasada 5. Kompiluj, wydawaj, uruchamiaj

Wiele osób zajmujących się Data Science uważa za przydatne doskonalenie umiejętności pisania oprogramowania. Jeśli chcemy, aby nasz program zawieszał się jak najrzadziej i jak najdłużej działał bezawaryjnie, musimy proces wypuszczenia nowej wersji podzielić na 3 etapy:

  1. Etap zespoły. Przekształcasz swój kod kreskowy z indywidualnymi zasobami w tzw. pakiet, który zawiera cały niezbędny kod i dane. Ten pakiet nazywa się zestawem.
  2. Etap wydanie — tutaj podłączamy naszą konfigurację do zestawu, bez którego nie moglibyśmy wypuścić naszego programu. Teraz jest to wersja całkowicie gotowa do uruchomienia.
  3. Następnie następuje scena spełnienie. Tutaj wypuszczamy aplikację, uruchamiając niezbędne procesy z naszej wersji.

Taki system wydawania nowych wersji modelu lub całego potoku pozwala na rozdzielenie ról pomiędzy administratorami i programistami, umożliwia śledzenie wersji i zapobiega niechcianym zatrzymaniom programu.

Dla zadania wydania utworzono wiele różnych usług, w których można napisać procesy do samodzielnego uruchomienia w pliku .yml (na przykład w CircleCI jest to config.yml do obsługi samego procesu). Wheely świetnie radzi sobie z tworzeniem pakietów do projektów.

Możesz tworzyć pakiety z różnymi wersjami swojego modelu uczenia maszynowego, a następnie je spakować i odwoływać się do niezbędnych pakietów i ich wersji, aby móc korzystać z funkcji, które tam napisałeś. Pomoże Ci to stworzyć API dla Twojego modelu, a Twój pakiet będzie mógł być hostowany na przykład na Gemfury.

Zasada 6. Uruchom swój model jako jeden lub więcej procesów

Co więcej, procesy nie powinny udostępniać danych. Oznacza to, że procesy muszą istnieć osobno i wszelkiego rodzaju dane muszą istnieć osobno, na przykład w usługach stron trzecich, takich jak MySQL lub innych, w zależności od potrzeb.

Oznacza to, że zdecydowanie nie warto przechowywać danych w systemie plików procesu, w przeciwnym razie może to doprowadzić do wyczyszczenia tych danych przy kolejnym wydaniu/zmianie konfiguracji lub przeniesieniu systemu, na którym działa program.

Jest jednak wyjątek: w przypadku projektów uczenia maszynowego można przechowywać pamięć podręczną bibliotek, aby nie instalować ich ponownie przy każdym uruchomieniu nowej wersji, jeśli nie wprowadzono żadnych dodatkowych bibliotek ani nie wprowadzono żadnych zmian w ich wersjach. W ten sposób skrócisz czas wprowadzenia swojego modelu na rynek.

Aby uruchomić model jako kilka procesów, możesz utworzyć plik .yml, w którym określisz niezbędne procesy i ich kolejność.

Zasada 7: Możliwość recyklingu

Procesy uruchamiane w aplikacji modelowej powinny być łatwe do uruchomienia i zatrzymania. Tym samym umożliwi szybkie wdrożenie zmian w kodzie, konfiguracji, szybkie i elastyczne skalowanie oraz zapobiegnie ewentualnym awariom działającej wersji.

Oznacza to, że proces z modelem powinien:

  • Zminimalizuj czas uruchamiania. W idealnym przypadku czas uruchamiania (od momentu wydania polecenia uruchomienia do momentu uruchomienia procesu) nie powinien być dłuższy niż kilka sekund. Opisane powyżej buforowanie bibliotek to jedna z technik pozwalających skrócić czas uruchamiania.
  • Zakończ poprawnie. Oznacza to, że nasłuchiwanie na porcie usługi jest faktycznie zawieszone, a nowe żądania przesłane do tego portu nie będą przetwarzane. Tutaj musisz albo nawiązać dobrą komunikację z inżynierami DevOps, albo sam zrozumieć, jak to działa (najlepiej oczywiście to drugie, ale komunikacja powinna być zawsze utrzymywana, w każdym projekcie!)

Zasada 8: Ciągłe wdrażanie/integracja

Wiele firm stosuje rozdział pomiędzy zespołami tworzącymi i wdrażającymi aplikacje (udostępniając aplikację użytkownikom końcowym). Może to znacznie spowolnić rozwój oprogramowania i postęp w jego ulepszaniu. Psuje to także kulturę DevOps, gdzie rozwój i integracja są, z grubsza rzecz ujmując, łączone.

Dlatego zasada ta stwierdza, że ​​środowisko programistyczne powinno znajdować się jak najbliżej środowiska produkcyjnego.

Umożliwi to:

  1. Skróć czas uwalniania dziesiątki razy
  2. Zmniejsz liczbę błędów wynikających z niezgodności kodu.
  3. Zmniejsza to również obciążenie personelu, ponieważ programiści i osoby wdrażające aplikację stanowią teraz jeden zespół.

Narzędzia, które pozwalają na pracę z tym, to CircleCI, Travis CI, GitLab CI i inne.

Można szybko uzupełnić model, zaktualizować go i od razu uruchomić, a w przypadku awarii bardzo łatwo będzie wrócić do działającej wersji tak, aby końcowy użytkownik nawet tego nie zauważył. Można to zrobić szczególnie łatwo i szybko, jeśli masz dobre testy.

Minimalizuj różnice!!!

Zasada 9. Twoje logi

Dzienniki (lub „Dzienniki”) to zdarzenia, zwykle rejestrowane w formacie tekstowym, które mają miejsce w aplikacji (strumień zdarzeń). Prosty przykład: „2020-02-02 – poziom systemu – nazwa procesu.” Zostały zaprojektowane tak, aby programista mógł dosłownie zobaczyć, co się dzieje, gdy program jest uruchomiony. Widzi postęp procesów i rozumie, czy jest tak, jak zamierzył to sam deweloper.

Zasada ta mówi, że nie powinieneś przechowywać swoich logów w swoim systemie plików - powinieneś po prostu „wyprowadzić” je na ekran, na przykład na standardowe wyjście systemu. W ten sposób możliwe będzie monitorowanie przepływu w terminalu podczas projektowania.

Czy to oznacza, że ​​w ogóle nie ma potrzeby zapisywania logów? Oczywiście nie. Twoja aplikacja po prostu nie powinna tego robić — zostaw to usługom stron trzecich. Twoja aplikacja może przekazywać dzienniki tylko do określonego pliku lub terminala w celu przeglądania w czasie rzeczywistym lub przekazywać je do systemu przechowywania danych ogólnego przeznaczenia (takiego jak Hadoop). Sama aplikacja nie powinna przechowywać dzienników ani wchodzić z nimi w interakcję.

Zasada 10. Testuj!

W przypadku przemysłowego uczenia maszynowego ta faza jest niezwykle ważna, ponieważ musisz zrozumieć, że model działa poprawnie i daje to, czego oczekiwałeś.

Testy można tworzyć za pomocą programu pytest i testować przy użyciu małego zestawu danych, jeśli masz zadanie regresji/klasyfikacji.

Nie zapomnij ustawić tego samego materiału siewnego dla modeli głębokiego uczenia się, aby nie generowały ciągle różnych wyników.

To był krótki opis 10 zasad i oczywiście trudno je stosować bez wypróbowania i sprawdzenia, jak działają, dlatego ten artykuł jest jedynie prologiem do serii ciekawych artykułów, w których zdradzę, jak stworzyć przemysłowe modele uczenia maszynowego, jak zintegrować je z systemami i jak te zasady mogą ułatwić życie nam wszystkim.

Postaram się też zastosować fajne zasady, które każdy może zostawić w komentarzach, jeśli chce.

Źródło: www.habr.com

Dodaj komentarz