こんにちは、技術開発の三浦です。
だいぶ寒くなってきて、いよいよ年末らしくなってきました。色々気になることは年内中に片づけておきたい。そういう気持ちになる人はこの時期多いのではないでしょうか。自分もこの時期は毎年忙しくなりがちで、加えて今年はもうすぐ資格試験も控えているため例年にも増してバタバタしています。忙しい時ほど自分のペースを崩さないように一息付く時間が大事だなと、最近感じます。このブログを読んで下さる皆様も、身体に気を付けてこの年末をお過ごしください。
今回は以前から気になっていて、いつか使ってみたいなと思っていたPythonの"Streamlit"というライブラリを少し試してみたお話をしたいと思います。
StreamlitはPythonだけでWebアプリのデザインから動きまでを作ることが出来るオープンソースのPythonのライブラリです。
Webアプリを作る際、UIを作るのにHTMLとCSSを書く必要がありますが、普段これらに触る機会がないと簡単な画面でも作るのにとても時間がかかります。しかしStreamlitを使えばその作業を使い慣れているPythonで行うことが出来るので、UIを作る時間を大幅に短縮することが出来ます。(ただHTML+CSSはもう少し書けるようになりたいです・・・年末年始を利用して本を読もうかと思っています。)
加えてStreamlitでは画面に配置する色々な要素をコード1行でどんどん追加していくことが出来、作っていてとても楽しかったです。今回は画像分類やテキストのポジティブネガティブ判定用の機械学習モデルの動作を試すことが出来るデモアプリを作ることを想定してStreamlitでUIを作ってみました。
アプリの画面
今回作ったWebアプリは3つの画面で構成されています。
Home
最初に表示されるHome画面です。左のサイドメニューから別の画面に移動することが出来ます。
Image
Image画面では、ローカルにある画像ファイルをアップロードして画面に表示し、画像分類モデルの推論スコアが棒グラフで表示されるようにしました。
Text
Text画面はテキストを入力してボタンをクリックすると、そのテキストに対するポジティブネガティブ判定モデルの結果が画面に表示されるようにしました。
Streamlitのインストール
pip
コマンドでインストールすることが出来ます。またグラフ描画にはPythonのグラフ描画ライブラリseabornを使いました。seabornもインストールしておきます。
pip install streamlit seaborn
最初のアプリと起動方法
まずproject用のディレクトリを作り、その直下に.py
ファイルを置きます。この.py
ファイルがこれから作るアプリのホーム画面に対応するため、Home.py
という名前にしています。
project ├── Home.py
Home.py
を開き、以下のように編集します。
import streamlit as st st.title('はじめてのStreamlit!') st.markdown( ''' これは私が**初めて**Streamlitで作ったアプリです! ''' ) with st.sidebar: st.subheader('News!🆕') st.text('画像認識AIが追加されました!')
このコードのimport streamlit as st
のようにstreamlit
をインポートした後、st.title
のように画面上に色々な要素を追加していくことになります。with
文では画面の左側に表示するサイドバーを作る処理を呼び出しています。
あとはこのファイルを保存して、projectディレクトリの中で以下のようにコマンドを実行すると、デフォルトのブラウザ上でアプリが起動します。
streamlit run Home.py
画面を追加する
次にこのアプリに複数の画面を追加してみます。画面の追加はとても簡単で、projectディレクトリの下にpagesというディレクトリを作成し、その中に各画面に対応する.py
ファイルを配置するだけです。
project ├── Home.py ├── pages │ ├── 1_📷_image.py │ └── 2_📝_text.py
この状態で、ふたたびアプリをコマンドを実行して再起動すると、ホーム画面が以下のように変化します。
サイドバーに各画面へのリンクが表示されました!pagesの下に配置したファイル名と比較すると、ファイル名の先頭につけた番号順に上から表示され、"_"と".py"が省かれた文字列が表示されています。ファイル名に絵文字を入れるのは少し違和感がありますが、表示してみるとカワイイですね。
画像AI用の画面
それでは各画面を作っていきます。画面に対応する.py
を編集していきながら作っていくことになります。1_📷_image.py
を開きます。
ファイルアップローダーと画像ファイルの読み込みと表示
まずユーザのローカル環境にある画像ファイルを受け取り、読み込んで画像を表示する部分です。ファイルアップローダを呼び出すボタンはst.file_uploader
で作ることが出来、受け取った画像ファイルは画像ライブラリPillow
で扱うことが出来ます。画面上に画像を表示する時はst.image
を呼び出します。
input_file = st.file_uploader(label='Upload Image File!',type=['png','jpg']) if input_file is not None: img = Image.open(input_file) st.image(img)
グラフの表示
次にユーザがアップロードした画像をモデルに通した後、推論結果をグラフ表示する部分を作っていきます。Streamlitではst.pyplot
でmatplotlibのグラフを表示することが出来、matplotlibをベースにしているseabornも同様に表示することが出来ます。
score_test = [0.9, 0.1] label_test = ['Cat', 'Dog'] fig = plt.figure(figsize=(15,10)) sns.barplot( data=pd.DataFrame({'score':score_test, 'label':label_test}), x='score', y='label', palette=sns.color_palette('dark:#5A9_r') ) st.pyplot(fig)
画面のレイアウト
Streamlitで要素を追加していくと、画面の下に追加されていきます。水平方向に要素を並べるにはst.columns
を呼び出してコンテナに分割し、コンテナ1つ1つに要素を追加していく方法を取ります。たとえば水平方向に1:1.5に2分割する場合は以下のようにします。
clm1, clm2 = st.columns([1., 1.5]) with clm1: ... with clm2: ...
これまでのポイントをすべてまとめると、1_📷_image.py
の内容は以下のようになります。
import streamlit as st from PIL import Image import matplotlib.pyplot as plt import seaborn as sns import pandas as pd sns.set(font_scale=2) st.title('AI for Images!📷') st.markdown('**画像**向けのAIデモページです!') input_file = st.file_uploader(label='Upload Image File!',type=['png','jpg']) clm1, clm2 = st.columns([1, 1.5]) with clm1: if input_file is not None: img = Image.open(input_file) st.image(img) with clm2: if input_file is not None: score_test = [0.9, 0.1] label_test = ['Cat', 'Dog'] fig = plt.figure(figsize=(15,10)) sns.barplot( data=pd.DataFrame({'score':score_test, 'label':label_test}), x='score', y='label', palette=sns.color_palette('dark:#5A9_r') ) st.pyplot(fig)
テキストAI用の画面
次は2_📝_text.py
を編集していきます。
ボタンクリック時の動作
ボタンはst.button
で追加することが出来ます。ボタンクリック時の動作は、ボタンがクリックされるとst.button
がTrue
を返すことを利用して以下のように作ることが出来ます。併せてテキスト入力要素に入力されているテキストをチェックし、空かそうでないかでメッセージの出し分けを行っています。
input_text = st.text_input(label='ここにテキストを入力してみてください') button_click = st.button('送信') if button_click: if input_text: st.markdown(f'{input_text}"の判定結果は"**ポジティブ**"です!') else: st.markdown(f'テキストを入力してからボタンを押して下さい')
このような感じでサクサクとUIを作っていくことが出来ます!
まとめ
ということで、今回はPythonのライブラリStreamlitを使ってWebアプリケーションを作ってみた話をご紹介しました。普段notebookなどで結果を出力しているのと同じような間隔で画面上に要素を配置することが出来、とても素早くアプリを作ることが出来ました。Webアプリとして公開しなくてもローカル環境で立ち上げておいてミーティングに使用する資料としても使えそうだと思いました。