0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Dashで作る機械学習アプリ

Posted at

はじめに

default of credit card clients Data Setデータを使って、基礎分析や簡単な分類モデルの構築などを行ってきた。せっかくなので動かせるものを作ろうと思い、Dashを用いたウェブアプリの作成を行った。機械学習アプリと名乗るにはおこがましい出来だが、どうぞご容赦を・・・。

アプリのイメージ

上記データには債権者がデフォルトするかしないかを示すフラグ "default payment next month" という項目があるので、デフォルトの分類モデルを作る。アプリのイメージは以下。

  1. ロジスティック回帰、決定木、サポートベクターマシンの3種類からモデルを選択
  2. 説明変数(量的変数、質的変数)を複数選択
  3. 上記2項目を設定後、決定ボタンを押すことで学習開始
  4. 学習結果を表示

とりあえず動くものができればいいので、機械学習の精度とデザインは一旦置いておく。

コールバック関数の引数State

今回のアプリを作成するにあたり、Dashでウェブアプリ作成①Dashでウェブアプリ作成②Dashで世界遺産を世界地図にプロットあたりで学習したこと以外で、dash.dependenciesライブラリの__State__が便利だったので書いておく。
もともとコールバック関数の引数としては Input(と Output )しか知らなかったため、上記1および2にて項目を選択する度にコールバック関数が呼び出されてしまっていた。これはイメージしたものと違うなと感じ調査したところ、State なるものを見つけた。Input と使い方はほぼ同様だが、State はコールバック関数を呼び出すトリガーにはならないらしい。上記1と2で選択した情報は State としてコールバック関数に渡して、3の決定ボタンをトリガーに State の情報をもとに学習するようにすれば、イメージ通りのものが作れるはず。

上記を踏まえたコードは以下に示す。(①CSV形式に直したデータセット、②標準化およびダミー変数化などの前処理後データが必要。過去記事ありきのコードとなってしまっているため、このままでは実行できない。。。)

app.py
# Run this app with `python app.py` and
# visit http://127.0.0.1:8050/ in your web browser.

import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State
import plotly.express as px
import pandas as pd

# For models
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve, roc_auc_score
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
# from sklearn.preprocessing import StandardScaler

df = pd.read_csv(
    "c:/***/data/default_of_credit_card_clients.csv", header=1, index_col=0)
col = df.columns.values
quantity_col = col[[0, 4, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]]
quality_col = col[[1, 2, 3, 5, 6, 7, 8, 9, 10]]

df_p = pd.read_csv(
    "c:/***/preprocessed_data.csv", header=0, index_col=0)
col_p = df_p.columns.values
# quantity_col_p = df_p.iloc[:, :14]
quality_col_p = df_p.iloc[:, 14:-1]

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([
    html.H4(children='default of credit card clients Data Set'),

    html.Div([
        html.Label('Training model'),
        dcc.Dropdown(id='model',
                     options=[
                         {'label': 'Logistic Regression',
                          'value': 'Logistic Regression'},
                         {'label': 'Decision Tree', 'value': 'Decision Tree'},
                         {'label': 'SVM', 'value': 'SVM'}
                     ],
                     value='Logistic Regression'
                     ),

        html.Label(children='Quantity column'),
        dcc.Dropdown(id='quantity-col',
                     options=[{'label': i, 'value': i} for i in quantity_col],
                     value=[i for i in quantity_col],
                     multi=True
                     ),

        html.Label(children='Quality column'),
        dcc.Dropdown(id='quality-col',
                     options=[{'label': i, 'value': i} for i in quality_col],
                     value=[i for i in quality_col],
                     multi=True
                     ),

        html.Button('Enter', id='enter-button', n_clicks=0)
    ]),

    html.H5('Result'),
    html.Div(id='result')
])


def make_dummycol(column):  # ダミー変数を含む列名のリストを作成
    dummycol = []
    for c in column:
        dummycol += [c + "_{}".format(i) for i in range(-1, 9)]
    l = [cp for cp in quality_col_p if cp in dummycol]
    return l


def train(model, quantity_col, quality_col):  # 選択モデルとデータを使用して学習、AUCスコアを返す
    col_list = list(quantity_col) + make_dummycol(quality_col)
    X = df_p[col_list]
    Y = df["default payment next month"]
    X_train, X_test, Y_train, Y_test = train_test_split(
        X, Y, test_size=0.2, random_state=0)

    if model == 'Logistic Regression':
        lr = LogisticRegression(max_iter=2000)
        lr.fit(X_train, Y_train)
        THRESHOLD = 0.30
        Y_pred = np.where(lr.predict_proba(X_test)[:, 1] > THRESHOLD, 1, 0)
    elif model == 'Decision Tree':
        dt = DecisionTreeClassifier(max_depth=4)
        dt = dt.fit(X_train, Y_train)
        Y_pred = dt.predict(X_test)
    elif model == 'SVM':
        svm = SVC(kernel="rbf", gamma="scale")
        svm.fit(X_train, Y_train)
        Y_pred = svm.predict(X_test)

    return html.Div([model, ": AUC Score:", round(roc_auc_score(Y_test, Y_pred), 3)])


@app.callback(
    Output('result', 'children'),
    Input('enter-button', 'n_clicks'),
    State('model', 'value'),
    State('quantity-col', 'value'),
    State('quality-col', 'value'))
def show_result(enter, model, quantity_col, quality_col):
    return train(model, quantity_col, quality_col)
    # print("Coefficients:", lr.coef_[0])
    # print("Intercept:", lr.intercept_[0])


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

実行結果は以下のようになる。(以下GIFでは為井していないが、SVMは他2つと比べ実行時間が長い。)
app.gif

おわりに

各モデルごとのパラメータ修正やその他結果の表示など修正すべき点は多々あるが、一旦ここまで。動くものを作るのはおもしろい。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?