その他

Devinを用いて札幌市と帯広市の積雪深予測モデルをWebアプリ化してみた!

その他
この記事は約9分で読めます。

前回のおさらい

前回の取り組みでは、11項目の気象データを用いてニューラルネットワークで積雪深を予測しようという取り組みをしました。

まだ読んでいない方は以下のリンクからぜひ読んでみてください。

これまでは統計学的手法による回帰分析で求めていましたが、予測精度が低く誤差が大きいという問題がありました。

そこで機械学習手法のニューラルネットワークで解いたらどうなるだろうかと思い、工夫してみたところ、予測精度が0.8、誤差が10cmとこれまでと比べるとかなり向上しました。

今回やること

ニューラルネットワークによって、これまでの予測精度とは大幅に向上したため、今回はwebアプリを作成していようと思います。

さらに最近話題のDevinを使って実装し、Devinがどんな感じでタスクを処理してくれるのかみていきます。

Devinとは

みなさんDevinをご存知でしょうか。

昨今、あちこちでAIエージェントの開発がされていますが、DevinはCognition社から提供されている完全自律型のAIエージェントです。

Devin以外にもCursorなどのエージェントがありますが、Devinの何がすごいかというと、実装からデバックまでを自立して処理してくれるところにあります。

弊社でも一部で導入され始めているらしく、我々のチームとしても社内にDevinを普及することが目標なので、Devinの素晴らしさがこの記事で伝わると良いなと思います。

とは言え、僕もDevinを使うのは初めてなので、一緒に使い方を覚えていきましょう!

Devin
Devin is an AI coding agent and software engineer that helps developers build better software faster. Parallel cloud agents for serious engineering teams.

Devinを使って実装してみよう

学習による重みファイルの生成

積雪深予測モデルをwebアプリ化するためには、まず学習用のファイルとアプリ用のファイルを作成する必要があります。

なぜなら同じファイルにまとめてしまうと、機械学習の特性上アプリのそのものが重くなってしまうからです。そのため学習ファイルを丸ごとモジュール化して使うことはほとんどありません。

ではどのようにしてアプリとして実装するかというと、学習で得られる特徴量の重みをファイルとして保存し、そのファイルを用いることが一般的です。

前回はscikit-learnを使用しており、学習で得た重みファイルはpickleライブラリで.pkl拡張子で保存することが慣例となります。(PyTorchでは.pth)

train_model.py

from sklearn.neural_network import MLPRegressor
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, r2_score
import pickle

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=0)

scaler = StandardScaler()
x_train_scaled = scaler.fit_transform(x_train)
x_test_scaled = scaler.transform(x_test)

model = MLPRegressor(
    hidden_layer_sizes=(128, 64, 32), 
    activation="relu", 
    solver="adam", 
    alpha=0.002, 
    learning_rate_init=0.001, 
    random_state=60, 
    early_stopping=True, 
    max_iter=500
)

model.fit(x_train_scaled, y_train)

with open(out_dir / "snow_depth_model.pkl", "wb") as f:
  pickle.dump(model, f)

with open(out_dir / "scaler.pkl", "wb") as f:
  pickle.dump(scaler, f)

アプリのレイアウト

ニューラルネットワークによって積雪深の予測精度が大幅に向上したことから、今回はstreamlitを使ってwebアプリ化してみます。

webアプリケーション化するフレームワークとして、streamlitの他にFlaskやDjangoがありますが、今回はpythonだけで済むようにstreamlitを採用しました。

pythonだけで完結するのでhtmlの<div>などのマークアップを設定する必要がないのは非常に楽ですね。

今回はwebアプリケーション化するだけではあまり面白くないため、帯広市の積雪深予測モデルを追加し、札幌市と帯広市の積雪深を予測できるようなアプリケーションを目指します。

なお、札幌市は約10年分のデータを用いて重みファイルを生成していますが、帯広市の学習サンプルは約2年分なので、偏りがあることだけ注意が必要です。

streamlitでアプリケーション作成するための基本設定として、set_page_configでタイトルやレイアウトを設定します。特にlayoutはデフォルトでは中央揃えのようになりますが、wideとすることで全体揃えのようなレイアウトになります。

続いて、それぞれのモデルを柔軟に用いるため、def文でまとめておきます。

streamlit_app.py

st.set_page_config(
    page_title="積雪深予測アプリ",
    page_icon="❄️",
    layout="wide"
)

def load_model_and_scaler():
    """Load the trained model and scaler"""
    try:
        with open("sapporo_models/snow_depth_model.pkl", "rb") as f:
            sapporo_model = pickle.load(f)
        
        with open("sapporo_models/scaler.pkl", "rb") as f:
            sapporo_scaler = pickle.load(f)
        
        with open("obihiro_models/snow_depth_model.pkl", "rb") as f:
            obihiro_model = pickle.load(f)
        
        with open("obihiro_models/scaler.pkl", "rb") as f:
            obihiro_scaler = pickle.load(f)

        return sapporo_model, sapporo_scaler, obihiro_model, obihiro_scaler

streamlitのラクな部分については、ユーザーがクリックできる枠をselectboxだけで設定することができます。これを定義することで各地域に応じたモデルの変更することができます。

region = st.selectbox(
 "地域を選択してください",
 ["札幌", "帯広"])

if region == "札幌":
    model, scaler = sapporo_model, sapporo_scaler
else:  # 帯広
    model, scaler = obihiro_model, obihiro_scaler

プロンプト

Devinにコーディングをさせる上で特に注意しなければならない点として、ChatGPTのようなプロンプトではまともに動かないという点に尽きます。

例えば、「積雪深予測モデルを使ってWebアプリを作って」だけではコーディングどころか応答すらなく、ただ時間だけを消費してしまうので注意が必要です。

ですが、リファレンスとなるコードやデータを所持している場合は、それらを添付して指示することでスムーズな対話をすることができます。

プロンプトの例

ここまでで数分程度でしたので、複雑なプロンプトでなければそれなりに効率化をすることができるのではないかと思います!

完成

実行するにはまずtrain_model.pyを実行します。そうすると、ディレクトリ内にそれぞれの重みファイルが保存されるので、これでアプリを実行する準備は整いました。

Webアプリを実行する際には以下のようにコマンドを入力します。

streamlit run streamlit_app.py

アプリを実行すると、このようにブラウザに画面表示されるため、札幌市を選択して、気象庁が公開している気象データを参照して入力をします。

入力をしてから赤いボタンをクリックすると、このように予測結果が表示されます。

予測結果が61.2cmという結果に対する指摘はさておき、札幌市の積雪深の予測はこのように動作を確認することができました!

予測結果
気象庁|過去の気象データ検索
過去の気象データ検索

おわりに

いかがでしたでしょうか。

今回はDevinを用いて札幌市と帯広市の積雪深予測モデルをWebアプリ化してみました。

DevinなどAIエージェントを導入することでご自分の業務効率を改善できそうだなと感じていただければなと思います。

今回作成したwebアプリは僕のgithubから一応使用することができます。
ですが、ソースコードの問題により学習データを置く場所にだけ注意してください。
必要なライブラリはgithubのREADMEに記載の方法でインストールできます!

GitHub - morishitaimpl/snowdepth_app: 積雪深予測アプリケーション
積雪深予測アプリケーション. Contribute to morishitaimpl/snowdepth_app development by creating an account on GitHub.

今後の課題

気象庁が公開している気象データは地域ごとに収集しているデータが異なります。

例えば、札幌市では陸面/海面気圧を記録してありますが、千歳市にはこのデータが記録されていませんでした。

このようにデータがない場合、積雪深の予測モデルに影響が出ることが考えられます。

学習データは過去のデータであるため、融雪量を計算することができますが、実利用では融雪量を求めることが難しいです。

また、気象データのみで正確な積雪深を予測することが難しいため、他にどのような情報で補うかを考えていく必要があります。

さらに、今回はstreamlitによるアプリであるため、ページ遷移をすることなく、都市に応じて重みファイルを分別することを想定していましたが、検証した結果、どちらかの重みファイルに統一されている可能性があります。

そのため、都市ごとにページ遷移をしてモデルも分別する方が確実だと考えられるので、今後はflaskによるwebアプリを検討します。

参考URL

streamlitを使ったお手軽Webアプリ開発 - Qiita
streamlitを使えばWebアプリケーションが簡単に作成できます。この記事では、streamlitでよく使う機能をサンプルコードと共に紹介し、それらを組み合わせたWebアプリケーションの作成方…
【完全網羅】Streamlitでセレクトボックスを作成する方法
Streamlitのセレクトボックスは、アプリ上でユーザーが選択を行えるようにするために用いる入力機能です。本記事では、Streamlitのセレクトボックスの作成方法から使用できる場面まで、網羅的に解