【Python-Streamlit, Docker】kaggle-タイタニックの機械学習Webアプリを実装する(その1)

datascience

今回は、kaggleのタイタニックデータを用いて、機械学習のWebアプリをDockerおよびPython-Streamlitで実装してみたいと思います。

今回はkaggleデータを取得して、Webアプリ上にデータ数を表示していきます。

1. Streamlitとは

詳しくは、Streamlitで確認してみてください。

大まかな内容は

  • PythonコードのみでWebアプリを作成できる
  • HTML, CSS不要
  • 公式ドキュメントが充実しているので実装しやすい
  • Pythonコードで閉じるので、初心者でもわかりやすい

手頃にWebアプリを作成して、シェアしたいときなどには重宝しそうです。

それでは、実装していきましょう。

2. 環境構築(Docker)

以下の本記事内容は、Docker環境で構築したAnacondaをベースに作成しています。予めご了承ください。

使用環境概要は以下となります。

  • ホストOS: Windows10 Pro
  • Docker image: ubuntu:18.04
  • Anaconda: Anaconda3-2020.07-Linux-x86_64
  • Python: Version 3.8.3 (64bit)

ファイルフォルダー構成は以下です。

.
|-- docker-compose.yml
`-- work
    |-- Dockerfile
    |-- requirements.txt
    `-- kaggle
        `-- taitanic
            |-- data
            |   |-- test.csv
            |   `-- train.csv
            `-- streamlit
                |-- main_streamlit.py
                `-- data_get.py

Dockerfileは以下のようにして、AnacondaをDockerコンテナ内に用意します。

解析内容を確認するため、Jupyterlabも起動できるようにしています。

# Dockerfile
FROM ubuntu:18.04
RUN apt-get update && apt-get install -y \
    sudo \
    wget \
    vim \
    curl 

WORKDIR /opt
# anacondaのインストール
RUN wget https://repo.continuum.io/archive/Anaconda3-2020.07-Linux-x86_64.sh && \
    sh /opt/Anaconda3-2020.07-Linux-x86_64.sh -b -p /opt/anaconda3 && \
    rm -f Anaconda3-2020.07-Linux-x86_64.sh
ENV PATH /opt/anaconda3/bin:$PATH

COPY requirements.txt /opt/app/requirements.txt
WORKDIR /opt/app
RUN pip3 install --upgrade -r requirements.txt
COPY . /opt/app
WORKDIR /
CMD ["jupyter", "lab", "--ip=0.0.0.0", "--allow-root", "--LabApp.token=''"]

また、docker-compose.ymlは以下のようにしています。

#docker-compose.yml
version: '3'

services:
  app:
    build:
      context: ./work
      dockerfile: Dockerfile
    ports:
        - '5555:8888'
    container_name: kaggle_app
    volumes:
      - '.:/work'

requirements.txtは以下のようにして、streamlitなど必要なライブラリをインストールしておきます。

pip
streamlit
scikit-learn

それでは、コマンドプロンプトなどを用いて、Docker-compose.ymlのあるフォルダまで移動したら、以下のコマンドを入力してコンテナを立ち上げましょう。(初期のコンテナ作成時は時間がかかります)

$ docker-compose up -d --build

無事コンテナ内に環境構築できたら、streamlitフォルダに”main.py”とデータを取得する”data_get.py”を作成しておきます。

これでDockerによる環境構築は完了です。

3. 解析データをサイトからダウンロード

まずは、kaggleから解析用データを取得しましょう。すでに取得方法をご存じの方は飛ばしていただいて構いません。

図1 Kaggle タイタニックデータの取得
  1. kaggleにアクセスし、”Compete”をクリックする
  2. “Data”をクリックする
  3. “test.csv”をクリックする
  4. “↓”をクリックしてデータをダウンロードする(ダウンロード先は各個人のPCで確認ください)
  5. “train.csv”も”test.csv”と同様にダウンロードする

これでデータ解析するデータの取得は完了です。

あとは、ダウンロードしたデータを先程の”data”フォッルダーに格納しておけばデータ準備は完了です。

4. 基本コードを書く

最初は、”Streamlit”は気にせずに通常通りデータ処理のコードを記載していきます。

データを取得する関数を”data_get.py”に作成していきます。このファイルにtrain.csvおよびtest.csvのデータをpandasデータフレームとして読み込みこむread_data関数を作成します

まずは、train.csvおよびtest.csvのデータをpandasデータフレームとして読み込みこみ、それぞれのデータサイズをprintします。また、後で目的変数をわかりやすくするため、’Target column = “Survived” ‘をprintしてきます。また、目的変数の平均値を表示しておきます。

あとは、trainデータおよびtestデータを一括で処理したいため、alldataを作成します。

alldataは後ほどtrainデータとtestデータを分割するために、df_trainとdf_testに’train_or_test’カラムを作成し、それぞれ0と1を付与します。

また、df_testには目的変数である”Survived”の値がないので、9を仮でおいておきます。

その後、alldataを作成し、df_trainとdf_test、alldataの詳細データ構造(describe(include=’all’))をprintするようにしておきます。

本関数の戻り値は、alldataとtest_rawとします。test_rawは後ほどの記事で使用します。

""" data_get.py """
import pandas as pd
import streamlit as st

class Data_Get():
    def read_data(self):
        train_raw = pd.read_csv('../data/train.csv') 
        test_raw = pd.read_csv('../data/test.csv')
        print('The size of the train data:' + str(train_raw.shape))
        print('The size of the test data:' + str(test_raw.shape))

        print('Target column = "Survived"')
        print('Target mean:' + str(train_raw['Survived'].mean()))

        df_train, df_test = train_raw.copy(), test_raw.copy()
        df_train['train_or_test'] = 0 
        df_test['train_or_test'] = 1 
        df_test['Survived'] = 9 """ テストにSurvivedカラムを9で仮置き """
        alldata = pd.concat([df_train,df_test],sort=False,axis=0).reset_index(drop=True)

        print(df_train.describe(include='all'))
        print(df_test.describe(include='all'))
        print(alldata.describe(include='all'))

        return alldata, test_raw
        

次に”main_streamlit.py”を作成します。こちらは簡単で、先程作成したdata_get.pyからData_Getインスタンスを読み込み、read_data関数を使用して、先程戻り値に指定したalldata, test_rawを取得します。

以上です。

""" main.py """
import pandas as pd
import streamlit as st
import data_get as dg

print('Titanic - Machine Learning from Disaster')

print('(1) Data Structure')
dg_Inst = dg.Data_Get()
alldata, test_raw = dg_Inst.read_data()

5. Streamlitを実装する

ここからStreamlitを実装して、簡単にWebアプリを作成してみましょう!

“main_streamlit.py”を以下のように変更します。

""" main.py """
import pandas as pd
import streamlit as st
import data_get as dg

st.title('Titanic - Machine Learning from Disaster')

st.subheader('(1) Data Structure')
dg_Inst = dg.Data_Get()
alldata, test_raw = dg_Inst.read_data()

それでは早速、コマンドプロンプトなどを用いて、main.pyのあるフォルダーに移動して、以下のコマンドを実行してください。

$ streamlit run main_streamlit.py

そうすると、Webブラウザ上に以下の図のような画面が表示されます。

表示されれば、Webアプリ完成です!ですが少し味気ないので、もう少し手を加えていきたいと思います。

図1 Webアプリ by streamlit

次に”data_get.py”を変更していきます。以下のように変更してみてください。

""" data_get.py """
import pandas as pd
import streamlit as st

class Data_Get():
    def read_data(self):
        train_raw = pd.read_csv('../data/train.csv') 
        test_raw = pd.read_csv('../data/test.csv') 
        st.write('The size of the train data:' + str(train_raw.shape))
        st.write('The size of the test data:' + str(test_raw.shape))

        target = train_raw.columns
        sel_target = st.sidebar.selectbox(
            '(1) Please select "Target column"',
            target
        )

        st.write('Target mean:' + str(round(train_raw[sel_target].mean(), 3)))

        df_train, df_test = train_raw.copy(), test_raw.copy()
        df_train['train_or_test'] = 0
        df_test['train_or_test'] = 1 
        df_test[sel_target] = 9 
        alldata = pd.concat([df_train,df_test],sort=False,axis=0).reset_index(drop=True)

        checkbox = st.checkbox('Show data')
        if checkbox:
            checkbox_1 = st.checkbox('Train_data')
            if checkbox_1:
                st.write(df_train.describe(include='all'))
            checkbox_2 = st.checkbox('Test_data')
            if checkbox_2:
                st.write(df_test.describe(include='all'))
            checkbox_3 = st.checkbox('All_data')
            if checkbox_3:
                st.write(alldata.describe(include='all'))

        return alldata, test_raw

コードを変更して”localhost:8501″を更新すると、以下のようにWebアプリが変更されます。

図2 Detail information by Streamlit (Target = PaasengerId)

いくつかコードを確認していきます。

以下のコードでは、サイドバーに目的変数を設定するselectboxを作成しています。目的変数候補はtrain_rawのカラム名としています。

リストでも指定可能です。([‘Survived’]など)

target = train_raw.columns
sel_target = st.sidebar.selectbox(
    '(1) Please select "Target column"',
    target
)

選択目的変数を”Survived”にすれば、以下のように表示が変更されます。

図3 Detail information by Streamlit (Target = Survived)

また、以下のコードでは、表示したい項目のチェックボックスを表示できるようになります。

checkbox = st.checkbox('Show data')
if checkbox:
    checkbox_1 = st.checkbox('Train_data')
    if checkbox_1:
        st.write(df_train.describe(include='all'))
    checkbox_2 = st.checkbox('Test_data')
    if checkbox_2:
        st.write(df_test.describe(include='all'))
    checkbox_3 = st.checkbox('All_data')
    if checkbox_3:
        st.write(alldata.describe(include='all'))

例えば、”Show data”と’train_data”のチェックボックスを押すと、以下のように表示が変更されます。

図4 Data display

自分が見たいデータだけをチェックボックスで簡単に表示することが可能です。

6. 本記事の完成形とまとめ

本記事内の内容での完成形のコードを以下に示します。

""" main_streamlit.py """
import pandas as pd
import streamlit as st
import data_get as dg

st.title('Titanic - Machine Learning from Disaster')

st.subheader('(1) Data Sturucture')
dg_Inst = dg.Data_Get()
alldata, test_raw = dg_Inst.read_data()
""" data_get.py """
import pandas as pd
import streamlit as st

class Data_Get():
    def read_data(self):
        train_raw = pd.read_csv('../data/train.csv')
        test_raw = pd.read_csv('../data/test.csv')
        st.write('The size of the train data:' + str(train_raw.shape))
        st.write('The size of the test data:' + str(test_raw.shape))

        target = train_raw.columns
        sel_target = st.sidebar.selectbox(
            '(1) Please select "Target column"',
            target
        )

        st.write('Target mean:' + str(train_raw[sel_target].mean()))

        df_train, df_test = train_raw.copy(), test_raw.copy()
        df_train['train_or_test'] = 0 
        df_test['train_or_test'] = 1 
        df_test[sel_target] = 9
        alldata = pd.concat([df_train,df_test],sort=False,axis=0).reset_index(drop=True)

        checkbox = st.checkbox('Show data')
        if checkbox:
            checkbox_1 = st.checkbox('Train_data')
            if checkbox_1:
                st.write(df_train.describe(include='all'))
            checkbox_2 = st.checkbox('Test_data')
            if checkbox_2:
                st.write(df_test.describe(include='all'))
            checkbox_3 = st.checkbox('All_data')
            if checkbox_3:
                st.write(alldata.describe(include='all'))

        return alldata, test_raw

以上のように、pythonコードのみでWebアプリ動作が可能であるので、動作させながら結果を見たい場合などに重宝しそうです。

次回は、欠損値処理の前後変化をWebアプリ上で可視化したいと思います。

それではよいpython-streamlit ライフを!

以下、関連記事となります。合わせてお読みいただけるお幸いです。

3件のコメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

ABOUT US

Baran-gizagiza
経歴:浪人→理系大学院卒業→大手製造業に就職(技術職)→アメリカ赴任中 仕事は、研究・設計など上流工程の仕事に携わっています。企業勤務を継続しながら、新しいことにチャレンジしたいと思い、ブログを下記はじめました。 このブログでは、趣味である 筋トレ(健康、ダイエット) AIとデータ(高校数学、プログラミング) 読書(主に自己啓発系) を中心に、人生経験やおすすめ情報の発信しています。