🏔️

【14分訓練・18秒予測】AWS AIサロゲートモデルで自動車流体設計を実践

はじめに

前回の記事では、AWSのAIサロゲートモデルソリューション:AI Surrogate Models in Engineering on AWS(MLSimKit)の概要と3つの予測タイプについて説明しました。

https://zenn.dev/aws_japan/articles/59829d08edbea4

AIサロゲートモデル イメージ

今回は、実際にAWS EC2上でMLSimKitを動かし、KPI予測手法で車両の揚力係数を予測するまでの手順を解説します。

KPI予測(Key Performance Indicator Prediction)イメージ

KPI予測の公式チュートリアルでは、MLSimKitのインストールやデータセットのダウンロード、モデル訓練等の手順が説明されていますが、EC2環境の構築方法や、実際に動かす際のトラブルシューティングについては記載されていません。

そこで本記事では、筆者が何度か試行を重ねて成功した、低コストで素早く実行できる、お勧め構成・手順をまとめています。

事前準備:

  1. MLSimKitリポジトリのクローン(ローカル環境)

    git clone https://github.com/awslabs/ai-surrogate-models-in-engineering-on-aws.git
    cd ai-surrogate-models-in-engineering-on-aws
    
  2. 【オプション】Amazon Q Developer CLIのインストール

実行手順概要:

フェーズ
EC2起動
SSH接続・GPU確認
MLSimKitインストール
データダウンロード
マニフェスト作成
前処理実行
訓練実行
テスト予測

第1章: 実行環境の準備

1-0. アーキテクチャ概要

本チュートリアルで構築するAWSアーキテクチャは以下の通りです:

**ネットワーク構成:**
- **VPC**: デフォルトVPCを使用(各AWSアカウントに自動作成済み)
  - 例: 172.31.0.0/16(本検証での値)
- **サブネット**: パブリックサブネット(インターネット接続可能)
  - 例: 172.31.32.0/20(本検証での値)
  - セキュリティグループで自分のIPのみ許可
- **Availability Zone**: 任意のAZ
  - 例: us-east-1c(本検証での値)
- **インターネットゲートウェイ**: SSH接続に必要(デフォルトVPCに自動アタッチ済み)
- **セキュリティグループ**: SSH (22) のみ許可、送信元は自分のIPアドレスのみ
- **外部接続**: Hugging FaceからWindsorMLデータセット(1.7GB)をダウンロード

**本番環境での推奨構成:**
- プライベートサブネット + NAT Gateway + Bastion Host
- より高いセキュリティが必要な場合に使用

1-1. EC2インスタンスの起動

推奨スペック

**インスタンスタイプ: g5.2xlarge**
- GPU: NVIDIA A10G × 1(24GB VRAM)
- vCPU: 8コア
- メモリ: 32GB
- コスト: $1.212/時間(us-east-1)
**AMI: Deep Learning Base GPU AMI (Ubuntu 22.04)**
- CUDA 12.1プリインストール
- NVIDIAドライバ設定済み
- Python 3.10搭載
**ストレージ: 100GB EBS gp3**
- WindsorML: 1.7GB
- システム + 作業領域: 約67GB
- 余裕を持って100GB推奨(約30GB空き)

起動手順

1. キーペアの作成とSecrets Managerへの保存

# キーペアを作成してSecrets Managerに保存
KEY_MATERIAL=$(aws ec2 create-key-pair \
  --key-name mlsimkit-tutorial-key \
  --query 'KeyMaterial' \
  --output text)

aws secretsmanager create-secret \
  --name mlsimkit-tutorial-key \
  --secret-string "$KEY_MATERIAL" \
  --region us-east-1

echo "秘密鍵をSecrets Managerに保存しました"

2. セキュリティグループの作成

# 現在のIPアドレスを取得
MY_IP=$(curl -s https://checkip.amazonaws.com)

# セキュリティグループを作成
SG_ID=$(aws ec2 create-security-group \
  --group-name mlsimkit-tutorial-sg \
  --description "Security group for MLSimKit tutorial" \
  --query 'GroupId' \
  --output text)

# SSH接続を許可
aws ec2 authorize-security-group-ingress \
  --group-id $SG_ID \
  --protocol tcp \
  --port 22 \
  --cidr ${MY_IP}/32

3. EC2インスタンスの起動

# インスタンスを起動
INSTANCE_ID=$(aws ec2 run-instances \
  --image-id ami-0601999f27e2188a7 \
  --instance-type g5.2xlarge \
  --key-name mlsimkit-tutorial-key \
  --security-group-ids $SG_ID \
  --block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":100,"VolumeType":"gp3"}}]' \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=MLSimKit-Windsor-Tutorial}]' \
  --query 'Instances[0].InstanceId' \
  --output text)

echo "Instance ID: $INSTANCE_ID"

# インスタンスが起動するまで待機
aws ec2 wait instance-running --instance-ids $INSTANCE_ID

# パブリックIPを取得
PUBLIC_IP=$(aws ec2 describe-instances \
  --instance-ids $INSTANCE_ID \
  --query 'Reservations[0].Instances[0].PublicIpAddress' \
  --output text)

echo "Public IP: $PUBLIC_IP"

1-2. SSH接続

秘密鍵の取得

# Secrets Managerから秘密鍵を取得
aws secretsmanager get-secret-value \
  --secret-id mlsimkit-tutorial-key \
  --region us-east-1 \
  --query 'SecretString' \
  --output text > mlsimkit-tutorial-key.pem

# 権限設定
chmod 400 mlsimkit-tutorial-key.pem

接続

# EC2に接続(上記で取得したPUBLIC_IPを使用)
ssh -i mlsimkit-tutorial-key.pem ubuntu@$PUBLIC_IP

# または、IPアドレスを直接指定
# ssh -i mlsimkit-tutorial-key.pem ubuntu@<EC2のパブリックIP>

接続成功の確認:

# GPU確認
nvidia-smi

# 出力例:
# +-----------------------------------------------------------------------------------------+
# | NVIDIA-SMI 580.95.05              Driver Version: 580.95.05      CUDA Version: 13.0     |
# |-------------------------------+----------------------+--------------------------------+
# | GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
# | Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
# |===============================+======================+================================|
# |   0  NVIDIA A10G              On  | 00000000:00:1E.0 Off |                    0 |
# |  0%   23C    P8              11W / 300W |      0MiB / 23028MiB |      0%      Default |
# +-------------------------------+----------------------+--------------------------------+

重要: GPU認識の確認

訓練を開始する前に、必ずGPUが正しく認識されているか確認してください。

# GPU認識の確認
nvidia-smi | grep "NVIDIA A10G"

期待される出力:

|   0  NVIDIA A10G              On  | 00000000:00:1E.0 Off |                    0 |

もしGPUが認識されていない場合:

  • 訓練時間が遅くなります
  • 以下の「GPU認識エラーの場合」を参照して解決してください
  • 解決後、必ずnvidia-smiでGPU認識を再確認してください

GPU認識エラーの場合

# 症状
nvidia-smi
# NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver

# 原因
# カーネルバージョンとNVIDIAドライバーの不一致
# 新しいカーネル(6.8.0-1041)でドライバー未対応

# 確認
uname -r  # 現在のカーネル
dkms status  # ドライバーがインストールされているカーネル

# 解決方法1: 古いカーネルで再起動
sudo grub-reboot '1>2'
sudo reboot

# 解決方法2: 現在のカーネル用にドライバー再ビルド(時間がかかる)
sudo dkms install nvidia/580.95.05 -k $(uname -r)

# 確認
nvidia-smi  # GPU認識を確認

1-3. MLSimKitインストール

MLSimKitの説明はこちらを参照

前提パッケージのインストール

# python3-venv インストール
sudo apt-get update
sudo apt-get install -y python3.10-venv

MLSimKitのダウンロード

# GitHubからダウンロード
wget https://github.com/awslabs/ai-surrogate-models-in-engineering-on-aws/archive/refs/heads/main.tar.gz

# 解凍
tar -xzf main.tar.gz

# ディレクトリ移動
cd ai-surrogate-models-in-engineering-on-aws-main

インストール実行

# システムワイドインストール
pip install -e .

インストール完了の確認:

# バージョン確認
mlsimkit-learn --version

# 出力例:
# ML for Simulation Toolkit, version 0.1.0

第2章: WindsorMLデータセットの準備

2-1. データセットのダウンロード

WindsorMLデータセットの説明はこちらを参照

チュートリアルディレクトリへ移動

cd tutorials/kpi/windsor
ls -la

利用可能なスクリプト:

  • download-dataset - データセットダウンローダー
  • run-create-manifest-training - 学習用マニフェスト作成
  • run-training-pipeline - 学習パイプライン実行
  • run-create-manifest-prediction - 予測用マニフェスト作成
  • run-prediction - 予測パイプライン実行

データセットダウンロード実行

# データ保存先ディレクトリ作成
mkdir -p ~/datasets

# ダウンロード実行
./download-dataset ~/datasets

プロンプトへの対応:

Download all runs? (y/n): 

y と入力してEnterキーを押す(全データダウンロード)

ダウンロード内容:

  • データセット: WindsorML
  • サイズ: 1.7GB
  • ケース数: 350ケース(run_0 〜 run_349)
  • ソース: Hugging Face (neashton/windsorml)

Hugging Face レート制限エラーが出た場合

# 症状
HTTP 429 Too Many Requests

# 原因
同時ダウンロード数が多すぎてレート制限に引っかかった

# 解決方法1: 待ってから再実行
# Hugging Faceはローカルキャッシュを使用するため、
# 既にダウンロード済みのファイルは再ダウンロードされない
./download-dataset ~/datasets

# 解決方法2: 1ファイルずつダウンロード(推奨)
# download-datasetスクリプトを編集して max_workers=1 を追加

2-2. データ構造の確認

ダウンロードされたファイル

# ディレクトリ構造確認
ls ~/datasets/

# 出力例:
# run_0  run_1  run_2  ... run_354

1つのケースの中身

# run_0の内容確認
ls ~/datasets/run_0/

# 出力例:
# windsor_0.stl      ← 車体の3D形状
# force_mom_0.csv    ← CFD結果(KPI値)

CFD結果の確認

# KPI値の確認
cat ~/datasets/run_0/force_mom_0.csv

# 出力例:
# cd, cs, cl, cmy
# 0.2818169578178322,0.0008234405065462456,0.48822197919945154,-0.07294317299334006

KPI値の意味:

  • cd: 抗力係数(Drag Coefficient)- 空気抵抗
  • cs: 横力係数(Side force Coefficient)- 横風の影響
  • cl: 揚力係数(Lift Coefficient)- 浮き上がる力
  • cmy: ピッチングモーメント係数 - 前後の回転力

これらの値は、実際のCFDシミュレーション(数時間かかる)で計算された結果です。MLSimKitは、これらの値を短時間で予測することを目指します。


第3章: マニフェストの作成

3-1. 訓練用マニフェストの作成

マニフェスト作成実行

./run-create-manifest-training ~/datasets

処理内容:

  • 355ケースのSTLファイルとCSVファイルをスキャン
  • 各ケースの形状ファイルとKPI値を紐付け
  • JSON Lines形式でマニフェストファイルを生成

生成されるファイル:

# マニフェストファイル確認
ls -lh training.manifest

# 出力例:
# -rw-rw-r-- 1 ubuntu ubuntu 59K Nov 14 06:00 training.manifest

マニフェストは、以下のような図面ごとの関係性を多数のケース(今回の場合355ケース)で定義するイメージになります。

マニフェストの内容確認

# 最初の3行を表示
head -3 training.manifest

出力例:

{"geometry_files": ["file:///home/ubuntu/datasets/run_0/windsor_0.stl"], "kpi": [0.2818169578178322, 0.0008234405065462456, 0.48822197919945154, -0.07294317299334006]}
{"geometry_files": ["file:///home/ubuntu/datasets/run_1/windsor_1.stl"], "kpi": [0.32251110051821463, -0.059431832381329826, -0.061135997912917385, -0.04094381732630274]}

マニフェストの役割:

  • 学習データの入力(geometry_files)と出力(kpi)を定義
  • 350ケースが学習用に使用される

3-2. 訓練設定の確認

デフォルト設定ファイル

公式チュートリアルのデフォルト設定(training.yaml)を確認します:

cat training.yaml

WindsorMLデータセットには4つのKPI値(Cd, Cs, Cl, CMy)が含まれていますが、デフォルトのtraining.yamlは1つのKPI(Cl: 揚力係数)のみを予測します。

重要な設定:

kpi:
  manifest_uri: training.manifest

  train:
    output_kpi_indices: "2"  # Cl(揚力係数)のみ予測
    pooling_type: max        
    epochs: 100
    opt:
      learning_rate: 0.003

  predict:
    compare-groundtruth: true
  • index 0: Cd(抗力係数)
  • index 1: Cs(横力係数)
  • index 2: Cl(揚力係数) ← デフォルト
  • index 3: CMy(ヨーモーメント係数)

もし4つ全ての係数を予測したい場合は、それぞれの係数について一つずつ学習してモデルを作成してから予測することになります(今回の試行 ×4 の試行を要することになります)。


第4章: 前処理の実行

4-1. 前処理の実行(初回のみ)

KPI学習では前処理データを再利用しますが、初回は前処理を実行する必要があります

# デフォルト設定で前処理のみ実行
mlsimkit-learn --config training.yaml kpi preprocess

処理内容:

  • 350個のSTLファイルをMGN(MeshGraphNet)が扱えるグラフ構造に変換
  • 訓練/検証/テスト用にデータ分割(60%/20%/20%)
  • 前処理データをoutputs/training/preprocessed_dataに保存

MGN(MeshGraphNet)の説明はこちらを参照


4-2. データ分割の確認

# マニフェストファイルの確認
wc -l outputs/training/*.manifest

# 出力例:
#  210 outputs/training/train.manifest      ← 訓練用(60%)
#   70 outputs/training/validate.manifest   ← 検証用(20%)
#   70 outputs/training/test.manifest       ← テスト用(20%)

データ分割の意味:

  • 訓練用(60%): モデルの学習に使用
  • 検証用(20%): 学習中の性能評価とハイパーパラメータ調整
  • テスト用(20%): 最終的な性能評価(学習に未使用)

4-3. 前処理データサイズの確認

du -sh outputs/training/preprocessed_data

# 出力例:
# 3.7G    outputs/training/preprocessed_data

第5章: モデルの訓練

5-1. 訓練パイプラインの実行

訓練開始

# KPI学習を実行
nohup mlsimkit-learn --config training.yaml kpi train > training.log 2>&1 &

# プロセスIDを記録
echo $!

実行内容:

  • Cl(揚力係数)のみを学習
  • 100エポック実行

5-2. 進捗確認

# リアルタイムでログを確認
tail -f training.log

# Ctrl+C で抜ける

訓練の流れ:

[INFO] Training:   0%|          | 0/100 [00:00<?, ?epochs/s]
[INFO] Epoch 0: train loss = 0.988; validation loss = 1.209
...
[INFO] Training: 100%|██████████| 100/100 [13:50<00:00, 8.30s/epochs]
[INFO] Epoch 21: train loss = 0.405; validation loss = 0.420

実測時間: 14分
速度: 8.3秒/エポック

5-3. 訓練結果の確認

訓練が完了したら、損失の推移を確認します:

ポイント:

  • Train LossとValidation Lossが両方とも減少し(学習が進み)、収束に向かっている
  • エポック96で最良の検証ロス(0.356)を達成
  • Train Loss(0.359)とValidation Loss(0.356)のギャップが小さい → 過学習なし、新しいデータでも高精度で予測可能

Train Loss(訓練ロス): 訓練データでの予測誤差
Validation Loss(検証ロス): 検証データでの予測誤差

計算式:

Loss = MSE(pred, actual)
     = 平均((予測値 - 実測値)²)

第6章: テストデータでの評価

6-1. テストデータでの予測実行

訓練完了後、テストデータ(70サンプル)で最終的な精度を評価します:

mlsimkit-learn --output-dir outputs/training --config training.yaml kpi predict --manifest-path outputs/training/test.manifest

実行内容:

  • テストデータ70サンプルで予測
  • Cl(揚力係数)の精度を計算
  • 実測時間: 18秒

6-2. テストデータ精度の確認

# 精度指標を確認
cat outputs/training/predictions/dataset_prediction_error_metrics.csv

グラフの見方:

  • 横軸: AIサロゲートモデル予測値
  • 縦軸: CFDシミュレーション実測値
  • 灰色の対角線: 完全一致のライン

評価:

  • 点が対角線に沿って分布 → 高精度
  • Cl = -0.4 〜 0.8の全範囲で予測可能
  • 外れ値がほとんどない

テストデータ(70サンプル)での精度:

指標 評価
MAPE 1.87% 優秀
方向性正確度 89.4% 優秀

補足説明. MAPE(Mean Absolute Percentage Error)

(クリックして展開)
定義

平均絶対パーセント誤差 - 相対誤差をパーセントで表示

計算式
MAPE = 平均(|予測値 - 実測値| / |実測値|) × 100%
具体例(抗力係数Cd)
サンプル1: 実測 0.30, 予測 0.32 → |0.32-0.30|/0.30 = 0.067 = 6.7%
サンプル2: 実測 0.31, 予測 0.28 → |0.28-0.31|/0.31 = 0.097 = 9.7%
サンプル3: 実測 0.29, 予測 0.30 → |0.30-0.29|/0.29 = 0.034 = 3.4%

MAPE = (6.7% + 9.7% + 3.4%) / 3 = 6.6%

補足説明. 方向性正確度(Directional Correctness)

(クリックして展開)
定義

増減の傾向が合っている割合

計算方法
全てのサンプルペア(A, B)について:
  実測値でA < B かつ 予測値でA < B → 一致 ✓
  実測値でA > B かつ 予測値でA > B → 一致 ✓
  それ以外 → 不一致 ✗

方向性正確度 = 一致したペア数 / 全ペア数
具体例(抗力係数Cd)
サンプルA: 実測 0.30, 予測 0.28
サンプルB: 実測 0.32, 予測 0.31
サンプルC: 実測 0.28, 予測 0.33

ペア(A,B): 実測 A<B, 予測 A<B → 一致 ✓
ペア(A,C): 実測 A>C, 予測 A<C → 不一致 ✗
ペア(B,C): 実測 B>C, 予測 B<C → 不一致 ✗

方向性正確度 = 1/3 = 33.3%

第7章: クリーンアップ

7-1. EC2インスタンスの停止

インスタンス停止

# インスタンスを停止(ローカルマシンで実行)
aws ec2 stop-instances --instance-ids $INSTANCE_ID

# または、インスタンスIDを直接指定
# aws ec2 stop-instances --instance-ids i-XXXXX

重要:

  • 使用後は必ず停止してください
  • 停止しないと課金が継続されます($1.212/時間)

7-2. リソースのクリーンアップ

Secrets Managerの秘密鍵を削除(今後、今回のEC2を使用しない場合)

# 秘密鍵を削除
aws secretsmanager delete-secret \
  --secret-id mlsimkit-tutorial-key \
  --force-delete-without-recovery \
  --region us-east-1

# ローカルの秘密鍵ファイルも削除
rm mlsimkit-tutorial-key.pem

EC2キーペアとセキュリティグループの削除(今後、今回のEC2を使用しない場合)

# キーペアを削除
aws ec2 delete-key-pair --key-name mlsimkit-tutorial-key

# セキュリティグループを削除
aws ec2 delete-security-group --group-id $SG_ID

重要: Secrets Managerの秘密鍵を削除しないと、$0.40/月の課金が継続されます。


まとめ

本記事では、EC2上で、AWSのAIサロゲートモデルソリューション・MLSimKitを使用し、WindsorML車両空力データセット210ケースを対象にした流体シミュレーションKPI予測を行いました。

従来、1つの車両形状の空力性能を評価するには数時間のCFDシミュレーションが必要でしたが、AIサロゲートモデルを使うことで:

訓練時間: わずか14分(210ケースの学習)
予測時間: わずか18秒(70ケースのテスト評価)
予測精度: MAPE 1.87%(揚力係数Clの予測誤差。優秀)

を達成しました。

これにより、新しい車両形状の空力性能を数秒で高精度に予測できるようになり、設計の初期段階で多数の形状案を素早く低コストで評価することが可能になります。

MLSimKitの全体概要説明についてはこちらの記事をご参照ください。
https://zenn.dev/aws_japan/articles/59829d08edbea4


アマゾン ウェブ サービス ジャパン (有志)

Discussion