
Ciao a tutti! Sono uno sviluppatore di CV in KROK. Da tre anni realizziamo progetti nel campo della CV. In questo periodo abbiamo fatto di tutto, ad esempio: monitoravamo i conducenti per assicurarci che durante la guida non bevessero, non fumassero, non parlassero al telefono, guardassero la strada anziché sogni o nuvole; registravamo gli amanti delle corsie riservate e quelli che occupavano più posti nel parcheggio; controllavamo che i lavoratori indossassero caschi, guanti, ecc.; identificavamo i dipendenti che volevano entrare in un'area; conteggiavamo tutto quello che era possibile.
A cosa serve tutto questo?
Durante l'implementazione dei progetti abbiamo fatto alcune brutte esperienze, tanti errori, e alcuni di essi potrebbero esservi già familiari o li conoscerete in futuro.
Modelliamo una situazione
Immaginiamo di essere assunti in una giovane azienda "N", la cui attività è legata all'ML. Stiamo lavorando a un progetto di ML (DL, CV), poi per qualche motivo ci spostiamo su un altro lavoro, in generale prendiamo una pausa, e ritorniamo al nostro o a un altro progetto di rete.
- Arriva il momento della verità, dobbiamo ricordare su cosa ci eravamo fermati, quali iperparametri avevamo provato e, cosa più importante, quali risultati avevano prodotto. Ci possono essere molte opzioni su come si sia conservata l'informazione su tutte le esecuzioni: nella mente, nelle configurazioni, in un taccuino, nell'ambiente di lavoro in cloud. Ho visto un caso in cui gli iperparametri erano conservati come righe commentate nel codice, insomma, un volo di fantasia. E ora immaginate di non essere tornati al vostro progetto, ma a quello di una persona che ha lasciato l'azienda e il cui codice e modello, chiamato model_1.pb, sono stati ereditati da voi. Per completezza, immaginiamo anche che siate un professionista alle prime armi.
- Procediamo. Per eseguire il codice, noi e tutti coloro che ci lavoreranno dobbiamo creare un ambiente. Spesso accade che anche quello non ci sia stato lasciato in eredità per qualche motivo. Questo può diventare un compito non da poco. Non è una perdita di tempo che vogliamo affrontare, giusto?
- Allenare il modello (ad esempio, un rilevatore di automobili). Arriviamo al punto in cui diventa piuttosto efficace: è il momento di salvare il risultato. Lo chiameremo car_detection_v1.pb. Poi ne alleniamo un altro: car_detection_v2.pb. Dopo un po', i nostri colleghi o noi stessi formiamo ancora e ancora, utilizzando architetture diverse. Alla fine si accumulano molti artefatti, le informazioni sui quali devono essere raccolte con cura (ma lo faremo più tardi, poiché abbiamo questioni più urgenti).
- Ecco fatto! Abbiamo un modello! Possiamo iniziare ad addestrare il modello successivo, sviluppare un'architettura per risolvere un nuovo problema o possiamo andare a prendere un tè? E chi si occuperà del deployment?
Identificare i problemi
Lavorare a un progetto o a un prodotto è il risultato del lavoro di molte persone. Con il passare del tempo, le persone partono e arrivano, i progetti aumentano e i progetti stessi diventano più complessi. In un modo o nell'altro, situazioni come quelle descritte nel ciclo precedente (e non solo) si verificheranno in varie combinazioni da iterazione a iterazione. Tutto ciò si traduce in una perdita di tempo, confusione, nervosismo, probabilmente – insoddisfazione del cliente, e infine – in denaro perso. Anche se di solito ci ritroviamo a camminare sugli stessi problemi, penso che nessuno voglia rivivere queste situazioni ripetutamente.

Quindi, abbiamo completato un ciclo di sviluppo e vediamo che ci sono problemi da risolvere. Per fare questo, è necessario:
- archiviare comodamente i risultati del lavoro;
- rendere semplice il processo di integrazione dei nuovi dipendenti;
- semplificare il processo di distribuzione dell'ambiente di sviluppo;
- configurare un processo di versioning dei modelli;
- avere un modo conveniente per validare i modelli;
- trovare uno strumento per gestire lo stato dei modelli;
- trovare un modo per consegnare i modelli in produzione.
Sembra necessario ideare un workflow che permetta di gestire facilmente questo ciclo di vita? Questa pratica è conosciuta come MLOps.
MLOps, o DevOps per l'apprendimento automatico, consente ai team di specialisti in elaborazione e analisi dei dati e di specialisti IT di collaborare, aumentando anche il ritmo di sviluppo e distribuzione dei modelli grazie a monitoraggio, verifica e sistemi di gestione per i modelli di apprendimento automatico.
Puoi , cosa ne pensano i ragazzi di Google. Dall'articolo si capisce che MLOps è una cosa piuttosto ampia.

Nel mio articolo descriverò solo una parte del processo. Per la realizzazione utilizzerò lo strumento MLflow, poiché è un progetto open-source, è necessario un piccolo numero di codice per connettersi e c'è integrazione con i framework ml più popolari. Puoi cercare su Internet altri strumenti, come Kubeflow, SageMaker, Trains, ecc., e forse trovare quello che si adatta meglio alle tue esigenze.
"Costruiamo" MLOps con l'uso dello strumento MLFlow
MLFlow è una piattaforma open source per la gestione del ciclo di vita dei modelli ml ().
MLflow include quattro componenti:
- MLflow Tracking si occupa della registrazione dei risultati e dei parametri che hanno portato a quel risultato;
- MLflow Project consente di impacchettare il codice e riprodurlo su qualsiasi piattaforma;
- MLflow Models si occupa del deployment dei modelli in produzione;
- MLflow Registry consente di memorizzare i modelli e gestirne lo stato in un repository centralizzato.
MLflow opera su due entità:
- run è l'intero ciclo di apprendimento, i parametri e le metriche che vogliamo registrare;
- esperimento è il "tema" che unisce i run.
Tutti i passi dell'esempio sono realizzati su sistema operativo Ubuntu 18.04.
1. Installiamo il server
Per poter gestire facilmente il nostro progetto e ottenere tutte le informazioni necessarie, installeremo un server. Il server di tracciamento MLflow ha due componenti principali:
- backend store si occupa della memorizzazione delle informazioni sui modelli registrati (supporta 4 DBMS: mysql, mssql, sqlite e postgresql);
- artifact store si occupa della memorizzazione degli artefatti (supporta 7 opzioni di memorizzazione: Amazon S3, Azure Blob Storage, Google Cloud Storage, server FTP, server SFTP, NFS, HDFS).
Come artifact store per semplicità prendiamo un server sftp.
- creiamo un gruppo
$ sudo groupadd sftpg - aggiungiamo un utente e impostiamo la sua password
$ sudo useradd -g sftpg mlflowsftp $ sudo passwd mlflowsftp - modifichiamo alcune impostazioni di accesso
$ sudo mkdir -p /data/mlflowsftp/upload $ sudo chown -R root.sftpg /data/mlflowsftp $ sudo chown -R mlflowsftp.sftpg /data/mlflowsftp/upload - aggiungiamo alcune righe a /etc/ssh/sshd_config
Match Group sftpg ChrootDirectory /data/%u ForceCommand internal-sftp - riavviamo il servizio
$ sudo systemctl restart sshd
Come backend store prendiamo postgresql.
$ sudo apt update
$ sudo apt-get install -y postgresql postgresql-contrib postgresql-server-dev-all
$ sudo apt install gcc
$ pip install psycopg2
$ sudo -u postgres -i
# Crea un nuovo utente: mlflow_user
[postgres@user_name~]$ createuser --interactive -P
Inserisci il nome del ruolo da aggiungere: mlflow_user
Inserisci la password per il nuovo ruolo: mlflow
Inseriscila di nuovo: mlflow
Il nuovo ruolo deve essere un superutente? (y/n) n
Il nuovo ruolo può creare database? (y/n) n
Il nuovo ruolo può creare altri ruoli? (y/n) n
# Crea il database mlflow_bd di proprietà di mlflow_user
$ createdb -O mlflow_user mlflow_dbPer avviare il server è necessario installare i seguenti pacchetti python (consiglio di creare un ambiente virtuale separato):
pip install mlflow
pip install pysftpAvviamo il nostro server
$ mlflow server
--backend-store-uri postgresql://mlflow_user:mlflow@localhost/mlflow_db
--default-artifact-root sftp://mlflowsftp:mlflow@sftp_host/upload
--host server_host
--port server_port2. Aggiungiamo il tracking
Affinché i risultati dei nostri addestramenti non vadano persi e le generazioni future di sviluppatori comprendano cosa sia realmente accaduto, consentendo ai colleghi più esperti e a te di analizzare il processo di apprendimento senza preoccupazioni, è necessario aggiungere il tracking. Il tracking implica il salvataggio dei parametri, delle metriche, degli artefatti e di qualsiasi informazione aggiuntiva riguardante l'esecuzione dell'addestramento, nel nostro caso, sul server.
Per esempio, ho creato un piccolo su Keras per la segmentazione di tutto ciò che si trova nel . Per aggiungere il tracking ho creato il file mlflow_training.py.
Ecco le righe in cui accade l'interessante:
def run(self, epochs, lr, experiment_name):
# ottenere l'id dell'esperimento, creando un esperimento se non esiste
remote_experiment_id = self.remote_server.get_experiment_id(name=experiment_name)
# creando un "run" e ottenendo il suo id
remote_run_id = self.remote_server.get_run_id(remote_experiment_id)
# indicare che vogliamo salvare i risultati su un server remoto
mlflow.set_tracking_uri(self.tracking_uri)
mlflow.set_experiment(experiment_name)
with mlflow.start_run(run_id=remote_run_id, nested=False):
mlflow.keras.autolog()
self.train_pipeline.train(lr=lr, epochs=epochs)
try:
self.log_tags_and_params(remote_run_id)
except mlflow.exceptions.RestException as e:
print(e)Qui self.remote_server è un piccolo wrapper sopra i metodi mlflow.tracking. MlflowClient (l'ho fatto per comodità), con cui creo esperimenti e avvii sul server. Poi indico dove devono essere salvati i risultati dell'avvio (mlflow.set_tracking_uri(self.tracking_uri)). Attivo la registrazione automatica mlflow.keras.autolog(). Attualmente, MLflow Tracking supporta la registrazione automatica per TensorFlow, Keras, Gluon XGBoost, LightGBM, Spark. Se non hai trovato il tuo framework o libreria, puoi sempre registrare esplicitamente. Avviamo l'addestramento. Registriamo i tag e i parametri di input sul server remoto.
Con poche righe e voi, come tutti gli interessati, avete accesso alle informazioni su tutti gli avvii. Fantastico?
3. Formattiamo il progetto
Ora rendiamo più semplice l'avvio del progetto. Per questo, aggiungiamo un file MLproject e conda.yaml nella radice del progetto.
MLproject
name: flow_segmentation
conda_env: conda.yaml
entry_points:
main:
parameters:
categories: {help: 'elenco delle categorie dal dataset coco'}
epochs: {type: int, help: 'numero di epoche nell'addestramento'}
lr: {type: float, default: 0.001, help: 'tasso di apprendimento'}
batch_size: {type: int, default: 8}
model_name: {type: str, default: 'Unet', help: 'Unet, PSPNet, Linknet, FPN'}
backbone_name: {type: str, default: 'resnet18', help: 'esempio resnet18, resnet50, mobilenetv2 ...'}
tracking_uri: {type: str, help: 'l'indirizzo del server'}
experiment_name: {type: str, default: 'My_experiment', help: 'nome dell'esperimento remoto e locale'}
command: "python mlflow_training.py
--epochs={epochs}
--categories={categories}
--lr={lr}
--tracking_uri={tracking_uri}
--model_name={model_name}
--backbone_name={backbone_name}
--batch_size={batch_size}
--experiment_name={experiment_name}"Il progetto MLflow ha diverse proprietà:
- Name — il nome del tuo progetto;
- Environment — nel mio caso conda_env indica che per l'esecuzione viene utilizzato Anaconda e la descrizione delle dipendenze si trova nel file conda.yaml;
- Entry Points — indica quali file e con quali parametri possiamo avviare (tutti i parametri all'avvio dell'addestramento vengono automaticamente registrati)
conda.yaml
name: flow_segmentation
channels:
- defaults
- anaconda
dependencies:
- python==3.7
- pip:
- mlflow==1.8.0
- pysftp==0.2.9
- Cython==0.29.19
- numpy==1.18.4
- pycocotools==2.0.0
- requests==2.23.0
- matplotlib==3.2.1
- segmentation-models==1.0.1
- Keras==2.3.1
- imgaug==0.4.0
- tqdm==4.46.0
- tensorflow-gpu==1.14.0Come ambiente di esecuzione puoi utilizzare Docker, per ulteriori informazioni fai riferimento a .
4. Avviamo l'addestramento
Cloniamo il progetto e passiamo alla directory del progetto:
git clone https://github.com/simbakot/mlflow_example.git
cd mlflow_example/Per avviare, è necessario installare le librerie
pip install mlflow
pip install pysftpPoiché nell'esempio utilizzo conda_env, sul tuo computer dovrebbe essere installato Anaconda (ma questo può essere aggirato installando tutti i pacchetti necessari manualmente e giocando con i parametri di avvio).
Tutti i passaggi preparatori sono completati e possiamo procedere con l'avvio dell'addestramento. Dalla radice del progetto:
$ mlflow run -P epochs=10 -P categories=cat,dog -P tracking_uri=http://server_host:server_port .Dopo aver inserito il comando verrà automaticamente creato un ambiente conda e inizierà l'addestramento.
Nell'esempio sopra ho passato il numero di epoche per l'addestramento, le categorie su cui vogliamo segmentare (l'elenco completo può essere visualizzato ) e l'indirizzo del nostro server remoto.
L'elenco completo dei parametri possibili può essere visualizzato nel file MLproject.
5. Valutiamo i risultati dell'addestramento
Dopo il completamento dell'addestramento, possiamo andare nel browser all'indirizzo del nostro server

Qui vediamo l'elenco di tutti gli esperimenti (in alto a sinistra), oltre alle informazioni sui lanci (al centro). Possiamo visualizzare informazioni più dettagliate (parametri, metriche, artefatti e altre informazioni aggiuntive) su ogni lancio.

Per ogni metrica possiamo osservare la storia delle modifiche.

Vale a dire, al momento possiamo analizzare i risultati in modalità 'manuale', inoltre puoi anche configurare la validazione automatica utilizzando l'API di MLflow.
6. Registriamo il modello
Dopo aver analizzato il nostro modello e deciso che è pronto per l'uso, procediamo alla sua registrazione, per questo selezioniamo il lancio di nostro interesse (come mostrato nel punto precedente) e scendiamo.

Dopo aver dato un nome al nostro modello, viene assegnata una versione. Quando salviamo un altro modello con lo stesso nome, la versione aumenterà automaticamente.

Per ogni modello possiamo aggiungere una descrizione e scegliere uno dei tre stati (Staging, Production, Archived), successivamente possiamo utilizzare l'API per accedere a questi stati, a seguito della versioning, offrendo flessibilità aggiuntiva.

Abbiamo anche un accesso comodo a tutti i modelli

e le loro versioni.

Come nel punto precedente, tutte le operazioni possono essere eseguite tramite API.
7. Deployamo il modello
A questo punto abbiamo già un modello (keras) addestrato. Ecco un esempio di come utilizzarlo:
class SegmentationModel:
def __init__(self, tracking_uri, model_name):
self.registry = RemoteRegistry(tracking_uri=tracking_uri)
self.model_name = model_name
self.model = self.build_model(model_name)
def get_latest_model(self, model_name):
registered_models = self.registry.get_registered_model(model_name)
last_model = self.registry.get_last_model(registered_models)
local_path = self.registry.download_artifact(last_model.run_id, 'model', '.\/')
return local_path
def build_model(self, model_name):
local_path = self.get_latest_model(model_name)
return mlflow.keras.load_model(local_path)
def predict(self, image):
image = self.preprocess(image)
result = self.model.predict(image)
return self.postprocess(result)
def preprocess(self, image):
image = cv2.resize(image, (256, 256))
image = image / 255.
image = np.expand_dims(image, 0)
return image
def postprocess(self, result):
return resultQui self.registry è di nuovo un piccolo wrapper su mlflow.tracking.MlflowClient, per comodità. Il punto è che mi riferisco a un server remoto e cerco lì il modello con il nome specificato, precisamente l'ultima versione di produzione. Successivamente scarico l'artefatto localmente nella cartella .\/model e compilo il modello da questa directory con mlflow.keras.load_model(local_path). Ora possiamo utilizzare il nostro modello. Gli sviluppatori di CV (ML) possono tranquillamente concentrarsi sul miglioramento del modello e pubblicare nuove versioni.
In conclusione
Ho presentato un sistema che consente di:
- archiviare centralmente le informazioni sui modelli ML, il progresso e i risultati dell'addestramento;
- implementare rapidamente un ambiente di sviluppo;
- monitorare e analizzare il progresso dei lavori sui modelli;
- gestire in modo conveniente le versioni e lo stato dei modelli;
- deployer facilmente i modelli ottenuti.
Questo esempio è solo un prototipo e serve come punto di partenza per costruire il proprio sistema, che probabilmente includerà l'automazione della valutazione dei risultati e la registrazione dei modelli (p.5 e p.6 rispettivamente) oppure si possono aggiungere versioni dei dataset, o forse qualcos'altro? Ho cercato di comunicare l'idea che in generale avete bisogno di MLOps, MLflow è solo uno strumento per raggiungere l'obiettivo.
Scrivete quali problemi avete riscontrato che non ho menzionato?
Cosa aggiungereste al sistema per soddisfare le vostre necessità?
Quali strumenti e approcci utilizzate per affrontare tutti o parte dei problemi?
P.S. Lascio un paio di link:
progetto github —
MLflow —
La mia email lavorativa, per domande — ikryakin@croc.ru
Nella nostra azienda si tengono periodicamente diversi eventi per specialisti IT, ad esempio: il 8 luglio alle 19:00 ora di Mosca si svolgerà un meetup online sul CV. Se siete interessati, potete partecipare, registrazione. .
Fonte: habr.com
