13. Web アプリへの展開¶
第 13 回では、これまで学んだ機械学習モデルを Web アプリケーションとして展開する方法を紹介します。
13.1 Web アプリケーションとは¶
13.1.1 Web アプリケーションの概要¶
Web アプリケーションとは、Web ブラウザを通じて利用できるアプリケーションのことです。ユーザは特別なソフトウェアをインストールすることなく、ブラウザさえあればどこからでもアプリケーションを利用できます。
Web アプリケーションの利点
- アクセスの容易さ: ブラウザがあればどこからでもアクセス可能
- クロスプラットフォーム: Windows、Mac、スマートフォンなど、環境を選ばない
- 共有が簡単: URL を共有するだけで他の人も利用可能
- メンテナンスが楽: サーバ側を更新すれば全ユーザに反映
13.1.2 機械学習モデルの Web アプリ化¶
機械学習モデルを Web アプリとして公開することで、以下のようなことが可能になります。
- 実用的なサービス: モデルを実際のサービスとして提供
- デモンストレーション: 研究成果やポートフォリオとして公開
- フィードバック収集: ユーザからの反応を得て改善
- API として提供: 他のシステムから利用可能
13.1.3 Python の Web フレームワーク¶
Python には、Web アプリケーションを構築するためのフレームワークがいくつか存在します。
| フレームワーク | 特徴 | 適用場面 |
|---|---|---|
| Streamlit | 簡単、素早くプロトタイプを作成 | デモ、社内ツール |
| Flask | 軽量、柔軟性が高い | 小〜中規模の Web アプリ、API |
| FastAPI | 高速、API 構築に特化 | REST API、本格的なサービス |
| Django | 多機能、大規模開発向け | 大規模 Web アプリケーション |
本講義では、Streamlit と Flask を使った実装例を紹介します。
13.2 Streamlit による簡単な Web アプリ¶
13.2.1 Streamlit とは¶
Streamlit は、データサイエンス向けの Web アプリを簡単に作成できる Python ライブラリです。わずか数行のコードで、インタラクティブな Web アプリを構築できます。
Streamlit の特徴
- 簡単: Python スクリプトを書くだけで Web アプリが作れる
- 高速: プロトタイプを素早く作成できる
- インタラクティブ: スライダ、ボタンなどの UI 部品が豊富
- ホットリロード: コードを編集すると自動的に反映される
13.2.2 Streamlit のインストール¶
Streamlit がインストールされていない場合は、以下のコマンドでインストールします。
Web アプリケーション開発環境について
以降の説明は、ローカル環境での開発を想定しています。
- Google Colab などのクラウドのノートブック環境では、Web アプリの開発・実行に工夫が必要となります
- CHIKUWA Editor は現状 Web アプリ開発に対応していません
13.2.3 Streamlit の基本的な使い方¶
まず、簡単な Hello World アプリを作成してみましょう。
import streamlit as st
# タイトル
st.title("Hello, Streamlit!")
# テキスト
st.write("これは Streamlit で作った Web アプリです。")
# ボタン
if st.button("クリックしてください"):
st.write("ボタンがクリックされました!")
# スライダー
value = st.slider("値を選択してください", 0, 100, 50)
st.write(f"選択された値: {value}")
このスクリプトを app.py として保存し、以下のコマンドで実行します。
ブラウザが自動的に開き、Web アプリが表示されます(通常は http://localhost:8501)。
以下に、実際に動作する Web アプリを用意しておきました(講義期間のみアクセス可)。
https://ml-sample.ibadai.com/st1/
13.2.4 主要な Streamlit コンポーネント¶
Streamlit では、さまざまな UI コンポーネントを簡単に追加できます。
テキスト表示
st.title("タイトル")
st.header("ヘッダー")
st.subheader("サブヘッダー")
st.write("テキスト")
st.markdown("**太字** や *斜体* も使えます")
入力ウィジェット
# テキスト入力
text = st.text_input("テキストを入力してください")
# テキストエリア
long_text = st.text_area("長いテキストを入力してください")
# 数値入力
number = st.number_input("数値を入力してください", min_value=0, max_value=100)
# スライダー
value = st.slider("値を選択してください", 0, 100, 50)
# セレクトボックス
option = st.selectbox("選択してください", ["オプション1", "オプション2", "オプション3"])
# ボタン
if st.button("送信"):
st.write("送信されました!")
データ表示
import pandas as pd
# DataFrame の表示
df = pd.DataFrame({
"列1": [1, 2, 3],
"列2": [4, 5, 6]
})
st.dataframe(df)
# テーブルの表示
st.table(df)
グラフ表示
import matplotlib.pyplot as plt
# Matplotlib のグラフ
fig, ax = plt.subplots()
ax.plot([1, 2, 3, 4], [1, 4, 2, 3])
st.pyplot(fig)
# 簡易グラフ
st.line_chart(df)
st.bar_chart(df)
公式ドキュメント: Streamlit API Reference
以下は、上記コードの実行例です(講義期間のみアクセス可)。
https://ml-sample.ibadai.com/st2/
13.3 Streamlit で感情分析アプリを作る¶
13.3.1 アプリの概要¶
第 12 回で学んだ Sentence Transformers を使って、テキストの感情分析ができる Web アプリを作成してみましょう。
機能:
- ユーザがテキストを入力
- 「Positive(ポジティブ)」「Negative(ネガティブ)」を分類
- 予測結果と確率を表示
13.3.2 モデルの準備と保存¶
まず、感情分析モデルを学習して保存します。
import pandas as pd
from sentence_transformers import SentenceTransformer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
import pickle
# データの読み込み
df = pd.read_csv('movie_reviews.csv')
# モデルの読み込み
model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')
# ベクトル化
embeddings = model.encode(df['text'].tolist())
# ラベルを数値に変換
df['label_num'] = (df['label'] == 'positive').astype(int)
# 訓練データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(
embeddings, df['label_num'],
test_size=0.2,
random_state=42
)
# ロジスティック回帰で学習
clf = LogisticRegression(random_state=42, max_iter=1000)
clf.fit(X_train, y_train)
# モデルの保存
with open('sentiment_model.pkl', 'wb') as f:
pickle.dump(clf, f)
print("モデルを保存しました: sentiment_model.pkl")
13.3.3 Streamlit アプリの実装¶
次に、保存したモデルを読み込んで使用する Streamlit アプリを作成します。
import streamlit as st
from sentence_transformers import SentenceTransformer
import pickle
# ページの設定
st.set_page_config(page_title="感情分析アプリ", page_icon="😊")
# タイトル
st.title("😊 感情分析アプリ")
st.write("テキストを入力すると、Positive(ポジティブ)か Negative(ネガティブ)かを判定します。")
# モデルの読み込み(キャッシュを使って1回だけ読み込む)
@st.cache_resource
def load_models():
# Sentence Transformers モデル
encoder = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')
# 分類モデル
with open('sentiment_model.pkl', 'rb') as f:
classifier = pickle.load(f)
return encoder, classifier
# モデルの読み込み
encoder, classifier = load_models()
# テキスト入力
text_input = st.text_area(
"テキストを入力してください",
height=150,
placeholder="例:この映画は本当に面白かった!"
)
# 予測ボタン
if st.button("感情を分析"):
if text_input.strip() == "":
st.warning("テキストを入力してください。")
else:
# ベクトル化
embedding = encoder.encode([text_input])
# 予測
prediction = classifier.predict(embedding)[0]
probability = classifier.predict_proba(embedding)[0]
# 結果の表示
st.subheader("分析結果")
if prediction == 1:
st.success("😊 Positive(ポジティブ)")
st.progress(probability[1])
st.write(f"確率: {probability[1]:.2%}")
else:
st.error("😞 Negative(ネガティブ)")
st.progress(probability[0])
st.write(f"確率: {probability[0]:.2%}")
# 詳細情報
with st.expander("詳細情報を表示"):
st.write(f"Positive の確率: {probability[1]:.2%}")
st.write(f"Negative の確率: {probability[0]:.2%}")
# サイドバー
st.sidebar.header("ℹ️ このアプリについて")
st.sidebar.write("""
このアプリは、機械学習を使って日本語テキストの感情を分析します。
**使用技術**
- Sentence Transformers
- Logistic Regression
- Streamlit
""")
13.3.4 アプリの実行¶
以下のコマンドでアプリを起動します。
ブラウザで http://localhost:8501 にアクセスすると、感情分析アプリが表示されます。
以下に、完成版を用意しておきました(講義期間のみアクセス可)。
https://ml-sample.ibadai.com/st3/
13.3.5 キャッシュの活用¶
@st.cache_resource デコレータを使うことで、モデルの読み込みを 1 回だけ実行し、結果をキャッシュできます。これにより、アプリの起動が高速になります。
キャッシュの種類:
| デコレータ | 用途 |
|---|---|
@st.cache_resource |
モデル、DB 接続などのグローバルなリソース |
@st.cache_data |
データの読み込みや変換処理 |
13.4 Flask による Web アプリ¶
13.4.1 Flask とは¶
Flask は、Python で Web アプリケーションを構築するための軽量なフレームワークです。Streamlit よりも柔軟性が高く、より本格的な Web アプリや REST API を構築できます。
Flask の特徴
- 軽量: 必要最小限の機能のみを提供
- 柔軟: 拡張性が高く、カスタマイズしやすい
- REST API: API サーバとして利用できる
- 豊富なエコシステム: 多数の拡張ライブラリが存在
13.4.2 Flask のインストール¶
13.4.3 Flask の基本的な使い方¶
最も簡単な Flask アプリの例を見てみましょう。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "Hello, Flask!"
if __name__ == '__main__':
app.run(debug=True)
このスクリプトを実行します。
ブラウザで http://localhost:5000 にアクセスすると、"Hello, Flask!" と表示されます。
13.4.4 Flask の基本構造¶
Flask アプリは、ルーティング(URL とハンドラ関数の対応付け)を基本としています。
from flask import Flask, request, render_template
app = Flask(__name__)
# ルート(トップページ)
@app.route('/')
def index():
return "トップページ"
# 別のページ
@app.route('/about')
def about():
return "About ページ"
# パラメータを受け取る
@app.route('/user/<name>')
def user(name):
return f"Hello, {name}!"
# POST リクエストを処理
@app.route('/submit', methods=['POST'])
def submit():
data = request.form['data']
return f"受け取ったデータ: {data}"
if __name__ == '__main__':
app.run(debug=True)
13.4.5 テンプレートエンジン¶
Flask では、HTML テンプレートを使って動的なページを生成できます。テンプレートには Jinja2 というテンプレートエンジンを使用します。
ディレクトリ構造
テンプレート(templates/index.html)
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ message }}</h1>
</body>
</html>
Flask アプリ(app.py)
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html',
title="My App",
message="Hello, Flask!")
if __name__ == '__main__':
app.run(debug=True)
13.5 Flask で感情分析 API を作る¶
13.5.1 REST API とは¶
REST API は、HTTP リクエスト/レスポンスを使ってデータをやり取りする仕組みです。Web アプリや他のプログラムから機械学習モデルを利用できるようになります。
REST API の利点
- プログラムから利用可能: 他のアプリケーションから呼び出せる
- 言語非依存: どんなプログラミング言語からでも利用可能
- スケーラブル: サーバを増やして処理能力を向上できる
13.5.2 感情分析 API の実装¶
Flask を使って、感情分析の REST API を実装してみましょう。
from flask import Flask, request, jsonify
from sentence_transformers import SentenceTransformer
import pickle
app = Flask(__name__)
# モデルの読み込み
print("モデルを読み込んでいます...")
encoder = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')
with open('sentiment_model.pkl', 'rb') as f:
classifier = pickle.load(f)
print("モデルの読み込みが完了しました。")
@app.route('/')
def index():
return """
<h1>感情分析 API</h1>
<p>使い方:POST /predict にテキストを送信してください。</p>
<p>例:curl -X POST -H "Content-Type: application/json" -d '{"text":"この映画は面白かった"}' http://localhost:5000/predict</p>
"""
@app.route('/predict', methods=['POST'])
def predict():
# リクエストから JSON データを取得
data = request.get_json()
# テキストの取得
if 'text' not in data:
return jsonify({'error': 'テキストが指定されていません'}), 400
text = data['text']
if not text.strip():
return jsonify({'error': 'テキストが空です'}), 400
# ベクトル化
embedding = encoder.encode([text])
# 予測
prediction = classifier.predict(embedding)[0]
probability = classifier.predict_proba(embedding)[0]
# 結果を返す
result = {
'text': text,
'sentiment': 'positive' if prediction == 1 else 'negative',
'confidence': float(probability[prediction]),
'probabilities': {
'positive': float(probability[1]),
'negative': float(probability[0])
}
}
return jsonify(result)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)
13.5.3 API の使い方¶
API の起動:
curl コマンドでテスト:
curl -X POST \
-H "Content-Type: application/json" \
-d '{"text":"この映画は本当に素晴らしかった!"}' \
http://localhost:5000/predict
レスポンス例
{
"text": "この映画は本当に素晴らしかった!",
"sentiment": "positive",
"confidence": 0.92,
"probabilities": {
"positive": 0.92,
"negative": 0.08
}
}
Python からの利用
import requests
url = 'http://localhost:5000/predict'
data = {'text': 'この映画はつまらなかった'}
response = requests.post(url, json=data)
result = response.json()
print(result)
13.5.4 Flask アプリと HTML フォーム¶
Flask アプリに HTML フォームを追加して、ブラウザから直接利用できるようにしてみましょう。
ディレクトリ構造
app.py
from flask import Flask, render_template, request
from sentence_transformers import SentenceTransformer
import pickle
app = Flask(__name__)
# モデルの読み込み
encoder = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')
with open('sentiment_model.pkl', 'rb') as f:
classifier = pickle.load(f)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/analyze', methods=['POST'])
def analyze():
text = request.form['text']
if not text.strip():
return render_template('index.html', error="テキストを入力してください")
# ベクトル化と予測
embedding = encoder.encode([text])
prediction = classifier.predict(embedding)[0]
probability = classifier.predict_proba(embedding)[0]
sentiment = 'Positive' if prediction == 1 else 'Negative'
confidence = probability[prediction]
return render_template('result.html',
text=text,
sentiment=sentiment,
confidence=confidence,
prob_positive=probability[1],
prob_negative=probability[0])
if __name__ == '__main__':
app.run(debug=True)
templates/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>感情分析アプリ</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 50px auto;
padding: 20px;
}
textarea {
width: 100%;
height: 150px;
padding: 10px;
font-size: 14px;
}
button {
background-color: #4caf50;
color: white;
padding: 10px 20px;
border: none;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #45a049;
}
.error {
color: red;
}
</style>
</head>
<body>
<h1>😊 感情分析アプリ</h1>
<p>テキストを入力すると、ポジティブかネガティブかを判定します。</p>
{% if error %}
<p class="error">{{ error }}</p>
{% endif %}
<form method="POST" action="/analyze">
<textarea
name="text"
placeholder="テキストを入力してください..."
></textarea>
<br /><br />
<button type="submit">分析する</button>
</form>
</body>
</html>
templates/result.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>分析結果</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 50px auto;
padding: 20px;
}
.result {
padding: 20px;
border-radius: 5px;
margin: 20px 0;
}
.positive {
background-color: #d4edda;
border: 1px solid #c3e6cb;
}
.negative {
background-color: #f8d7da;
border: 1px solid #f5c6cb;
}
a {
color: #007bff;
text-decoration: none;
}
</style>
</head>
<body>
<h1>分析結果</h1>
<div
class="result {% if sentiment == 'Positive' %}positive{% else %}negative{% endif %}"
>
<h2>{{ sentiment }}</h2>
<p><strong>入力テキスト:</strong> {{ text }}</p>
<p><strong>信頼度:</strong> {{ "%.2f"|format(confidence * 100) }}%</p>
<hr />
<p>Positive: {{ "%.2f"|format(prob_positive * 100) }}%</p>
<p>Negative: {{ "%.2f"|format(prob_negative * 100) }}%</p>
</div>
<a href="/">← 戻る</a>
</body>
</html>
13.6 デプロイ(公開)の基礎¶
13.6.1 デプロイとは¶
デプロイ(Deploy)とは、作成したアプリケーションをインターネット上のサーバに配置し、誰でもアクセスできるようにすることです。
13.6.2 主要なデプロイ先¶
| サービス | 特徴 | 無料プラン |
|---|---|---|
| Streamlit Community Cloud | Streamlit 専用、簡単 | あり(制限付き) |
| Render | Flask/FastAPI など幅広く対応 | あり(制限付き) |
| Heroku | 老舗、多機能 | 有料のみ |
| Google Cloud Run | コンテナベース、スケーラブル | 無料枠あり |
| AWS (EC2, Lambda) | 柔軟性が高い、学習コストも高い | 無料枠あり(1 年間) |
| 自宅サーバ | 自由度が最も高い | サーバ費用が必要 |
13.6.3 Streamlit Community Cloud へのデプロイ¶
Streamlit アプリを最も簡単に公開する方法は、Streamlit Community Cloud を使うことです。
手順
-
GitHub にコードをアップロード
-
リポジトリを作成
-
app.py、requirements.txt(必要なライブラリ)、モデルファイルをアップロード -
requirements.txt の作成
-
Streamlit Community Cloud に登録
-
GitHub アカウントでログイン
-
アプリをデプロイ
- "New app" をクリック
- GitHub リポジトリを選択
- デプロイするファイル(
app.py)を指定 - "Deploy!" をクリック
数分でアプリが公開され、URL が発行されます。
13.6.4 注意点¶
モデルファイルのサイズ
- 大きなモデルファイルは GitHub にアップロードできません(100MB 制限)
- 対処法: モデルの軽量化 / Git LFS の使用 / クラウドストレージから読み込む
環境変数
- API キーなどの秘密情報は、環境変数として設定する
- Streamlit では
st.secretsを使って安全に管理できる
13.7 チャレンジ問題¶
チャレンジ 13-1: 画像分類 Web アプリの作成¶
チャレンジ 13-1
Streamlit を使って、画像分類(例: MNIST 手書き数字認識)の Web アプリを作成してください。
タスク:
- ユーザが画像をアップロードできるようにする
- アップロードされた画像を分類モデルで予測
- 予測結果(クラスと確率)を表示
ヒント:
st.file_uploader()で画像をアップロード- PIL で画像を読み込み
st.image()で画像を表示
チャレンジ 13-2: Flask API の拡張¶
チャレンジ 13-2
13.5 で作成した Flask API を拡張して、複数の文を一度に分析できる機能を追加してください。
タスク:
/predict_batchエンドポイントを作成- リクエストで複数の文を受け取る(JSON 配列)
- 各文の感情分析結果をまとめて返す
入力例:
出力例:
13.8 まとめ¶
本章では、機械学習モデルを Web アプリケーションとして展開する方法について学びました。
第 13 回のまとめ
Web アプリケーション
- ブラウザで利用できるアプリケーション
- アクセスしやすく、共有が簡単
- Python の Web フレームワークを使って構築
Streamlit
- データサイエンス向けの Web アプリフレームワーク
- 簡単に素早くプロトタイプを作成できる
st.text_input(),st.button(),st.write()などの UI 部品@st.cache_resourceでモデルをキャッシュ
Flask
- 軽量で柔軟な Web フレームワーク
- ルーティングで URL とハンドラを対応付け
- テンプレートエンジン(Jinja2)で HTML を生成
- REST API の構築に適している
REST API
- HTTP リクエスト/レスポンスでデータをやり取り
- プログラムから機械学習モデルを利用可能
- JSON 形式でデータを送受信
デプロイ
- アプリをインターネット上に公開
- Streamlit Community Cloud: Streamlit アプリを簡単に公開
- Render, Heroku, Google Cloud Run など様々な選択肢
実装のポイント
- モデルを pickle で保存・読み込み
- キャッシュを活用して高速化
- エラーハンドリングを適切に行う
- 環境変数で秘密情報を管理
13.9 講義全体の総括¶
本講義「機械学習」では、全 13 回を通じて、機械学習の基礎から実践的な応用までを学んできました。
学んできたこと¶
| 回 | テーマ | 内容 |
|---|---|---|
| 1 | ガイダンス | 講義の概要、機械学習の全体像 |
| 2 | Python 入門 | プログラミングの基礎 |
| 3 | データ可視化 | Matplotlib によるデータの可視化 |
| 4 | 機械学習の基礎 | 教師あり学習、訓練とテスト、評価指標 |
| 5 | 回帰モデル | 単回帰分析、重回帰分析 |
| 6 | 分類モデル | ロジスティック回帰、決定木、ランダムフォレスト |
| 7 | 画像処理 ① | 画像データの基礎、読み込み・表示・変換 |
| 8 | 画像処理 ② | 古典的な特徴抽出(エッジ検出、HOG など) |
| 9 | 画像処理 ③ | 画像分類の実践 |
| 10 | 自然言語処理 ① | テキストの前処理、形態素解析 |
| 11 | 自然言語処理 ② | Bag-of-Words、TF-IDF による文書分類 |
| 12 | 自然言語処理 ③ | Sentence Transformers によるテキストのベクトル化 |
| 13 | Web アプリへの展開 | Streamlit、Flask による機械学習モデルの公開 |
機械学習プロジェクトの流れ¶
本講義で学んだ内容を組み合わせることで、以下のような機械学習プロジェクトの一連の流れを実践できます。
1. 問題の定義
↓
2. データの収集・整理
↓
3. データの可視化・探索(第 3 回)
↓
4. 特徴量の抽出・前処理(第 7〜12 回)
↓
5. モデルの選択・学習(第 4〜6 回)
↓
6. モデルの評価・改善(第 4〜6 回)
↓
7. デプロイ・公開(第 13 回)
今後の学習に向けて¶
本講義では機械学習の基礎を学びました。興味のある方は、以下のようなトピックについても学んでみてください。
- ディープラーニング: ニューラルネットワーク、CNN、RNN、Transformer
- 大規模言語モデル(LLM): GPT、BERT、LLaMA などの活用
- 強化学習: ゲーム AI、ロボット制御
- MLOps: 機械学習モデルの運用・管理
- 倫理と公平性: AI の社会的影響、バイアスへの対処
機械学習は日々進化している分野です。本講義で学んだ基礎を土台に、引き続き学習を続けてください。