Es gibt eine Geschichte namens MLOps: "Lassen Sie uns eine Grundlage für den Betrieb eines Systems schaffen, das die Technologie des maschinellen Lernens ordnungsgemäß enthält, damit das Modell des maschinellen Lernens nicht veraltet und das System zum Müll wird." Referenzartikel: MLOps2020, das klein anfängt und groß wird
MLFlow ist ein Tool, das dabei helfen soll. Ich hatte die Möglichkeit, eine der Funktionen von MLflow, MLflow Tracking, zu verwenden. Ich dachte, es wäre gut, wenn ich es bei der Recherche verschiedener Dinge versuchen würde, also werde ich es hier schreiben. Nun, es gibt viele andere Artikel darüber, wie man es verwendet. Wenn Sie es sich also ansehen, können Sie es als Grundlage für Ideen verwenden, wie man ein Protokoll über die Modellkonstruktion führt. Glücklich. MLflow verwendete Version 1.8.0. Der folgende Artikel ist über MLflow leicht zu verstehen. Überlegen Sie, wie Sie mit mlflow den Datenanalysezyklus optimieren können MLflow 1.0.0 veröffentlicht! Starten Sie den Lebenszyklus des maschinellen Lernens!
Verwenden Sie Daten aus Kaggles Telco Customer Churn. https://www.kaggle.com/blastchar/telco-customer-churn Dies sind Daten über die Kunden der Telefongesellschaft und stellen ein binäres Klassifizierungsproblem dar, wobei die Zielvariable darin besteht, ob storniert werden soll oder nicht. Jede Zeile repräsentiert einen Kunden und jede Spalte enthält die Attribute des Kunden.
Erstellen Sie eine Funktion zur Visualisierung des Aggregationsergebnisses und eine Funktion zum Erstellen eines Modells. Da es nicht das Hauptthema ist, wird die Erklärung weggelassen.
Paket verwendet
# package
import numpy as np
import scipy
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import seaborn as sns
import pandas as pd
from pandas.plotting import register_matplotlib_converters
import xgboost
import xgboost.sklearn as xgb
import sklearn
from sklearn.model_selection import train_test_split
from sklearn.model_selection import KFold
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import accuracy_score
from sklearn.metrics import f1_score
from sklearn.metrics import auc
from sklearn.metrics import roc_curve
from sklearn.metrics import log_loss
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import cross_validate
from sklearn.cluster import KMeans
from sklearn.metrics import confusion_matrix
from sklearn.metrics import make_scorer
from sklearn.metrics import precision_recall_curve
import time
import os
import glob
from tqdm import tqdm
import copy
import mlflow
from mlflow.sklearn import log_model
from mlflow.sklearn import load_model
Definierte Funktionen
#Histogramm erstellen
def plot_many_hist(df_qiita,ex_col,ob_col,clip=[0, 99.],defalt_bin=10,png='tmp.png', visual = True):
fig=plt.figure(figsize=(15,10))
for i in range(len(ex_col)):
df_qiita_clip=df_qiita.copy()
col=ex_col[i]
#Ausschnitt
upperbound, lowerbound = np.percentile(df_qiita[col].values, clip)
col_clip = np.clip(df_qiita[col].values, upperbound, lowerbound)
df_qiita_clip['col_clip']=col_clip
#Anpassen der Anzahl der Fächer
if len(df_qiita_clip['col_clip'].unique())<10:
bins=len(df_qiita_clip['col_clip'].unique())
else:
bins=defalt_bin
#Histogrammplot
ax=plt.subplot(3,3,i+1)
for u in range(len(df_qiita_clip[ob_col].unique())):
ln1=ax.hist(df_qiita_clip[df_qiita_clip[ob_col]==u]['col_clip'], bins=bins,label=u, alpha=0.7)
ax.set_title(col)
h1, l1 = ax.get_legend_handles_labels()
ax.legend(loc='upper right')
ax.grid(True)
plt.tight_layout()
fig.suptitle("hist", fontsize=15)
plt.subplots_adjust(top=0.92)
plt.savefig(png)
if visual == True:
print('Cluster Hist')
plt.show()
else:
plt.close()
#Standardisierung
def sc_trans(X):
ss = StandardScaler()
X_sc = ss.fit_transform(X)
return X_sc
#kmeans Modellbildung
def km_cluster(X, k):
km=KMeans(n_clusters=k,\
init="k-means++",\
random_state=0)
y_km=km.fit_predict(X)
return y_km,km
#Kreisdiagrammerstellung
def pct_abs(pct, raw_data):
absolute = int(np.sum(raw_data)*(pct/100.))
return '{:d}\n({:.0f}%)'.format(absolute, pct) if pct > 5 else ''
def plot_chart(y_km, png='tmp.png', visual = True):
km_label=pd.DataFrame(y_km).rename(columns={0:'cluster'})
km_label['val']=1
km_label=km_label.groupby('cluster')[['val']].count().reset_index()
fig=plt.figure(figsize=(5,5))
ax=plt.subplot(1,1,1)
ax.pie(km_label['val'],labels=km_label['cluster'], autopct=lambda p: pct_abs(p, km_label['val']))#, autopct="%1.1f%%")
ax.axis('equal')
ax.set_title('Cluster Chart (ALL UU:{})'.format(km_label['val'].sum()),fontsize=14)
plt.savefig(png)
if visual == True:
print('Cluster Structure')
plt.show()
else:
plt.close()
#Tabellenerstellung
def plot_table(df_qiita, cluster_name, png='tmp.png', visual = True):
fig, ax = plt.subplots(figsize=(10,10))
ax.axis('off')
ax.axis('tight')
tab=ax.table(cellText=np.round(df_qiita.groupby(cluster_name).mean().reset_index().values, 2),\
colLabels=df_qiita.groupby(cluster_name).mean().reset_index().columns,\
loc='center',\
bbox=[0,0,1,1])
tab.auto_set_font_size(False)
tab.set_fontsize(12)
tab.scale(5,5)
plt.savefig(png)
if visual == True:
print('Cluster Stats Mean')
plt.show()
else:
plt.close()
#XGB-Modellerstellung
def xgb_model(X_train, y_train, X_test):
model = xgb.XGBClassifier()
model.fit(X_train, y_train)
y_pred=model.predict(X_test)
y_pred_proba=model.predict_proba(X_test)[:, 1]
y_pred_proba_both=model.predict_proba(X_test)
return model, y_pred, y_pred_proba, y_pred_proba_both
#Erstellung von Trainingsdaten und Testdaten
def createXy(df, exp_col, ob_col, test_size=0.3, random_state=0, stratify=True):
dfx=df[exp_col].copy()
dfy=df[ob_col].copy()
print('exp_col:',dfx.columns.values)
print('ob_col:',ob_col)
if stratify == True:
X_train, X_test, y_train, y_test = train_test_split(dfx, dfy, test_size=test_size, random_state=random_state, stratify=dfy)
else:
X_train, X_test, y_train, y_test = train_test_split(dfx, dfy, test_size=test_size, random_state=random_state)
print('Original Size is {}'.format(dfx.shape))
print('TrainX Size is {}'.format(X_train.shape))
print('TestX Size is {}'.format(X_test.shape))
print('TrainY Size is {}'.format(y_train.shape))
print('TestY Size is {}'.format(y_test.shape))
return X_train, y_train, X_test, y_test
#Gibt das Ergebnis des Klassifizierungsbewertungsindex zurück
def eval_list(y_test, y_pred, y_pred_proba, y_pred_proba_both):
# eval
log_loss_=log_loss(y_test, y_pred_proba_both)
accuracy=accuracy_score(y_test, y_pred)
precision=precision_score(y_test, y_pred)
recall=recall_score(y_test, y_pred)
# FPR, TPR, thresholds
fpr, tpr, thresholds = roc_curve(y_test, y_pred_proba)
# AUC
auc_ = auc(fpr, tpr)
# roc_curve
fig, ax = plt.subplots(figsize=(10,10))
ax.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %.2f)'%auc_)
ax.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.legend()
plt.title('ROC curve')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.grid(True)
plt.savefig('ROC_curve.png')
plt.close()
return log_loss_, accuracy, precision, recall, auc_
# Recall-Präzisionskurve kehrt zurück
def threshold_pre_rec(test, prediction, save_name='threshold_pre_rec.png'):
precision, recall, threshold = precision_recall_curve(test, prediction)
thresholds = threshold
user_cnt=[prediction[prediction>=i].shape[0] for i in thresholds]
fig=plt.figure(figsize=(10,6))
ax1 = plt.subplot(1,1,1)
ax2=ax1.twinx()
ax1.plot(thresholds, precision[:-1], color=sns.color_palette()[0],marker='+', label="precision")
ax1.plot(thresholds, recall[:-1], color=sns.color_palette()[2],marker='+', label="recall")
ax2.plot(thresholds, user_cnt, linestyle='dashed', color=sns.color_palette()[6], label="user_cnt")
handler1, label1 = ax1.get_legend_handles_labels()
handler2, label2 = ax2.get_legend_handles_labels()
ax1.legend(handler1 + handler2, label1 + label2, loc='lower left')
ax1.set_xlim(-0.05,1.05)
ax1.set_ylim(-0.05,1.05)
ax1.set_xlabel('threshold')
ax1.set_ylabel('%')
ax2.set_ylabel('user_cnt')
ax2.grid(False)
plt.savefig(save_name)
plt.close()
#Voraussichtliche Wahrscheinlichkeitsrenditen Gemessene Wahrscheinlichkeitskurve
def calib_curve(y_tests, y_pred_probas, save_name='calib_curve.png'):
y_pred_proba_all=y_pred_probas.copy()
y_tests_all=y_tests.copy()
proba_check=pd.DataFrame(y_tests_all.values,columns=['real'])
proba_check['pred']=y_pred_proba_all
s_cut, bins = pd.cut(proba_check['pred'], list(np.linspace(0,1,11)), right=False, retbins=True)
labels=bins[:-1]
s_cut = pd.cut(proba_check['pred'], list(np.linspace(0,1,11)), right=False, labels=labels)
proba_check['period']=s_cut.values
proba_check = pd.merge(proba_check.groupby(['period'])[['real']].mean().reset_index().rename(columns={'real':'real_ratio'})\
, proba_check.groupby(['period'])[['real']].count().reset_index().rename(columns={'real':'UU'})\
, on=['period'], how='left')
proba_check['period']=proba_check['period'].astype(str)
proba_check['period']=proba_check['period'].astype(float)
fig=plt.figure(figsize=(10,6))
ax1 = plt.subplot(1,1,1)
ax2=ax1.twinx()
ax2.bar(proba_check['period'].values, proba_check['UU'].values, color='gray', label="user_cnt", width=0.05, alpha=0.5)
ax1.plot(proba_check['period'].values, proba_check['real_ratio'].values, color=sns.color_palette()[0],marker='+', label="real_ratio")
ax1.plot(proba_check['period'].values, proba_check['period'].values, color=sns.color_palette()[2], label="ideal_line")
handler1, label1 = ax1.get_legend_handles_labels()
handler2, label2 = ax2.get_legend_handles_labels()
ax1.legend(handler1 + handler2, label1 + label2, loc='center right')
ax1.set_xlim(-0.05,1.05)
ax1.set_ylim(-0.05,1.05)
ax1.set_xlabel('period')
ax1.set_ylabel('real_ratio %')
ax2.set_ylabel('user_cnt')
ax2.grid(False)
plt.savefig(save_name)
plt.close()
#Gemischte Matrix ausgeben
def print_cmx(y_true, y_pred, save_name='tmp.png'):
labels = sorted(list(set(y_true)))
cmx_data = confusion_matrix(y_true, y_pred, labels=labels)
df_cmx = pd.DataFrame(cmx_data, index=labels, columns=labels)
plt.figure(figsize = (10,6))
sns.heatmap(df_cmx, annot=True, fmt='d', cmap='coolwarm', annot_kws={'fontsize':20},alpha=0.8)
plt.xlabel('pred', fontsize=18)
plt.ylabel('real', fontsize=18)
plt.savefig(save_name)
plt.close()
Da dies nicht das Hauptthema ist, wird die fehlende Zeile unverändert gelöscht.
#Daten gelesen
df=pd.read_csv('WA_Fn-UseC_-Telco-Customer-Churn.csv')
churn=df.copy()
#Ändern Sie den Rohling mit halber Breite in Nan
churn.loc[churn['TotalCharges']==' ', 'TotalCharges']=np.nan
#Wechseln Sie zu float
churn['TotalCharges']=churn['TotalCharges'].astype(float)
#Wenn eine Zeile fehlt, weil sie problematisch ist, löschen Sie diese Zeile
churn=churn.dropna()
print(churn.info())
display(churn.head())
Nach dem Clustering mit Kmenas usw. interpretieren Menschen das Clustering-Ergebnis, indem sie die Eigenschaften jedes Clusters betrachten. Es ist jedoch schwierig, eine Tabelle zu visualisieren und zu erstellen, um die Eigenschaften des Clusters jedes Mal durch Ausprobieren anzuzeigen, und Sie können vergessen, was das vorherige Ergebnis war. MLflow kann verwendet werden, um dieses Problem zu lösen. Das Clustering wird durchgeführt, indem die erklärenden Variablen auf kontinuierliche Werte von'tenure ',' MonthlyCharges 'und'TotalCharges' eingegrenzt werden. Das Ergebnis wird in MLflow aufgezeichnet.
####Clustering-Implementierung
exp_col=['tenure','MonthlyCharges','TotalCharges']
df_km=churn.copy()[exp_col]
df_cluster=df_km.copy()
cluster_name = 'My_Cluster'
k=5
ob_col = cluster_name
#Notieren Sie das Clustering-Ergebnis in mlflow
mlflow.set_experiment('My Clustering')#Definieren Sie den Namen des Experiments
with mlflow.start_run():#mlflow-Aufzeichnung gestartet
#Standardisierung
X=sc_trans(df_cluster)
#kmeans Modellbildung
y_km, km=km_cluster(X, k)
#Notieren Sie die Parameter in mlflow
mlflow.log_param("method_name",km.__class__.__name__)
mlflow.log_param("k", k)
mlflow.log_param("features", df_cluster.columns.values)
#Modell in mlflow speichern
log_model(km, "model")
df_cluster[cluster_name]=y_km
#Visualisieren Sie Clustering-Ergebnisse
#Cluster-Zusammensetzungsverhältnis
plot_chart(y_km, png='Cluster_Chart.png', visual = False)#Speichern Sie das Diagramm im aktuellen Verzeichnis
mlflow.log_artifact('Cluster_Chart.png')#Notieren Sie das Diagramm im aktuellen Verzeichnis
os.remove('Cluster_Chart.png')#Löschte die Figur im aktuellen Verzeichnis nach der Aufnahme
#Durchschnittswert pro Cluster
plot_table(df_cluster, ob_col, png='Cluster_Stats_Mean.png', visual = False)#Speichern Sie das Diagramm im aktuellen Verzeichnis
mlflow.log_artifact('Cluster_Stats_Mean.png')#Notieren Sie das Diagramm im aktuellen Verzeichnis
os.remove('Cluster_Stats_Mean.png')#Löschte die Figur im aktuellen Verzeichnis nach der Aufnahme
#Grapher nach Cluster
plot_many_hist(df_cluster,exp_col,ob_col,clip=[0, 99.],defalt_bin=20, png='Cluster_Hist.png', visual = False)#Speichern Sie das Diagramm im aktuellen Verzeichnis
mlflow.log_artifact('Cluster_Hist.png')#Notieren Sie das Diagramm im aktuellen Verzeichnis
os.remove('Cluster_Hist.png')#Löschte die Figur im aktuellen Verzeichnis nach der Aufnahme
Wie oben erwähnt, wird im aktuellen Verzeichnis ein Ordner mit dem Namen "mlruns" erstellt, wenn Sie den Code ausführen, der den Algorithmusnamen, den Namen der erklärenden Variablen, den hohen Para-Wert und das Diagramm aufzeichnet, das die Eigenschaften jedes Clusters visualisiert. Alle aufgezeichneten Ergebnisse werden in diesem Ordner namens "mlruns" gespeichert. Wenn Sie ein Terminal in dem Verzeichnis öffnen, das den Ordner "mlruns" enthält, "mlflow ui" schreiben und ausführen, wird localhost number 5000 gestartet. Wenn Sie mit Ihrem Browser auf localhost 5000 zugreifen, können Sie den Datensatz des Modells anzeigen, das über die umfangreiche Benutzeroberfläche von MLflow erstellt wurde.
Ordner "mlruns" Schreiben Sie "mlflow ui" in das Verzeichnis mit dem Ordner "mlruns". mlflow ui oberer Bildschirm
Die Clustering-Ergebnisse werden in einem Raum mit dem Namen "Mein Clustering" aufgezeichnet. Überprüfen Sie den Link mit Datum und Uhrzeit der Aufnahme, um zu sehen, was aufgezeichnet wurde.
Parameters, Metrics
Artifacts
Artifacts
Artifacts
Es kann bestätigt werden, dass der aufzuzeichnende Algorithmusname, der Name der erklärenden Variablen und der hohe Para-Wert in Parametern aufgezeichnet werden. Diagramme und andere Informationen werden in Artefakten aufgezeichnet. Die Aufzeichnung auf diese Weise erleichtert den Vergleich der Ergebnisse des vorherigen Modells, selbst wenn die erklärenden Variablen oder der Wert von k geändert werden.
Dasselbe kann beim Erstellen eines Klassifizierungsmodells aufgezeichnet werden.
####Erstellen Sie ein Vorhersagemodell
exp_col=['tenure','MonthlyCharges','TotalCharges']
ob_col = 'Churn'
df_pred=churn.copy()
df_pred.loc[df_pred[ob_col]=='Yes', ob_col]=1
df_pred.loc[df_pred[ob_col]=='No', ob_col]=0
df_pred[ob_col]=df_pred[ob_col].astype(int)
df_pred[cluster_name]=y_km
X_tests, y_tests, y_preds, y_pred_probas, y_pred_proba_boths = [],[],[],[],[]
for cluster_num in np.sort(df_pred[cluster_name].unique()):
#Extrahieren Sie Daten aus einem Cluster
df_n=df_pred[df_pred[cluster_name]==cluster_num].copy()
#Erstellung von Trainingsdaten und Testdaten
X_train, y_train, X_test, y_test=createXy(df_n, exp_col, ob_col, test_size=0.3, random_state=0, stratify=True)
#Modellieren
model, y_pred, y_pred_proba, y_pred_proba_both = xgb_model(X_train, y_train, X_test)
#Bewertungsindexberechnung
log_loss_, accuracy, precision, recall, auc_ = eval_list(y_test, y_pred, y_pred_proba, y_pred_proba_both)
#Fügen Sie Daten in eine leere Liste ein
X_tests.append(X_test)
y_tests.append(y_test)
y_preds.append(y_pred)
y_pred_probas.append(y_pred_proba)
y_pred_proba_boths.append(y_pred_proba_both)
#Gemischte Matrix
print_cmx(y_test.values, y_pred, save_name='confusion_matrix.png')
# Recall-Präzisionskurve
threshold_pre_rec(y_test, y_pred_proba, save_name='threshold_pre_rec.png')
#Pred Prob Kurve
calib_curve(y_test,y_pred_proba, save_name='calib_curve.png')
#Notieren Sie das Vorhersageergebnis in mlflow
mlflow.set_experiment('xgb_predict_cluster'+str(cluster_num))#Definieren Sie den Namen des Experiments
with mlflow.start_run():#mlflow-Aufzeichnung gestartet
mlflow.log_param("01_method_name", model.__class__.__name__)
mlflow.log_param("02_features", exp_col)
mlflow.log_param("03_objective_col", ob_col)
mlflow.log_params(model.get_xgb_params())
mlflow.log_metrics({"01_accuracy": accuracy})
mlflow.log_metrics({"02_precision": precision})
mlflow.log_metrics({"03_recall": recall})
mlflow.log_metrics({"04_log_loss": log_loss_})
mlflow.log_metrics({"05_auc": auc_})
mlflow.log_artifact('ROC_curve.png')
os.remove('ROC_curve.png')
mlflow.log_artifact('confusion_matrix.png')
os.remove('confusion_matrix.png')
mlflow.log_artifact('threshold_pre_rec.png')
os.remove('threshold_pre_rec.png')
mlflow.log_artifact('calib_curve.png')
os.remove('calib_curve.png')
log_model(model, "model")
#Konzentrieren Sie die Daten für jeden Cluster und fügen Sie alle Daten zusammen
y_pred_all=np.hstack((y_preds))
y_pred_proba_all=np.hstack((y_pred_probas))
y_pred_proba_both_all=np.concatenate(y_pred_proba_boths)
y_tests_all=pd.concat(y_tests)
#Bewertungsindexberechnung
log_loss_, accuracy, precision, recall, auc_ = eval_list(y_tests_all.values, y_pred_all, y_pred_proba_all, y_pred_proba_both_all)
#Gemischte Matrix
print_cmx(y_tests_all.values, y_pred_all, save_name='confusion_matrix.png')
#Pred Prob Kurve
calib_curve(y_tests_all, y_pred_proba_all, save_name='calib_curve.png')
#Notieren Sie das Vorhersageergebnis aller Daten in mlflow
mlflow.set_experiment('xgb_predict_all')#Definieren Sie den Namen des Experiments
with mlflow.start_run():#mlflow-Aufzeichnung gestartet
mlflow.log_param("01_method_name", model.__class__.__name__)
mlflow.log_param("02_features", exp_col)
mlflow.log_param("03_objective_col", ob_col)
mlflow.log_params(model.get_xgb_params())
mlflow.log_metrics({"01_accuracy": accuracy})
mlflow.log_metrics({"02_precision": precision})
mlflow.log_metrics({"03_recall": recall})
mlflow.log_metrics({"04_log_loss": log_loss_})
mlflow.log_metrics({"05_auc": auc_})
mlflow.log_artifact('ROC_curve.png')
os.remove('ROC_curve.png')
mlflow.log_artifact('confusion_matrix.png')
os.remove('confusion_matrix.png')
mlflow.log_artifact('calib_curve.png')
os.remove('calib_curve.png')
Wenn Sie den obigen Code ausführen, wird für jeden Cluster ein Modell erstellt und in MLflow aufgezeichnet. Sie können Algorithmusnamen, erklärende Variablennamen, High-Para-Werte, Verlustfunktionen, Klassifizierungsgenauigkeit verschiedener Indikatoren, ROC-Kurve, Kalibrierungskurve, Rückruf, Präzisionskurve, gemischte Matrix usw. aufzeichnen.
mlflow oberer Bildschirm
Parameters
Metrics
Artifacts
Die Aufzeichnung auf diese Weise erleichtert den Vergleich der Ergebnisse des vorherigen Modells, wenn die erklärenden Variablen geändert, die High-Para-Anpassung vorgenommen oder der Algorithmus geändert wird.
Obwohl es auch als Memorandum dient, habe ich MLflow überhaupt nicht erklärt und hauptsächlich gezeigt, wie man es so benutzt. Es wäre großartig, wenn der Inhalt ein Bild der Menschen vermitteln würde, die darüber nachdenken, ihn in Zukunft zu verwenden. Wenn Sie interessiert sind, empfehle ich Ihnen, andere Artikel zu überprüfen und zu verwenden.
Inhalt des Ordners "mlruns"
Klicken Sie auf 1
Klicken Sie auf b3fa3eb983044a259e6cae4f149f32c8
Klicken Sie auf Artefakte
Die Figur wird gespeichert Was mit mlflow ui bestätigt werden kann, wird wie folgt in Local gespeichert. Es scheint möglich zu sein, Modelldatensätze in Zusammenarbeit mit Cloud-Diensten mit verschiedenen Personen zu teilen. Gibt es ein Problem mit Local für den persönlichen Gebrauch?
das ist alles!