
Ciao a tutti! Sono uno sviluppatore di CV in KROK. Da tre anni realizziamo progetti nel settore del CV. In questo periodo abbiamo fatto di tutto, ad esempio: monitorato i conducenti per assicurarci che durante la guida non bevessero, non fumassero, non parlassero al telefono e guardassero la strada, piuttosto che il cielo o i sogni; abbiamo registrato gli amanti delle corsie riservate e di occupare più posti auto; abbiamo vigilato affinché i lavoratori indossassero caschi, guanti ecc.; identificato i dipendenti che vogliono accedere al sito; contato tutto ciò che era possibile.
A cosa voglio arrivare?
Durante l'implementazione dei progetti abbiamo accumulato esperienze, molte esperienze, e alcune delle problematiche le conoscerete o le conoscerete in futuro.
Modelliamo una situazione
Immaginiamo di essere stati assunti in una giovane azienda "N", la cui attività è collegata al ML. Stiamo lavorando a un progetto di ML (DL, CV), poi per qualche motivo ci spostiamo su un altro lavoro, in breve facciamo una pausa e torniamo al nostro o al suo rete neurale.
- Arriva il momento della verità, bisogna in qualche modo ricordare dove ci eravamo fermati, quali iperparametri abbiamo provato e, soprattutto, quali risultati hanno portato. Ci possono essere molteplici modi in cui le informazioni su tutti i lanci sono state conservate: nella mente, nei file di configurazione, in un quaderno, nell'ambiente di lavoro nel cloud. Ho visto un caso in cui gli iperparametri erano conservati come righe commentate nel codice, un vero volo della fantasia. E ora immaginate di non star tornando al vostro progetto, ma a quello di una persona che ha lasciato l'azienda e vi ha lasciato in eredità codice e un modello chiamato model_1.pb. Per completezza e per trasmettere tutta la frustrazione, immaginiamo anche che siate un professionista alle prime armi.
- Andiamo oltre. Per eseguire il codice, è necessario creare un ambiente per tutti coloro che lavoreranno con esso. Spesso accade che anche questo non ci sia stato lasciato in eredità per qualche motivo. Anche questo può diventare un compito non banale. Non si vuole sprecare tempo su questo, vero?
- Stiamo addestrando un modello (ad esempio, un rilevatore di automobili). Raggiungiamo il momento in cui diventa piuttosto buono — è il momento di salvare il risultato. Lo chiameremo car_detection_v1.pb. Poi alleniamo un altro modello — car_detection_v2.pb. Dopo un po' di tempo, i nostri colleghi o noi stessi alleniamo ancora e ancora, usando diverse architetture. Alla fine, si forma un mucchio di artefatti, le cui informazioni devono essere raccolte con cura (ma lo faremo più tardi, abbiamo cose più prioritarie da fare nel frattempo).
- Ecco fatto! Abbiamo un modello! Possiamo iniziare ad addestrare il modello successivo, a sviluppare un'architettura per risolvere un nuovo problema, o possiamo andare a bere un tè? E chi si occuperà del deployment?
Identifichiamo i problemi
Lavorare su un progetto o un prodotto è il risultato del lavoro di molte persone. Con il passare del tempo, i membri del team cambiano e i progetti aumentano di numero, diventando sempre più complessi. In un modo o nell'altro, situazioni come quelle descritte sopra (e non solo) si presenteranno in varie combinazioni ad ogni iterazione. Tutto ciò si traduce in una perdita di tempo, confusione, nervosismo e, possibilmente, nel disappunto del cliente, con la conseguente perdita economica. Anche se spesso ripetiamo gli stessi errori, credo che nessuno voglia rivivere costantemente questi momenti.

Quindi, abbiamo completato un ciclo di sviluppo e notiamo che ci sono problemi da risolvere. Per affrontarli, è necessario:
- conservare comodamente i risultati del lavoro;
- semplificare il processo di inserimento dei nuovi collaboratori;
- facilitare il processo di distribuzione dell'ambiente di sviluppo;
- impostare il processo di versioning dei modelli;
- avere un modo semplice per validare i modelli;
- trovare uno strumento di gestione dello stato dei modelli;
- trovare un modo per distribuire i modelli in produzione.
Sembra necessario ideare un workflow che permetta di gestire facilmente e comodamente questo ciclo di vita? Questa pratica ha un nome: MLOps.
MLOps, o DevOps per l'apprendimento automatico, consente ai team di specialisti in elaborazione e analisi dei dati e a professionisti IT di collaborare, aumentando così il ritmo di sviluppo e rilascio dei modelli attraverso monitoraggio, convalida e sistemi di gestione per i modelli di machine learning.
Puoi , cosa ne pensano i ragazzi di Google. Dall'articolo si evince che MLOps è un concetto piuttosto complesso.

Nella mia prossima sezione descriverò solo una parte del processo. Per la realizzazione userò lo strumento MLflow, poiché è un progetto open-source, per il collegamento è necessario un piccolo numero di righe di codice e c'è integrazione con famosi framework di machine learning. Puoi cercare su internet altri strumenti, come Kubeflow, SageMaker, Trains, ecc., e magari trovare quello che si adatta meglio alle tue esigenze.
"Costruiamo" MLOps usando lo strumento MLFlow
MLFlow è una piattaforma open-source per la gestione del ciclo di vita dei modelli ml ().
MLflow include quattro componenti:
- MLflow Tracking — risolve le questioni relative alla 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 — è responsabile del deployment dei modelli in produzione;
- MLflow Registry — consente di archiviare i modelli e gestire il loro stato in un repository centralizzato.
MLflow opera con due entità:
- lancio — è l'intero ciclo di apprendimento, i parametri e le metriche che vogliamo registrare;
- esperimento — è il "tema" che riunisce i lanci.
Tutti i passaggi dell'esempio sono realizzati su sistema operativo Ubuntu 18.04.
1. Configuriamo il server
Per poter gestire facilmente il nostro progetto e ottenere tutte le informazioni necessarie, configureremo un server. Il server di tracciamento MLflow ha due componenti principali:
- backend store — è responsabile della memorizzazione delle informazioni sui modelli registrati (supporta 4 DBMS: mysql, mssql, sqlite e postgresql);
- artifact store — è responsabile della memorizzazione degli artefatti (supporta 7 opzioni di archiviazione: Amazon S3, Azure Blob Storage, Google Cloud Storage, server FTP, server SFTP, NFS, HDFS).
Come artifact store per semplicità, utilizziamo 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 - correggiamo un paio di 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 in /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
Enter name of role to add: mlflow_user
Enter password for new role: mlflow
Enter it again: mlflow
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n
# Crea database mlflow_bd posseduto da 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
Per garantire che i risultati dei nostri allenamenti non vadano perduti, che le future generazioni di sviluppatori comprendano ciò che è accaduto e che i colleghi più esperti e tu possiate analizzare il processo di apprendimento senza preoccupazioni, è necessario aggiungere il tracciamento. Con tracciamento si intende la registrazione dei parametri, delle metriche, degli artefatti e di qualsiasi informazione aggiuntiva riguardante l'avvio dell'allenamento, nel nostro caso, sul server.
A titolo di esempio, ho creato un piccolo utilizzando Keras per la segmentazione di tutto ciò che si trova nel . Per aggiungere il tracciamento, ho creato il file mlflow_training.py.
Ecco le righe in cui avviene la parte più interessante:
def run(self, epochs, lr, experiment_name):
# ottenere l'id dell'esperimento, creando un esperimento in assenza
remote_experiment_id = self.remote_server.get_experiment_id(name=experiment_name)
# creare un "run" e ottenere 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 attorno ai metodi mlflow.tracking. MlflowClient (che ho creato per comodità), tramite i quali avvio esperimenti e esecuzioni sul server. Poi indico dove devono essere inviati i risultati dell'esecuzione (mlflow.set_tracking_uri(self.tracking_uri)). Attivo il logging automatico con mlflow.keras.autolog(). Attualmente, MLflow Tracking supporta il logging automatico per TensorFlow, Keras, Gluon XGBoost, LightGBM e Spark. Se non riesci a trovare il tuo framework o libreria, puoi sempre registrare in modo esplicito. Avviamo l'addestramento. Registriamo i tag e i parametri di input sul server remoto.
Bastano poche righe e avrete, come tutti, accesso alle informazioni su tutte le esecuzioni. Impressionante, vero?
3. Creiamo il progetto
Ora rendiamo semplice l'avvio del progetto. Per fare ciò, 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: 'list of categories from coco dataset'}
epochs: {type: int, help: 'number of epochs in training'}
lr: {type: float, default: 0.001, help: 'learning rate'}
batch_size: {type: int, default: 8}
model_name: {type: str, default: 'Unet', help: 'Unet, PSPNet, Linknet, FPN'}
backbone_name: {type: str, default: 'resnet18', help: 'exampe resnet18, resnet50, mobilenetv2 ...'}
tracking_uri: {type: str, help: 'the server address'}
experiment_name: {type: str, default: 'My_experiment', help: 'remote and local experiment name'}
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}"MLflow Project имеет несколько свойств:
- Name — имя вашего проекта;
- Environment — в моем случае conda_env указывает на то, что для запуска используется Anaconda и описание зависимостей находится в файле conda.yaml;
- Entry Points — указывает какие файлы и с какими параметрами мы можем запустить (все параметры при запуске обучения автоматически логируются)
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 dettagli, fai riferimento a .
4. Avviare l'addestramento
Cloniamo il progetto e accediamo alla directory del progetto:
git clone https://github.com/simbakot/mlflow_example.git
cd mlflow_example/Per avviarlo, è necessario installare le librerie
pip install mlflow
pip install pysftpPoiché in questo esempio utilizzo conda_env, Anaconda deve essere installata sul tuo computer (ma è possibile evitarlo installando tutti i pacchetti necessari autonomamente e modificando i parametri di avvio).
Tutti i passaggi preparatori sono completati e possiamo avviare l'addestramento. Dalla root 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 sarà avviato l'addestramento.
Nell'esempio sopra, ho passato il numero di epoche per l'addestramento e le categorie su cui vogliamo segmentare (l'elenco completo può essere visualizzato ) e l'indirizzo del nostro server remoto.
È possibile visualizzare l'elenco completo dei parametri nel file MLproject.
5. Valutiamo i risultati dell'apprendimento
Dopo il completamento dell'apprendimento, possiamo accedere nel browser all'indirizzo del nostro server

Qui vediamo l'elenco di tutti gli esperimenti (in alto a sinistra), insieme alle informazioni sulle esecuzioni (al centro). Possiamo visualizzare ulteriori dettagli (parametri, metriche, artefatti e altre informazioni) su ciascuna esecuzione.

Per ciascuna metrica, possiamo osservare la cronologia delle modifiche.

Cioè, al momento possiamo analizzare i risultati in modo "manuale", ma è anche possibile configurare la validazione automatica tramite l'API MLflow.
6. Registriamo il modello
Dopo aver analizzato il nostro modello e deciso che è pronto per l'uso, procediamo alla registrazione; per fare ciò, scegliamo l'esecuzione di nostro interesse (come mostrato nel punto precedente) e scendiamo.

Dopo aver assegnato un nome al nostro modello, esso acquisisce una versione. Quando salviamo un altro modello con lo stesso nome, la versione aumenta automaticamente.

Per ogni modello, possiamo aggiungere una descrizione e selezionare uno dei tre stati (Staging, Production, Archived); successivamente, grazie all'API, possiamo interagire con questi stati, il che, insieme alle versioni, offre ulteriore flessibilità.

Abbiamo anche un accesso comodo a tutti i modelli

e alle loro versioni

Come nel punto precedente, tutte le operazioni possono essere effettuate tramite API.
7. Deployiamo il modello
In questo stadio, abbiamo già un modello addestrato (keras). 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à. La sostanza è che mi connetto a un server remoto e cerco un modello con il nome specificato, e precisamente l'ultima versione di produzione. Successivamente scarico l'artefatto localmente nella cartella ./model e carico 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 lavorare al miglioramento del modello e pubblicare nuove versioni.
In conclusione
Ho presentato un sistema che consente di:
- archiviare centralmente le informazioni sui modelli ML, sul progresso e sui risultati dell'addestramento;
- disporre rapidamente di un ambiente di sviluppo;
- monitorare e analizzare il progresso del lavoro sui modelli;
- gestire comodamente la versioning e lo stato dei modelli;
- deployare facilmente i modelli ottenuti.
Questo esempio è solo un modello e serve come punto di partenza per costruire il tuo sistema, che potrebbe includere l'automazione della valutazione dei risultati e la registrazione dei modelli (p.5 e p.6 rispettivamente), oppure potresti aggiungere la versioning dei dataset, o forse qualcos'altro? Ho cercato di trasmettere l'idea che hai bisogno di MLOps in generale; MLflow è solo uno strumento per raggiungere questo obiettivo.
Quali problemi hai affrontato che non ho menzionato?
Cosa aggiungeresti al sistema per soddisfare le tue esigenze?
Quali strumenti e approcci utilizzi per affrontare tutti o parte dei problemi?
P.S. Ti lascio alcuni link:
progetto github —
MLflow —
La mia email di lavoro per domande — ikryakin@croc.ru
Nella nostra azienda vengono periodicamente organizzati eventi per professionisti IT, ad esempio: l'8 luglio alle 19:00 ora MSK ci sarà un meetup su CV in formato online; se sei interessato, puoi partecipare, registrati. .
Fonte: habr.com
