Industriell maskininlärning: 10 designprinciper

Industriell maskininlärning: 10 designprinciper

Nuförtiden skapas nya tjänster, applikationer och andra viktiga program varje dag som gör det möjligt att skapa otroliga saker: från mjukvara för att styra en SpaceX-raket till att interagera med en vattenkokare i nästa rum via en smartphone.

Och ibland kommer varje nybörjare, oavsett om han är en passionerad startuper eller en vanlig Full Stack eller Data Scientist, förr eller senare till insikten att det finns vissa regler för programmering och skapande av mjukvara som avsevärt förenklar livet.

I den här artikeln kommer jag kort att beskriva 10 principer för hur man programmerar industriell maskininlärning så att den enkelt kan integreras i en applikation/tjänst, baserat på 12-faktors App-metodik. föreslagits av Heroku-teamet. Mitt initiativ är att öka medvetenheten om denna teknik, som kan hjälpa många utvecklare och datavetenskapare.

Den här artikeln är en prolog till en serie artiklar om industriell maskininlärning. I dem kommer jag vidare att prata om hur man faktiskt gör en modell och lanserar den i produktion, skapar ett API för den, samt exempel från olika områden och företag som har inbyggt ML i sina system.

Princip 1: En kodbas

Vissa programmerare i de första stegen, av lättja att lista ut det (eller av någon egen anledning), glömmer Git. Antingen glömmer de helt ordet, det vill säga slänger filer till varandra i enheten/slänger bara text/skickas med duvor, eller så tänker de inte igenom sitt arbetsflöde, och förbinder sig var och en till sin egen gren och sedan till bemästra.

Denna princip säger: har en kodbas och många distributioner.

Git kan användas både i produktion och i forskning och utveckling (FoU), där det inte används så ofta.

Till exempel kan du i FoU-fasen lämna commits med olika databehandlingsmetoder och modeller, för att sedan välja den bästa och enkelt fortsätta arbeta vidare med den.

För det andra, i produktionen är detta en oersättlig sak - du måste hela tiden titta på hur din kod förändras och veta vilken modell som gav bäst resultat, vilken kod som fungerade till slut och vad som hände som fick den att sluta fungera eller börja producera felaktiga resultat . Det är vad commits är till för!

Du kan också skapa ett paket av ditt projekt, placera det till exempel på Gemfury och sedan helt enkelt importera funktioner från det för andra projekt, för att inte skriva om dem 1000 gånger, utan mer om det senare.

Princip 2: Klart deklarera och isolera beroenden

Varje projekt har olika bibliotek som du importerar utifrån för att kunna tillämpa dem någonstans. Oavsett om det är Python-bibliotek, eller bibliotek med andra språk för olika ändamål, eller systemverktyg - din uppgift är:

  • Deklarera tydligt beroenden, det vill säga en fil som kommer att innehålla alla bibliotek, verktyg och deras versioner som används i ditt projekt och som måste installeras (till exempel i Python kan detta göras med Pipfile eller requirements.txt. A länk som låter bra att förstå: realpython.com/pipenv-guide)
  • Isolera beroenden specifikt för ditt program under utveckling. Du vill inte ständigt ändra versioner och installera om till exempel Tensorflow?

På så sätt kommer utvecklare som kommer att ansluta sig till ditt team i framtiden snabbt kunna bekanta dig med biblioteken och deras versioner som används i ditt projekt, och du kommer även att ha möjlighet att hantera versionerna och biblioteken själva installerade för en specifik projekt, som hjälper dig att undvika inkompatibilitet mellan bibliotek eller deras versioner.

Din applikation bör inte heller förlita sig på systemverktyg som kan vara installerade på ett specifikt operativsystem. Dessa verktyg måste också deklareras i beroendemanifestet. Detta är nödvändigt för att undvika situationer där versionen av verktygen (liksom deras tillgänglighet) inte matchar systemverktygen för ett visst operativsystem.

Således, även om curl kan användas på nästan alla datorer, bör du fortfarande deklarera det i beroenden, eftersom när du migrerar till en annan plattform kanske det inte finns där eller så kommer versionen inte att vara den du ursprungligen behövde.

Din requirements.txt kan till exempel se ut så här:

# 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

Princip 3: Konfigurationer

Många har hört historier om olika utvecklarkillar som av misstag laddar upp kod till GitHub till offentliga arkiv med lösenord och andra nycklar från AWS, och vaknar nästa dag med en skuld på $6000 50000, eller till och med $XNUMX XNUMX.

Industriell maskininlärning: 10 designprinciper

Naturligtvis är dessa fall extrema, men mycket betydelsefulla. Om du lagrar dina referenser eller annan data som behövs för konfiguration i koden gör du ett misstag, och jag tror att det inte finns något behov av att förklara varför.

Ett alternativ till detta är att lagra konfigurationer i miljövariabler. Du kan läsa mer om miljövariabler här.

Exempel på data som vanligtvis lagras i miljövariabler:

  • Domännamn
  • API URL:er/URI:er
  • Offentliga och privata nycklar
  • Kontakter (e-post, telefoner, etc.)

På så sätt behöver du inte ständigt ändra koden om dina konfigurationsvariabler ändras. Detta kommer att hjälpa dig att spara tid, ansträngning och pengar.

Till exempel, om du använder Kaggle API för att utföra tester (till exempel ladda ner programvaran och kör modellen genom den för att testa när den körs att modellen fungerar bra), så ska privata nycklar från Kaggle, som KAGGLE_USERNAME och KAGGLE_KEY, vara lagras i miljövariabler.

Princip 4: Tredjepartstjänster

Tanken här är att skapa programmet på ett sådant sätt att det inte finns någon skillnad mellan lokala och tredje parts resurser när det gäller kod. Du kan till exempel ansluta både lokala MySQL och tredjeparts. Detsamma gäller för olika API:er som Google Maps eller Twitter API.

För att inaktivera en tredjepartstjänst eller ansluta en annan behöver du bara ändra nycklarna i konfigurationen i miljövariablerna, som jag pratade om i stycket ovan.

Så, till exempel, istället för att ange sökvägen till filer med datauppsättningar inuti koden varje gång, är det bättre att använda pathlib-biblioteket och deklarera sökvägen till datauppsättningarna i config.py, så att oavsett vilken tjänst du använder (för Exempelvis CircleCI), kunde programmet ta reda på sökvägen till datamängderna med hänsyn till strukturen för det nya filsystemet i den nya tjänsten.

Princip 5. Bygg, släpp, körtid

Många personer inom Data Science tycker att det är användbart att förbättra sina färdigheter i att skriva programvara. Om vi ​​vill att vårt program ska krascha så sällan som möjligt och fungera utan fel så länge som möjligt, måste vi dela upp processen för att släppa en ny version i 3 steg:

  1. stadium församlingar. Du omvandlar din barkod med individuella resurser till ett så kallat paket som innehåller all nödvändig kod och data. Detta paket kallas en montering.
  2. stadium frisättning — här ansluter vi vår config till assembly, utan vilken vi inte skulle kunna släppa vårt program. Nu är detta en helt klar att lansera release.
  3. Nästa kommer scenen uppfyllelse. Här släpper vi applikationen genom att köra nödvändiga processer från vår release.

Ett sådant system för att släppa nya versioner av en modell eller hela pipelinen låter dig separera roller mellan administratörer och utvecklare, låter dig spåra versioner och förhindrar oönskade stopp av programmet.

För releaseuppgiften har många olika tjänster skapats där du kan skriva processer för att köra dig själv i en .yml-fil (till exempel i CircleCI är detta config.yml för att stödja själva processen). Wheely är bra på att skapa paket för projekt.

Du kan skapa paket med olika versioner av din maskininlärningsmodell och sedan paketera dem och hänvisa till de nödvändiga paketen och deras versioner för att använda funktionerna du skrev därifrån. Detta hjälper dig att skapa ett API för din modell, och ditt paket kan till exempel lagras på Gemfury.

Princip 6. Kör din modell som en eller flera processer

Dessutom bör processer inte ha delad data. Det vill säga att processer måste finnas separat, och alla typer av data måste finnas separat, till exempel på tredjepartstjänster som MySQL eller andra, beroende på vad du behöver.

Det vill säga, det är definitivt inte värt att lagra data i processfilsystemet, annars kan detta leda till att dessa data rensas under nästa release/ändring av konfigurationer eller överföring av systemet som programmet körs på.

Men det finns ett undantag: för maskininlärningsprojekt kan du lagra en cache med bibliotek för att inte installera om dem varje gång du startar en ny version, om inga ytterligare bibliotek eller ändringar har gjorts i deras versioner. På så sätt kommer du att minska tiden det tar att lansera din modell i industrin.

För att köra modellen som flera processer kan du skapa en .yml-fil där du anger nödvändiga processer och deras sekvens.

Princip 7: Återvinningsbarhet

Processerna som körs i din modellapplikation ska vara lätta att starta och stoppa. Således kommer detta att tillåta dig att snabbt distribuera kodändringar, konfigurationsändringar, snabbt och flexibelt skala och förhindra eventuella haverier av den fungerande versionen.

Det vill säga, din process med modellen bör:

  • Minimera starttiden. Idealiskt bör starttiden (från det ögonblick då startkommandot utfärdades till det ögonblick då processen startar) inte vara mer än några sekunder. Bibliotekscachelagring, som beskrivs ovan, är en teknik för att minska starttiden.
  • Avsluta korrekt. Det vill säga att lyssna på serviceporten är faktiskt avstängd och nya förfrågningar som skickas till denna port kommer inte att behandlas. Här behöver du antingen skapa en bra kommunikation med DevOps-ingenjörer, eller förstå hur det fungerar själv (helst, naturligtvis, det senare, men kommunikationen ska alltid upprätthållas, i alla projekt!)

Princip 8: Kontinuerlig distribution/integrering

Många företag använder en separation mellan applikationsutvecklings- och distributionsteamen (gör applikationen tillgänglig för slutanvändare). Detta kan avsevärt bromsa mjukvaruutveckling och framsteg i att förbättra den. Det förstör också DevOps-kulturen, där utveckling och integration, grovt sett, kombineras.

Därför säger denna princip att din utvecklingsmiljö ska vara så nära din produktionsmiljö som möjligt.

Detta kommer att tillåta:

  1. Minska släpptiden med tiotals gånger
  2. Minska antalet fel på grund av kodinkompatibilitet.
  3. Detta minskar också arbetsbelastningen på personalen, eftersom utvecklare och personer som distribuerar applikationen nu är ett team.

Verktyg som låter dig arbeta med detta är CircleCI, Travis CI, GitLab CI och andra.

Du kan snabbt göra tillägg till modellen, uppdatera den och starta den omedelbart, samtidigt som det blir lätt, vid misslyckanden, att återgå mycket snabbt till den fungerande versionen, så att slutanvändaren inte ens märker det. Detta kan göras särskilt enkelt och snabbt om du har bra tester.

Minimera skillnader!!!

Princip 9. Dina loggar

Loggar (eller "loggar") är händelser, vanligtvis inspelade i textformat, som inträffar i applikationen (händelseström). Ett enkelt exempel: "2020-02-02 - systemnivå - processnamn." De är designade så att utvecklaren bokstavligen kan se vad som händer när programmet körs. Han ser framstegen i processer och förstår om det är som utvecklaren själv tänkt sig.

Denna princip säger att du inte ska lagra dina loggar i ditt filsystem - du ska bara "mata ut" dem till skärmen, till exempel gör detta på systemets standardutgång. Och på så sätt blir det möjligt att övervaka flödet i terminalen under utvecklingen.

Betyder detta att det inte finns något behov av att spara loggar alls? Självklart inte. Din applikation borde helt enkelt inte göra detta – lämna den till tredjepartstjänster. Din applikation kan bara vidarebefordra loggar till en specifik fil eller terminal för visning i realtid, eller vidarebefordra den till ett allmänt datalagringssystem (som Hadoop). Din applikation i sig bör inte lagra eller interagera med loggar.

Princip 10. Testa!

För industriell maskininlärning är denna fas extremt viktig, eftersom du måste förstå att modellen fungerar korrekt och producerar det du ville ha.

Tester kan skapas med pytest och testas med en liten datauppsättning om du har en regression/klassificeringsuppgift.

Glöm inte att sätta samma frö för modeller för djupinlärning så att de inte ständigt ger olika resultat.

Detta var en kort beskrivning av de 10 principerna, och det är naturligtvis svårt att använda dem utan att försöka se hur de fungerar, så den här artikeln är bara en prolog till en serie intressanta artiklar där jag kommer att avslöja hur man skapar industriella maskininlärningsmodeller, hur man integrerar dem i system och hur dessa principer kan göra livet lättare för oss alla.

Jag ska också försöka använda mig av coola principer som vem som helst kan lämna i kommentarerna om de vill.

Källa: will.com

Lägg en kommentar