Bevezetés

A Machine Learning kutatásában nagy hangsúlyt fektetnek a modellfejlesztésre. Annyira nagy hangsúlyt fektetnek az újszerű architektúrákra, hogy az adatok szinte utólagos gondolatok – és lehet is. Ha olyan szabványosított adatkészlettel dolgozunk, amely alaposan felkészült a gépi tanulási modellek teljesítményértékelésére, akkor nem kell beszélnünk a modelljeink és az adatok közötti interakció kezeléséről.

A való világban ez egy kicsit bonyolultabb. A hangsúly az adatok feldolgozására helyeződik, mivel egy üzleti környezetben az adatok ingatagok, rendetlenek és szétszórtak. Tehát arról fogunk beszélni, hogy áthidaljuk a szakadékot a világszínvonalú modell megléte és egy olyan rendszer felépítése között, amely ezt a modellt alkalmazza az üzleti munkafolyamatokra. Az egyértelműség kedvéért nem fogunk beszélni magukról a gépi tanulási modellekről vagy a modelltervezésről, mivel rengeteg „Hogyan építsünk fel neurális hálózatot a semmiből” című cikket. A cikk terjedelmének korlátozása érdekében nem merülünk el túl sokat az adatkezelésben és -tárolásban (ezt tartsa meg egy további bejegyzésnek!).

Ehelyett a gépi tanulási rendszer egyes részeinek gyors leírásával kezdjük. Innentől kezdve arról fogunk beszélni, hogyan lehet ezeket a részeket mikroszolgáltatásként telepíteni. Végül leírjuk, hogyan definiáljuk ezeknek az összetevőknek az interfészeit, és hogyan hozzunk létre olyan folyamatokat, amelyek lehetővé teszik, hogy ezek az összetevők kölcsönhatásba lépjenek egymással.

Gépi tanulási rendszer tervezése

A modellt egyfajta fekete doboznak tekinthetjük, amely két dolgot tesz: az adatokra oktat és előrejelzéseket készít. Lényegében ez az, amit csinál, és az alkalmazásunk lényege is ez lesz. Nevezzük fit és transform. De sok más rész is megérdemli, hogy önmagukban elismerjék.

A fenti kis fekete négyzet az ML kód. A fenti diagramon nem térünk ki minden egyes mezőre, de beszéljünk néhány olyan dologról, amelyek közvetlenül vonatkoznak a modellünkre.

Online és offline

Az Online és az Offline lényegében az adatok feldolgozásának módjára utal. Ebből a két kategóriából a gépi tanulási rendszerünk összes többi részéhez eltérő stratégiánk lehet, így ez tekinthető a rendszer legmagasabb felosztásának.

Az „Offline” beállításban a forrásadatok előzményadatokból származnak (naplók, adatbázisok). A modell betanítása legtöbbször „offline” történik, mivel az adatok a tárolásból származnak. Amikor a felhasználók a webhelyén lévő dolgokra kattintanak, az adott tevékenység naplókban tárolódik. Mivel az összes adat birtokában van, azokat kötegesen lehet feldolgozni.

„Online” beállítás esetén az adatok „élőben” vannak, tehát menet közben keletkeznek. Ez azt jelenti, hogy az adatok olyan forrásból származnak, amely adatokat generál. Példa erre a valós időben („online”) történő kattintások. Nincsenek kéznél az adatok, és talán nem tudja megvárni, hogy a tárolóban gyűljenek, mielőtt egy új modellt betanítana, ezért adatfolyamként kell feldolgozni.

Alkomponensek

Az online és offline mód között van néhány közös összetevő. Ezeket az összetevőket szolgáltatásokba rendezzük, így kezdjük azzal, hogy felsoroljuk, melyek ezek.

Lenyelés

Az adatbevitel a gépi tanulási rendszer legelső része. Megragadja az adatokat külső adatforrásokból. Ez a rendszer határa. Meg akarjuk határozni, hogy honnan származnak az adatok a betanításhoz, és honnan érkeznek a kiszolgáláshoz. A feldolgozás során a külső adatok másolatát „nyersként” kell kiírnia, így a modell elkészítéséhez használt adatok megváltoztathatatlan, történeti időbélyegzője lesz. Ez előnyösebb, mint a modell adatkezelésének külső adatforráshoz való csatlakoztatása.

Előkészítés

Az előfeldolgozás az, ahol az erőfeszítés nagy része történik. Általában „funkciótervezésnek” vagy „adatbányászatnak” nevezik, ez az a hely, ahol a forrásból bevitt nyers adatokat vesszük, és modellkész formátumba alakítjuk át. Ez az adatok tisztítását, formázását, imputálását és gazdagítását jelenti. Minden egyedi forrás saját csővezetéket kapna az adatok előkészítéséhez.

Kombináció

A kombináció azt jelenti, hogy az összes különálló előkészítő csővezetékből össze kell kapcsolni a szükséges dolgokat. Ha az előkészítő folyamatok párhuzamosan futottak, akkor is össze kell őket vonni egyetlen szolgáltatásokból és címkékből álló adathalmazba. A kiszolgálás során csak funkciókkal rendelkezünk, címkék nélkül, mivel a címkéket a mi betanított modellünk hozza létre.

Elválasztás

Az adatkészletet különböző kohorszokra kell felosztanunk. Általában a rendelkezésre álló címkézett adatkészlet nagy részét fenntartjuk képzésre, majd néhányat tesztelésre. A modellfejlesztés során a tesztadatokat tovább bonthatjuk egy „fejlesztési” vagy „validációs” adathalmazra, így javíthatjuk modellünket a nem látott adatokkal szemben, de továbbra is tesztelhetjük valóban soha nem látott adatokon.

A kiszolgálás során csak a címkézetlen adatokat különíthetjük el és őrizhetjük meg, vagy eltérő felosztást alkalmazhatunk az online tanuláshoz és kiszolgáláshoz.

Képzés

A képzéshez megragadjuk az adatkészlet felosztását a képzéshez (amely magában foglalja a funkciókat és címkéket) és a nem betanított együtthatóadatokat, majd frissítjük ezeket az együtthatókat, amíg modellünk nem tud olyan címkéket létrehozni, amelyek megfelelnek a tényleges címkéknek, pusztán az együtthatók és jellemzők felhasználásával. Ennek végén maradt egy betanított modell, és a betanítási adatok megfeleltek a célnak.

Értékelés

Szükségünk van egy módszerre, amellyel mérhetjük betanított modellünk teljesítményét. Persze, elég jól illeszkedik a látott adatokhoz, de hogyan működik a még nem látott adatokkal? Ez a lépés megragadja a tesztadatokat és a betanított modellt, és kiértékeli a modell működését. Ha a betanított modell átmegy az értékelésen, akkor elérhető jelöltté válik az előrejelzések kiszolgálására.

Kiszolgálás

A megjelenítés kiválasztja a jelölt modellt, és azt használja előrejelzések létrehozására címkézetlen adatokon. Ez a gépi tanulás alapvető értéke – megbecsülni, mi lesz valami valamikor, mielőtt ismertté válna. Ellentétben a képzéssel, amely bemeneti és kimeneti adatokat igényelt a betanított együtthatók elkészítéséhez, most bemeneteket és együtthatókat fogunk használni a vállalkozásunkhoz szükséges előrejelzések elkészítéséhez.

Utófeldolgozás

Amikor adat- és gépi tanulási modellekkel dolgozunk, nagyon közel vagyunk a fémhez. A gépi tanulási modellek mátrixszorzást, számítást és lineáris algebrát tartalmaznak lebegőpontos számok vektorain, és valószínűségeket vagy valós értékeket adnak vissza. Az utófeldolgozás során a modellkimenetet újraformázzuk és fogyaszthatóbb formátumba gazdagítjuk.

Monitoring

Beszámolhatunk a rendszerbe érkező adatok jellemzőiről, a modell teljesítményéről, az előre jelzett értékekről és a történelmi valós értékekről. A lakásárak előrejelzéséhez a várható lakásárak eloszlását a rendelkezésre álló adatok lakásárak eloszlásához hasonlónak képzelnénk el. Ha egészen más, akkor a modell súlyosan leromlott, vagy hiba van. A felügyeleti szolgáltatásokat a fent leírt egyéb összetevőktől függetlenül is beépíthetjük.

Mikroszolgáltatások létrehozása

Amit most tennünk kell, az az, hogy ezeket az összetevőket szolgáltatásként definiáljuk. A mikroszolgáltatások tervezésének egyik alapelve a durva külső interfészek felkínálása. Ezt úgy érjük el, hogy mindegyik összetevőt RESTful API-kkal csomagoljuk. Ez a séma „végpontokat” biztosít, amelyek nagyon hasonlítanak azokhoz a webcímekhez, amelyeket az ügyfél az összetevők bármelyikének végrehajtásához hív meg.

Végpontok meghatározása

Tegyük fel, hogy modellt építünk egy új gyógyszer klinikai vizsgálatainak sikerének valószínűségére. A korábbi klinikai vizsgálatok előzményei és az eredmények elérhetők a „Health Data Now” nevű megosztott adattárban.

A http://hostname:port/offline/preprocess előfeldolgozza a Health Data Now-ból és számos forrásból bevitt adatokat, hogy modellkész adatkészleteket hozzon létre. Az előrejelzések kiszolgálása során a „Private Health Cloud”-ban található belső klinikai vizsgálati adatainkra támaszkodunk. Amikor új kísérleteket indítanak belsőleg, felhívjuk a http://hostname:port/online/preprocess számot, hogy nyers, címkézetlen adatokat készítsünk a „Private Health Cloudból”. Ezután felhívjuk a http://hostname:port/online/serve számot, hogy megragadjuk a legújabb telepített modellt az előrejelzések generálásához.

Szolgáltatási határok meghatározása

Ön dönti el, hogy mely összetevők melyik szolgáltatás-végponthoz tartoznak. Lehet olyan részletes, hogy minden egyes összetevő önálló szolgáltatásnak minősül, saját API-végponttal, vagy ahol több összetevő található egy szolgáltatás alatt. Minél kibontottabbak a szolgáltatások, annál modulárisabb az alkalmazás. Azonban magasabbak a hálózati költségek és további infrastruktúra fenntartása. Mindegyik szolgáltatás felelős a saját adataiért, ezért előfordulhat, hogy kevésbé kívánatos a szolgáltatások kibontása, amikor az adatok a memóriában vannak, és egyszerűen továbbíthatják azokat a folyamat következő lépéséhez.

Konténerezés

A mikroszolgáltatás-orientált architektúra másik előnye, hogy a szolgáltatásoknak nem kell együtt ülniük. Mivel API-kon keresztül kölcsönhatásba lépnek egymással, minden szolgáltatás saját alkalmazásnak tekinthető saját alkalmazáskövetelményekkel. Ha a gépi tanulási rendszer különböző részei eltérő számítási követelményekkel rendelkeznek, akkor külön konténereket definiálhatunk számukra. A legegyszerűbb esetben az összes szolgáltatáshoz egy tárolót határozunk meg, így a telepítés tartalmazza az összes szolgáltatás futtatásához szükséges összes követelményt. A másik véglethez tartozik egy tároló minden végponthoz, ahol minden végpont a saját szolgáltatása, amely önálló alkalmazásként van telepítve.

Ha több tárolót definiál a szolgáltatásokhoz, az az előnye, hogy mindegyik szolgáltatásnak csak a futásához szükséges követelmények vannak. Ez nagyszerű a függőségi izolációhoz. Nézzünk egy példát, ahol különböző szolgáltatásokat fejlesztettek ki különböző kódolási nyelvekkel. A modellképzést Scala segítségével tervezték, és GPU-erőforrásokat igényel. Ezeket a konténereket éjszakánként felpörgetik a képzés futtatásához, ahol a modellparaméterek egy YAML-fájlba kerülnek a felhőben. Míg modellünk betanításához adatpárhuzamra volt szükségünk, az élő adatok előrejelzési sebességéhez viszonyított sebességéhez nincs szükség GPU-ra az előrejelzések kiszolgálásához. A kiszolgáló modell C++ nyelven íródott, ahol a modell frissül a legújabb paramétereket tartalmazó YAML fájllal. Továbbá az adatok előkészítéséhez és betanításához használt eszközök nagy részére egyszerűen nincs szükség a kiszolgálás során, ezért az előrejelzések kiszolgálásához kapcsolódó szolgáltatásokat csak az előrejelzés készítéséhez szükséges szoftverrel konténerezzük.

Verziózás

A gépi tanulási rendszerek jellemzően a „CACE” paradigmától szenvednek – bármit megváltoztat, mindent megváltoztat. Ezt szem előtt tartva azt mondjuk, hogy a „modell” mindent magában foglal, amit fent leírtunk. Bármely szolgáltatás módosítása, bár függetlenül moduláris, új modellváltozatnak minősül.

Mélyebbre ásni: Szolgáltatás megvalósítása

Tudjuk, hogy milyen összetevőkre van szükség a gépi tanulási rendszerünkhöz, és tudjuk, hogy RESTful API-végpontokat fogunk használni a velük való interakcióhoz. Hogyan tervezzük meg a rendszert e végpontok mögött?

Két keretrendszerről fogunk beszélni, amelyeket a gépi tanulási modellünk összehangolásához fogunk használni, és ez a két keretrendszer áthatja rendszerünk nagy részét. Az első a sablonos interfészek, a második az adatfolyam-programozás.

Sablonos felületek

Két csomagot tervezünk a gépi tanulási rendszerünk összetevőinek, a Handlers és a Models létrehozásához. Amikor egy ügyfél meghívja az egyik szolgáltatásvégpontot, az alkalmazás a Kezelők és Modellek segítségével végrehajtja a szükséges funkciókat.

A kezelők két interfészt biztosítanak, a train és serve , míg a modellek a fit és transform felületet. Ezek a mi belső API-ink, amelyeket az alkalmazás fogja használni, míg az alkalmazás a RESTful API-kat ("URI" formájában) teszi közzé az ügyfél számára.

Kezelők

A kezelők adatokat kezelnek. Tekintsd őket osztályoknak, amelyek egy adatfolyamot határoznak meg. Elsősorban az adatkezelésért felelősek. A szabványos kivonat, átalakítás, betöltés (ETL) logikával foglalkoznak, amely adatokat nyer ki a forrásból, átadja azokat egy modellen, és eltárolja a rendeltetési helyére.

Vonat

Akiképzésnél ezek a kezelők a modellek oktatóiként működnek. Összegyűjtik a képzési adatokat és a képzési paramétereket, ezeket betáplálják a modellbe, és eltárolják az eredményeket. Meghatározzuk, hogy a modell hogyan lesz betanítva a Handlers train funkcióban, a modell fit interfészének használatával, hogy a modell módosítsa az együtthatókat.

Kiszolgálás

Kiszolgálás esetén a kezelők felelősek a címkézetlen adatok és a betanított együtthatókkal rendelkező modell összegyűjtéséért. A kezelő a transform modellek API-ját használja, hogy a címkézetlen adatok jellemzőit előrejelzett címkékké alakítsa.

class RegressorHandler(BaseHandler):
    @classmethod
    def train(cls, model, epochs):
        ...
    @classmethod 
    def serve(cls, model):
        ...
    @staticmethod
    def load_data():
        ...
    @staticmethod
    def load_params():
        ...
    @staticmethod
    def store_output():
        ...

A nem ML modellek kezelésekor nincs train funkció. Ehelyett a Serve a transform modellek API-ját fogja használni az adatok átalakításához, és előfordulhat, hogy nincs szüksége paraméterekre. Példa erre a csoportos — alkalmaz — kombinál módszer. Ehhez nincs szükség paraméterekre, de továbbra is egy modell osztályt használnánk a logika megvalósításához, a kezelő pedig a serve-t használja a forrásadatok ilyen módon történő átalakításához.

Modellek

A modellek tartalmazzák az alkalmazás alapvető logikáját. Elfogadják az adatokat és végrehajtanak valamilyen átalakítást. Sablonozhatjuk őket egy absztrakt alaposztállyal, hogy két interfészre legyen szükség: fit és transform.

Fitnesz

A Fit azoknak a modelleknek van fenntartva, amelyeknek bejövő adatokat kell használniuk bizonyos paraméterek beállításához (ezt a szót az „együtthatókkal” felváltva használom). Ez a gépi tanulás „tanulási” része. Lényegében a bemeneteket egy előrejelzett címkévé alakítja azáltal, hogy megszorozza és összeadja őket az együtthatókkal, megméri az előrejelzés és a ténylegesen megadott címke közötti hibát, majd frissíti ezeket az együtthatókat iránypontosan.

Átalakítás

A gépi tanuláshoz a transzformáció alkotja az illesztési függvény első részét – a bemeneteket előre jelzett címkékké alakítja. Amikor előrejelzéseket készítünk, többé nem kell frissítenünk az együtthatókat, így a kezelők a transform API-t használják. A nem gépi tanulási modelleknél a transzformáció más állapot nélküli függvényeken keresztül továbbítja az adatokat a kívánt kimenet eléréséhez.

# models/regression.py
from templates import BaseModel
import numpy as np
class Regressor(BaseModel):
    
    @classmethod
    def fit(cls, parameters, x, y):
        y_h = cls.transform(x, parameters)
        err = cls.loss_func(y_h, y)
        
        return cls.update(parameters, x, y_h, y)
    @classmethod
    def transform(cls, x, parameters):
        x = x.dot(parameters.theta)
        x = x.add(parameters.bias)
    return x
    @classmethod
    def loss_func(y_h, y):
        ...
    @classmethod
    def update():
       ...

Adatfolyam-építés

Az „adatfolyam-programozás” funkcionálisabb megközelítést alkalmaz a szoftvertervezésben, abban az értelemben, hogy az adatok állapot nélküli programokon keresztül áramlanak, amelyek átalakítják a rajtuk áthaladót. Tekintsük ezeket a programokat csomópontoknak, amelyek az adatáramlás iránya alapján folyamatábra módon kapcsolódnak össze. Ezt irányított aciklikus gráfnak vagy röviden DAG-nak nevezik.

Rendelési szolgáltatások

Amikor megszervezzük szolgáltatásaink végrehajtását, minden szolgáltatásra úgy tekinthetünk, mint egy állapot nélküli csomópontra, amelyen adatok áramlanak ki és be. Sok esetben az olyan ütemező és hangszerelési rendszerek, mint az Airflow vagy a Luigi DAG-ként határozzák meg ezen szolgáltatások végrehajtását. Ebben az esetben a hangszerelés (és az ütemezés) a rendszeren kívül esik, így (még) nem kell aggódnunk, hogy ez hogyan történik.

Kezelők hangszerelése

A fenti diagramon minden szolgáltatás a Handler API-kat hívja meg az adatfolyamatok futtatásához. A kezelők olyan osztályok, amelyek leírnak egy adott adatfolyamot. trainvagy serve Az API-k egy sor alprogramot hajtanak végre, amelyek azonos módon vannak összefűzve.

Modellek hangszerelése

A kezelőkhöz hasonlóan a modellek is adatfolyamok. A nyilvánosságra hozott API-jaik, a fit és a transform, egy sor alprogramot hajtanak végre, amelyek DAG-szerűen vannak összefűzve.

Végső gondolatok

A modelleket és a kezelő API-kat alkotó alprogramok az atomi függvények. A fenti diagramokon a load_data → train_model → store results and transform → loss_function → update_params DAG-ját mutattam be. Ezek a funkciók a modellek és kezelők építőkövei.

Egy tökéletesen működő programozási világban adatokat mozgatunk egyik névtelen, állapot nélküli függvényről a másikra. Ha tudni szeretné, mit csinál egy függvény, nézze meg a matematikát. Mivel névtelen, nincs meghatározott név.

Ehelyett vesszük ezeket a kis névtelen függvényeket, például a lambda x: sum(x) / count(x)-t (amit „átlagosnak” is nevezhetnénk), és egy elnevezett függvénybe halmozzuk őket, amely egyetlen feladatot lát el. Tesztelhetjük ezeket a megnevezett függvényeket, hogy megbizonyosodjunk arról, hogy az adatokat a várt módon alakítják-e át, majd összefűzhetjük őket a modell- vagy kezelő API-k által meghívott folyamatba. Ezután tesztelhetjük ezeket az API-kat, hogy megbizonyosodjunk arról, hogy az adatokat is a megfelelő módon alakítják át.

Következtetés

Ezzel befejeződik a Machine Learning Systemsről szóló írás, a magastól az alacsonyig. Kezdjük a gépi tanulás egészének leírásával, majd komponensekre bontottuk, majd leírtuk, hogyan szerveznénk őket mikroszolgáltatásként. Ezután megbeszéltük a sablonozási módszerek és az adatfolyam-paradigma használatát az adatfolyamok felépítéséhez szükséges osztályok összeállításához.

Végül leírjuk a két szükséges osztályt, a kezelőket és a modelleket. A kezelőktől kezdve beszéltünk arról, hogyan használják őket ETL adatfolyamokhoz, oktatáshoz és kiszolgálási modellekhez. Ezután befejeztük a legalsó réteget, a modellosztályt, amely leírja az alkalmazásunk alapvető logikáját, a gépi tanulási módszereket és az azokat alkotó atomi függvényeket.