Un esempio

Questo esempio mostrerà come il concetto di flusso di lavoro agile può creare un grande valore. Questo è un esempio molto semplice che ha lo scopo di visualizzare questo concetto. Gli esempi di vita reale saranno molto meno ovvi, ma l'idea che vedrai qui è altrettanto rilevante.

Diamo un'occhiata a questi dati bidimensionali che ho simulato da tre classi di uguali dimensioni.

num_samples_A = 500
num_samples_B = 500
num_samples_C = 500

# Class A
mean_A = (3, 2)
cov_A = ((0.1, 0), (0, 0.1)) # Low variance
class_A = np.random.multivariate_normal(mean_A, cov_A, num_samples_A)

# Class B
mean_B = (0, 0)
cov_B = ((1, 0.5), (0.5, 1)) # Larger variance with some overlap with class C
class_B = np.random.multivariate_normal(mean_B, cov_B, num_samples_B)

# Class C
mean_C = (0, 1)
cov_C = ((2, 0.5), (0.5, 2)) # Larger variance with some overlap with class B
class_C = np.random.multivariate_normal(mean_C, cov_C, num_samples_C)

Un grafico che ho creato per visualizzare i dati simulati
Dati bidimensionali da tre classi

Ora proviamo ad adattare un classificatore di apprendimento automatico a questi dati, sembra che un classificatore SVM con un kernel gaussiano (“rbf”) potrebbe fare il trucco:

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC

# Creating DataFrame
data = np.concatenate((class_A, class_B, class_C))
labels = np.concatenate((np.zeros(num_samples_A), np.ones(num_samples_B), np.ones(num_samples_C) * 2))
df = pd.DataFrame(data, columns=('x', 'y'))
df('label') = labels.astype(int)

# Splitting data into train and test sets
X_train, X_test, y_train, y_test = train_test_split(df(('x', 'y')), df('label'), test_size=0.2, random_state=42)

# Training SVM model with RBF kernel
svm_rbf = SVC(kernel='rbf', probability= True)
svm_rbf.fit(X_train, y_train)

# Predict probabilities for each class
svm_rbf_probs = svm_rbf.predict_proba(X_test)

# Get predicted classes and corresponding confidences
svm_rbf_predictions = ((X_test.iloc(i)('x'), X_test.iloc(i)('y'), true_class, np.argmax(probs), np.max(probs)) for i, (true_class, probs) in enumerate(zip(y_test, svm_rbf_probs)))

svm_predictions_df = pd.DataFrame(svm_rbf_predictions).rename(columns={0:'x',1:'y' ,2: 'true_class', 3: 'predicted_class', 4: 'confidence'})

Come si comporta questo modello sui nostri dati?

accuracy = (svm_predictions_df('true_class') == svm_predictions_df('predicted_class')).mean()*100
print(f'Accuracy = {round(accuracy,2)}%')

Precisione = 75,33%

Una precisione del 75% è deludente, ma questo significa che questo modello è inutile?

Ora vogliamo esaminare le previsioni più attendibili e vedere come si comporta il modello su di esse. Come definiamo le previsioni più attendibili? Possiamo provare diverse soglie di confidenza (predict_proba) e vedere quale copertura e precisione otteniamo per ciascuna soglia e quindi decidere quale soglia soddisfa le nostre esigenze aziendali.

thresholds = (.5, .55, .6, .65, .7, .75, .8, .85, .9)
results = ()

for threshold in thresholds:
svm_df_covered = svm_predictions_df.loc(svm_predictions_df('confidence') > threshold)
coverage = len(svm_df_covered) / len(svm_predictions_df) * 100
accuracy_covered = (svm_df_covered('true_class') == svm_df_covered('predicted_class')).mean() * 100

results.append({'Threshold': threshold, 'Coverage (%)': round(coverage,2), 'Accuracy on covered data (%)': round(accuracy_covered,2)})

results_df = pd.DataFrame(results)
print(results_df)

E otteniamo

La tabella risultante dal blocco di codice precedente
Copertura e accuratezza per tabella delle soglie

Oppure, se desideriamo uno sguardo più dettagliato, possiamo creare un grafico della copertura e dell'accuratezza per soglia:

Un grafico lineare dell'accuratezza e della copertura del modello sui dati simulati per varie soglie
Precisione e copertura come funzione di soglia

Ora possiamo selezionare la soglia che si adatta alla nostra logica aziendale. Ad esempio, se la politica della nostra azienda è garantire almeno il 90% di precisione, allora possiamo scegliere una soglia di 0,75 e ottenere una precisione del 90% per il 62% dei dati. Questo è un enorme miglioramento rispetto all'eliminazione del modello, soprattutto se non ne abbiamo alcuno in produzione!

Ora che il nostro modello funziona felicemente in produzione sul 60% dei dati, possiamo spostare la nostra attenzione sul resto dei dati. Possiamo raccogliere più dati, progettare più funzionalità, provare modelli più complessi o ottenere assistenza da un esperto di dominio.

Fonte: towardsdatascience.com

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *