Как выбрать и запустить модель из выпадающего меню и обновить рисунок матрицы путаницы? - PullRequest
0 голосов
/ 06 ноября 2019

Я создаю приложение для прогнозирования ML на основе этого набора данных по раку молочной железы .

В раскрывающемся меню я хочу выбрать одну из моих моделей и запустить примеркуи верните обновленную матрицу путаницы (тепловая карта).

Я планирую расширить сценарий на таблицы, кривые roc, кривые обучения и т. д. (т. е. многоканальный обратный вызов )- но сначала я хочу, чтобы эта часть работала, прежде чем реализовывать другие элементы.

Я пробовал разные вещи.

Например, перед текущим кодом (ниже) я пытался вызвать модель из выпадающего меню напрямую, а затем выполнить все вычисления cm внутри результатов обратного вызова. в AttributeError: у объекта 'str' нет атрибута 'fit' :

@app.callback(Output('conf_matrix', 'figure'), [Input('dropdown-5', 'value')])
def update_cm_matix(model):
    class_names=[0,1]
    fitModel = model.fit(X_train, y_train)
    y_pred = fitModel.predict(X_test)
    cm = confusion_matrix(y_test, y_pred)
    return {'data': [go.Heatmap(x=class_names, y=class_names, z=cm, showscale=True, colorscale='blues')],
            'layout': dict(width=350, height=280, margin={'t': 10},
                       xaxis=dict(title='Predicted class', tickvals=[0, 1]),
                       yaxis=dict(title='True class', tickvals=[0, 1], autorange='reversed'))}

(замена app.callback и функции в приведенном ниже скрипте).

Текущая версия, с которой я борюсь:

# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.metrics import confusion_matrix
from sklearn.feature_selection import RFE
import plotly.graph_objs as go
from dash.dependencies import Input, Output

app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
server = app.server

app.config.suppress_callback_exceptions = True

df = pd.read_csv("breast_cancer.csv")
y = np.array(df.diagnosis.tolist())
data = df.drop('diagnosis', 1)
X = np.array(data.values)

scaler = StandardScaler()
X = scaler.fit_transform(X)

random_state = 42
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=random_state)

# First model: logistic model + optimize hyperparameters
log = LogisticRegression(random_state=random_state)
param_grid = {'penalty': ['l2', 'l1'], 'C': [0.001, 0.01, 0.1, 1, 10, 100, 1000]}
CV_log = GridSearchCV(estimator=log, param_grid=param_grid,, scoring='accuracy', verbose=1, n_jobs=-1)
CV_log.fit(X_train, y_train)
log_best_params = CV_log.best_params_
log_clf = LogisticRegression(C=log_best_params['C'], penalty=log_best_params['penalty'], random_state=random_state)

# Second model: logistic model with recursive features elimination (just for illustration purposes, other models will be included)
rfe_selector = RFE(log_clf)

# app layout
app.layout = html.Div([
    html.Div([
        dcc.Dropdown(
            id='dropdown-5',
            options=[{'label': 'Logistic', 'value': 'log_clf'},
                     {'label': 'RFE', 'value': 'rfe_selector'}],
            value='log_clf',
            style={'width': '150px', 'height': '35px', 'fontSize': '10pt'}
        )], style={}),

    html.Div([
        dcc.Graph(id='conf_matrix')
    ])
])

# function to run selected model
def ClassTrainEval(model):
    fitModel = model.fit(X_train, y_train)
    y_pred = fitModel.predict(X_test)
    cm = confusion_matrix(y_test, y_pred)
    return fitModel, y_pred, y_score, cm

models = [log_clf, rfe_selector]
class_names = [0,1]

# dash callback
@app.callback(Output('conf_matrix', 'figure'), [Input('dropdown-5', 'value')])
def update_cm_matix(model):
    for model in models:
        ClassTrainEval(model)
    return {'data': [go.Heatmap(x=class_names, y=class_names, z=cm, showscale=True, colorscale='blues')],
            'layout': dict(width=350, height=280, margin={'t': 10},
                           xaxis=dict(title='Predicted class', tickvals=[0, 1]),
                           yaxis=dict(title='True class', tickvals=[0, 1], autorange='reversed'))}

if __name__ == '__main__':
    app.run_server(debug=True)

Где я получаю NameError: имя 'cm' не определено ошибка.

Я не совсем уверен, как двигаться вперед, чтобы заставить это работать - поэтому я надеюсь, что кто-то может направить меня в правильном направлении.

Спасибо!

1 Ответ

1 голос
/ 06 ноября 2019

В вашем коде много ошибок. давайте сначала выполним ваши две попытки.

dcc.Dropdown(
        id='dropdown-5',
        options=[{'label': 'Logistic', 'value': 'log_clf'},
                 {'label': 'RFE', 'value': 'rfe_selector'}],
        value='log_clf',
        style={'width': '150px', 'height': '35px', 'fontSize': '10pt'}
    )], style={})

в вашем раскрывающемся списке, модель представляет собой строку (type('log_clf') == str), поэтому вы не можете обучить ее. вам нужно написать обратный вызов следующим образом:

models = {'Logistic':log_clf, 'RFE':rfe_selector}
""""i jumped some line of code"""
dcc.Dropdown(
        id='dropdown-5',
        options=[{'label': v, 'value': v} for v in ['Logistic','RFE']],
        value='Logistic',
        style={'width': '150px', 'height': '35px', 'fontSize': '10pt'}
    )

для второй попытки, вам также нужна строка, чтобы адаптироваться к внесенным мною изменениям:

ошибка была: NameError: name 'cm' is not defined error (я предполагаю, что это произошло в обратном вызове) и происходит потому, что вы не присвоили выходные данные функции переменным:

функция была

# function to run selected model
def ClassTrainEval(model):
    fitModel = model.fit(X_train, y_train)
    y_pred = fitModel.predict(X_test)
    cm = confusion_matrix(y_test, y_pred)
    return fitModel, y_pred, y_score, cm #Note that y_score is never defined so you need to remove this 

, а затем в обратном вызове вы получили:

# dash callback
@app.callback(Output('conf_matrix', 'figure'), [Input('dropdown-5', 'value')])
def update_cm_matix(model):
    for model in models: #<-------No loop needed
        ClassTrainEval(model) #<-------Here You need to assigne the output
    return {'data': [go.Heatmap(x=class_names, y=class_names, z=cm, showscale=True, colorscale='blues')],
            'layout': dict(width=350, height=280, margin={'t': 10},
                           xaxis=dict(title='Predicted class', tickvals=[0, 1]),
                           yaxis=dict(title='True class', tickvals=[0, 1], autorange='reversed'))}

Вы можете написать:

@app.callback(Output('conf_matrix', 'figure'), [Input('dropdown-5', 'value')])
def update_cm_matix(v):
    model = models[v]
    fitModel, y_pred, cm =  ClassTrainEval(model)
    return {'data': [go.Heatmap(x=class_names, y=class_names, z=cm, showscale=True, colorscale='blues')],
            'layout': dict(width=350, height=280, margin={'t': 10},
                           xaxis=dict(title='Predicted class', tickvals=[0, 1]),
                           yaxis=dict(title='True class', tickvals=[0, 1], autorange='reversed'))}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...