Совместная работа и эксперименты стали проще

Моя цель в этом посте — описать, как команда по науке о данных / машинному обучению может сотрудничать для обучения модели предсказанию вида пингвина в наборе данных пингвинов Палмера. Каждый член команды имеет следующие обязанности:

Бильбо: 1) собрать необработанные данные

from sklearn.datasets import fetch_openml

def load_and_save_data(data_id=42585):
    X,Y = fetch_openml(data_id=data_id, return_X_y=True, parser='auto')
    
    names = ["Features", "Outcomes"]
    
    dataset = dict()

    for name,file in zip(names,[X,Y]):
        path = f'./datasets/{name}.csv'
        file.to_csv(path)
        dataset[name] = dict( {'data':file , 'path':path } )
    
    return dataset

Бильбо: 2) создать проект и записать необработанные данные

import wandb

with wandb.init(project="penguins-LOTR", job_type="load-raw-data"
                                       , config = dict(user='Bilbo') ) as run:
    
    # load data
    dataset = load_and_save_data(data_id=42585)
    
    # create artificat
    raw_data = wandb.Artifact(name='penguins-raw'
                               , type='raw-XandY'
                               , description = 'Data pulled from openML using sklearn'
                               , metadata = { 'source'  : "fetch_openml(data_id=data_id, return_X_y=True, parser='auto') " 
                                            }
                               )
    #associate files with artifact
    for file in dataset.keys():
        raw_data.add_file(dataset[file]['path'], name = file)
        
    #log event
    run.log_artifact(raw_data)

Боромир: 3) преобразовать функции в горячее кодирование и разделить данные для обучения и тестирования

import os
import wandb
import pandas as pd
from sklearn.model_selection import train_test_split

with wandb.init(project="penguins-LOTR", job_type="transform-raw-data", config = dict(user='Boromir') ) as run:
    
    # get raw data  & copy to local dir, this is not actuallt downloaded if already in your system
    raw_data = run.use_artifact('data-tonalli/penguins-LOTR/penguins-raw:latest', type='raw-XandY')   
    artifact_dir = raw_data.download()
    
    print (os.system(f'ls -lhrt {artifact_dir}' ) )

    # get data
    X = pd.read_csv(f'{artifact_dir}/Features.csv').drop(['Unnamed: 0'],axis=1)
    Y = pd.read_csv(f'{artifact_dir}/Outcomes.csv').drop(['Unnamed: 0'],axis=1)

    # transform and split
    X_one_hot = pd.get_dummies(X).replace([True,False],[1,0])
    X_train, X_test, y_train, y_test = train_test_split( X_one_hot, Y, test_size=0.33, random_state=42)
    
    # create artifact
    one_hot_art = wandb.Artifact(  name='data-split-oneHot', type='dataset')

    # add files
    names = ['X_train', 'X_test', 'y_train', 'y_test']
    objs  = [X_train, X_test, y_train, y_test ]
    
    for N,F in zip(names,objs):
        p = f'./{N}.csv'
        F.to_csv(p, index=False)
        one_hot_art.add_file(p)
        
    #log work
    run.log_artifact(one_hot_art)

Гэндальф: 4) Обучить классификатор повышения градиента гистограммы без дальнейшей обработки данных.

with wandb.init(project="penguins-LOTR", job_type="train-HGB-clf", config = dict(user='Gandalf') ) as run:
    art_name = 'data-tonalli/penguins-LOTR/data-split-oneHot:latest'
    local_path = run.use_artifact(art_name).download()

    print (os.system(f'ls -lhrt {local_path}' ) )

    Xtrain = pd.read_csv(f'{local_path}/X_train.csv')
    Ytrain = pd.read_csv(f'{local_path}/y_train.csv')

    Xtest = pd.read_csv(f'{local_path}/X_test.csv')
    Ytest = pd.read_csv(f'{local_path}/y_test.csv')
    
    # train
    clf = HGB_clf(verbose=0, max_depth=2, max_iter=2000, early_stopping=True, n_iter_no_change=5).fit(X_train, y_train.values.ravel() )
    
    # update config
    wandb.config.update(clf.get_params())

    # log classificaton metrics
    species = ['Adelie','Chinstrap','Gentoo']
    R = metrics.classification_report(Ytest, clf.predict(Xtest), output_dict=True )

    for sp in species:
        run.log(  { f'test_{sp}':  R[sp] } )

    # log confusion matrix
    le = LabelEncoder().fit(Ytrain.values.ravel())
    y_true = le.transform(Ytest.values.ravel())

    wandb.log(  { 'confusion_matrix':  wandb.plot.confusion_matrix(probs = clf.predict_proba(X_test) , y_true=y_true, class_names=le.classes_)} )

    # log model
    model_artifact = wandb.Artifact( "GB_SK", type="model" )

    model_path = './Gandalf_classifier.joblib'
    dump(clf, model_path) 

    model_artifact.add_file(model_path)
    run.log_artifact(model_artifact)

родословная модели будет выглядеть примерно так:

посмотреть проект можно здесь