マテリアルズインフォマティクス(MI)入門②【勾配ブースティング(CatBoost)を用いた未知組成からの高精度な物性予測】

マテリアルズインフォマティクス(MI)入門②【勾配ブースティング(CatBoost)を用いた未知組成からの高精度な物性予測】

前回の記事では、基本の線形回帰モデルで鋼材の強度予測に挑み、訓練データではまずまずの性能(R²=0.551)を示しながらも、未知のテストデータではR²スコアがマイナスになるという、典型的な「過学習」に陥る結果となりました。これは、材料の物性と化学組成の関係が、単純な足し算(線形)では到底表せない複雑なものであることを明確に示しています。

そこで第2回となる今回は、線形モデルの限界を乗り越えるため、より複雑で非線形な関係も巧みに捉えることができる高性能な機械学習アルゴリズム「CatBoost」を導入します。過学習を克服し、高い汎化性能を持つモデルを構築するだけでなく、そのモデルを使って全く新しい材料の強度を予測する瞬間を体験しましょう。

動作検証済み環境

Google Colaboratory
Python 3.11.13
matminer==0.9.3
scikit-learn==1.6.1
pandas==2.2.2
matplotlib==3.10.0
catboost==1.2.8

この記事から学べること

  • 高性能モデルへのステップアップ: CatBoostのような勾配ブースティングモデルで、ベースラインモデルの性能を改善する王道フローを実践できます。
  • 過学習の克服: 訓練データとテストデータ両方で高い性能を示すモデルを構築し、汎化性能の重要性を理解できます。
  • CatBoostの利点と使い方: CatBoostの利点(標準化不要など)を学び、Pythonでの実装方法をマスターできます。
  • 未知の材料の物性予測: 学習済みモデルを使い、任意の化学組成を持つ新材料の物性を予測する「推論」コードを実装できます。

関連理論の解説

1. 決定木ベースのモデルとは?

線形回帰が「$y = aX_1 + bX_2 + …$」という一本の数式で関係性を表現しようとするのに対し、決定木ベースのモデルは「もし特徴量Aが〇〇より大きいなら、次に特徴量Bを…」というように、データを「Yes/No」で次々と分割していくルール(決定木)の集まりで関係性を表現します。これにより、元素間の複雑な相互作用のような、単純な足し算では表せない「非線形」な関係を捉えることができます。

2. 勾配ブースティング (CatBoost) とは?

勾配ブースティングは、決定木をさらに発展させた強力なアンサンブル学習の手法です。一本の精巧な決定木を作るのではなく、多数の「少しだけ賢い(予測精度がそこまで高くない)単純な決定木」を段階的に構築していきます。

  1. まず最初の木が予測を行い、その予測の「間違い(残差)」を計算します。
  2. 次の木は、その「間違い」を正しく予測することを目標に学習します。
  3. このプロセスを何百回、何千回と繰り返し、前の木の失敗を次の木が補うようにモデル全体を少しずつ(勾配降下法的に)改善していきます。

この仕組みにより、CatBoostは個々の決定木の弱点を互いに補い合い、非常に高い予測精度と、未知のデータにも強い汎化性能を両立することができます。

実装方法

ワークフロー

# ===================================================================
# 0. 環境構築:必要なライブラリのインストール
# 1. 必要なライブラリのインポート
# 2. データセットの読み込み & 3. 特徴量エンジニアリング
# 4. 特徴量とターゲットの定義
# 5. データを訓練用とテスト用に分割
# 6. モデルの訓練
# 7. 予測の実行(Train & Test両方)
# 8. モデルの性能評価(Train & Test両方)
# 9. 結果の可視化
# 10. 未知の組成に対する予測(推論)
# ===================================================================

実行手順

  • 以下のコードブロック全体をコピーします。
  • Google Colaboratoryの新しいセルに貼り付けます。
  • セルが選択されていることを確認し、Shift キーと Enter キーを同時に押してコードを実行します。
# ===================================================================
# 0. 環境構築:必要なライブラリのインストール
# ===================================================================
!pip install matminer==0.9.3 scikit-learn==1.6.1 pandas==2.2.2
!pip install matplotlib==3.10.0  catboost==1.2.8

# ===================================================================
# 1. 必要なライブラリのインポート
# ===================================================================
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import re
from matminer.datasets import load_dataset
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
from catboost import CatBoostRegressor

# ===================================================================
# 2. データセットの読み込み & 3. 特徴量エンジニアリング
# ===================================================================
print("ステップ2&3: データセットの読み込みと特徴量エンジニアリング...")
df = load_dataset("matbench_steels")

def extract_value(composition_string, element_name):
    pattern = r"{}(\d+\.?\d*)".format(element_name)
    match = re.search(pattern, str(composition_string))
    if match:
        return float(match.group(1))
    else:
        return 0.0

elements = [
    "Fe",
    "C",
    "Mn",
    "Si",
    "Cr",
    "Ni",
    "Mo",
    "V",
    "N",
    "Nb",
    "Co",
    "W",
    "Al",
    "Ti",
]
for element in elements:
    df[element] = df["composition"].apply(lambda x: extract_value(x, element))

df_clean = df.drop(columns=["composition"])
print("完了しました。")

# ===================================================================
# 4. 特徴量とターゲットの定義
# ===================================================================
features = elements
target = "yield strength"
X = df_clean[features]
y = df_clean[target]

# ===================================================================
# 5. データを訓練用とテスト用に分割
# ===================================================================
print("\nステップ5: データを訓練データとテストデータに分割します...")
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
print("データの分割が完了しました。")

# ★★★ CatBoostでは標準化のステップは不要 ★★★

# ===================================================================
# 6. モデルの訓練
# ===================================================================
print("\nステップ6: CatBoost回帰モデルの学習を開始します...")
model = CatBoostRegressor(random_seed=42, verbose=0)
model.fit(X_train, y_train)
print("モデルの学習が完了しました。")

# ===================================================================
# 7. 予測の実行(Train & Test両方)
# ===================================================================
print("\nステップ7: 予測を実行します...")
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)
print("予測が完了しました。")

# ===================================================================
# 8. モデルの性能評価(Train & Test両方)
# ===================================================================
print("\nステップ8: モデルの性能を評価します...")

# 訓練データに対する性能評価
mae_train = mean_absolute_error(y_train, y_train_pred)
rmse_train = np.sqrt(mean_squared_error(y_train, y_train_pred))
r2_train = r2_score(y_train, y_train_pred)

# テストデータに対する性能評価
mae_test = mean_absolute_error(y_test, y_test_pred)
rmse_test = np.sqrt(mean_squared_error(y_test, y_test_pred))
r2_test = r2_score(y_test, y_test_pred)

print("\n" + "=" * 50)
print("【モデル性能評価の比較】")
print("\n--- 訓練データ (Train) ---")
print(f"  平均絶対誤差 (MAE)    : {mae_train:.3f} MPa")
print(f"  二乗平均平方根誤差 (RMSE) : {rmse_train:.3f} MPa")
print(f"  決定係数 (R2 Score)      : {r2_train:.3f}")

print("\n--- テストデータ (Test) ---")
print(f"  平均絶対誤差 (MAE)    : {mae_test:.3f} MPa")
print(f"  二乗平均平方根誤差 (RMSE) : {rmse_test:.3f} MPa")
print(f"  決定係数 (R2 Score)      : {r2_test:.3f}")
print("=" * 50 + "\n")

# ===================================================================
# 9. 結果の可視化
# ===================================================================
print("ステップ9: 予測結果をグラフで可視化します...")
plt.figure(figsize=(8, 8))
plt.style.use("seaborn-v0_8-whitegrid")
plt.scatter(
    y_train, y_train_pred, alpha=0.6, edgecolors="w", s=50, c="blue", label="Train"
)
plt.scatter(y_test, y_test_pred, alpha=0.6, edgecolors="w", s=50, c="red", label="Test")

max_val = max(y.max(), y_train_pred.max(), y_test_pred.max()) * 1.05
min_val = 0
plt.plot([min_val, max_val], [min_val, max_val], "k--", lw=2, label="Ideal (y=x)")

plt.xlabel("Actual Yield Strength (MPa)", fontsize=14)
plt.ylabel("Predicted Yield Strength (MPa)", fontsize=14)
plt.title("Actual vs. Predicted Yield Strength (CatBoost)", fontsize=16)
plt.legend(fontsize=12)
plt.xlim(min_val, max_val)
plt.ylim(min_val, max_val)
plt.grid(True)
plt.show()
print("可視化処理が完了しました。")

# ===================================================================
# 10. 未知の組成に対する予測(推論)
# ===================================================================
print("\nステップ10: 未知の組成データで降伏強度を予測します...")

# 予測したい仮想の鋼材の組成を定義 (単位: 重量%)
# ここでは例として、中炭素鋼にCrとMoを添加したような組成を想定
new_composition_input = {
    'C': 0.35, 'Mn': 0.7, 'Si': 0.25, 'Cr': 0.9, 'Mo': 0.15,
    'V': 0.05, 'N': 0.008, 'Al': 0.02
}

# モデルが学習したすべての特徴量(元素)を含む辞書を作成し、0で初期化
full_composition = {element: 0.0 for element in features}

# 入力された組成で値を更新
full_composition.update(new_composition_input)

# Feの含有量を計算 (合計が100%になるように)
sum_other_elements = sum(v for k, v in full_composition.items() if k != 'Fe')
full_composition['Fe'] = 100 - sum_other_elements

# 辞書からPandas DataFrameを作成
# DataFrameのコンストラクタに渡すデータはリストでラップする [full_composition]
new_steel_df = pd.DataFrame([full_composition], columns=features)

print("\n予測対象の組成 (wt%):")
print(new_steel_df.to_string(index=False))

# 学習済みモデルで予測を実行
predicted_strength = model.predict(new_steel_df)

print("\n" + "=" * 50)
print("【未知の組成に対する予測結果】")
print(f"  予測される降伏強度: {predicted_strength[0]:.2f} MPa")
print("=" * 50 + "\n")
print("推論処理が完了しました。")
print("\n処理はすべて完了しました。")

実行結果と考察

革命的な性能向上

CatBoostモデルの性能評価は、線形回帰モデルとは全く異なる様相を呈しています。

データ種別 MAE (MPa) RMSE (MPa) R²スコア
訓練データ 15.872 19.656 0.996
テストデータ 75.700 116.075 0.805
  • 訓練データでの性能: R²スコアが0.996と、ほぼ完璧です。これは、CatBoostが訓練データのパターンを非常に高い精度で学習できる、強力な表現力を持っていることを示します。
  • テストデータでの性能: R²スコアが0.805と、訓練データよりは低いものの、非常に高いレベルを維持しています。線形回帰のマイナススコアとは雲泥の差であり、実用的な予測モデルとして機能していることを示します。
  • 汎化性能の獲得: 訓練データとテストデータ両方で高い性能が出ており、モデルが未知のデータに対しても(過学習を抑制しつつ)うまく機能する、高い汎化性能を持つことがわかります。

モデルパフォーマンスの可視化

グラフでは、訓練データ(青)はほぼ完全に理想線上に乗っており、テストデータ(赤)も多少のばらつきはありますが、全体として理想線に強く追従しています。これは、CatBoostが線形回帰では捉えきれなかった非線形な関係性をうまく学習できていることを視覚的に示しています。

未知組成に対する予測結果

予測対象の組成 (wt%):
    Fe    C  Mn   Si  Cr  Ni   Mo    V     N  Nb  Co   W   Al  Ti
97.572 0.35 0.7 0.25 0.9 0.0 0.15 0.05 0.008 0.0 0.0 0.0 0.02 0.0

==================================================
【未知の組成に対する予測結果】
  予測される降伏強度: 1410.40 MPa
==================================================

この結果は、モデルが「C: 0.35%, Mn: 0.7%, Cr: 0.9% …」といった組成を持つ鋼材の降伏強度を約1410.40 MPaと予測したことを示しています。このように、学習済みモデルを使えば、実際に実験を行うことなく、新しい材料の性能を瞬時にシミュレーションできるのです。

コードの詳細解説

ソースコードの各ステップが、マテリアルズインフォマティクスのプロジェクトにおいてどのような意味を持つのか、より深く掘り下げて解説します。

ステップ0 & 1: 環境構築とライブラリのインポート

これは、料理で言えば調理器具と食材を揃える、プロジェクトの最も基本的な準備段階です。

# ===================================================================
# 0. 環境構築:必要なライブラリのインストール
# ===================================================================
!pip install matminer==0.9.3 scikit-learn==1.6.1 pandas==2.2.2
!pip install matplotlib==3.10.0  catboost==1.2.8

# ===================================================================
# 1. 必要なライブラリのインポート
# ===================================================================
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import re
from matminer.datasets import load_dataset
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
from catboost import CatBoostRegressor
  • !pip install ...: Google Colaboratoryの環境に、今回の分析で必要な専門ライブラリをインストールするコマンドです。前回から新たに追加された catboost が、今回の主役となる高性能モデルのライブラリです。
  • import ...: インストールしたライブラリを、Pythonコードの中で実際に使えるように宣言します。特に重要なのが from catboost import CatBoostRegressor で、これにより前回の LinearRegression に代わる、新しい予測モデルの設計図を読み込んでいます。

ステップ2, 3, 4, 5: データ準備と分割

この一連の流れは第1回と全く同じです。これは、MIプロジェクトにおいてデータの前処理パイプラインは、試行錯誤するモデルとは独立して構築されるべきという重要な概念を示しています。一度堅牢なデータ準備の仕組みを作れば、様々なモデルを効率的に試すことができます。

# ===================================================================
# 2. データセットの読み込み & 3. 特徴量エンジニアリング
# ===================================================================
print("ステップ2&3: データセットの読み込みと特徴量エンジニアリング...")
df = load_dataset("matbench_steels")

def extract_value(composition_string, element_name):
    pattern = r"{}(\d+\.?\d*)".format(element_name)
    match = re.search(pattern, str(composition_string))
    if match:
        return float(match.group(1))
    else:
        return 0.0

elements = [
    "Fe",
    "C",
    "Mn",
    "Si",
    "Cr",
    "Ni",
    "Mo",
    "V",
    "N",
    "Nb",
    "Co",
    "W",
    "Al",
    "Ti",
]
for element in elements:
    df[element] = df["composition"].apply(lambda x: extract_value(x, element))

df_clean = df.drop(columns=["composition"])
print("完了しました。")

# ===================================================================
# 4. 特徴量とターゲットの定義
# ===================================================================
features = elements
target = "yield strength"
X = df_clean[features]
y = df_clean[target]

# ===================================================================
# 5. データを訓練用とテスト用に分割
# ===================================================================
print("\nステップ5: データを訓練データとテストデータに分割します...")
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
print("データの分割が完了しました。")
  • データ読み込みと特徴量エンジニアリング: 前回同様、matminer でデータを読み込み、正規表現を用いた自作関数で組成式という「文字列」を、AIが理解できる「数値(各元素の含有率)」に変換(特徴量エンジニアリング)します。
  • データ定義と分割: 予測の原因となる元素含有率を Xに、予測したい結果である降伏強度をyに割り当てます。そして、モデルの性能を公正に評価するため、データを訓練用とテスト用に分割します。random_state=42 で分割方法を固定し、誰が実行しても同じ結果になる「再現性」を確保することは、科学的な検証において極めて重要です。

前回との大きな違い:標準化が不要

ここで、今回のワークフローにおける最初の、そして非常に重要な変更点が登場します。

# ★★★ CatBoostでは標準化のステップは不要 ★★★
  • 線形回帰が標準化を必要とした理由: 前回の線形回帰は、各特徴量の「数値の大きさ(スケール)」に直接影響を受けます。例えば、含有率が ~90% のFeと ~0.1% のCでは、スケールが大きく異なるため、モデルはFeの影響を過大評価しがちでした。これを防ぐため、全元素を「平均0、標準偏差1」という同じ土俵に立たせる「標準化」が必要でした。
  • CatBoostが標準化を不要とする理由: 一方、CatBoostのような決定木ベースのモデルは、データの分割を「ある特徴量が、ある閾値より大きいか小さいか」というルールで行います。例えば「Cの含有率は0.05%より大きいか?」という問いに、Cのスケールが 0.05 であろうと 50 であろうと影響はありません。重要なのは大小関係のみです。このため、事前に特徴量のスケールを揃える必要がなく、前処理のステップが一つ簡略化され、コードがよりシンプルになります。

ステップ6: CatBoostモデルの訓練

ここが今回の核心部分であり、予測システムの「エンジン」を、シンプルな線形回帰から高性能な勾配ブースティングに載せ替える工程です。

# ===================================================================
# 6. モデルの訓練
# ===================================================================
print("\nステップ6: CatBoost回帰モデルの学習を開始します...")
model = CatBoostRegressor(random_seed=42, verbose=0)
model.fit(X_train, y_train)
print("モデルの学習が完了しました。")
  • model = CatBoostRegressor(...)LinearRegression() の代わりに CatBoostRegressor() を呼び出すことで、使用するモデルの種類を宣言します。
  • random_seed=42: CatBoostは内部で、決定木を構築する際にランダムな要素(どの特徴量で分割するかなど)を含みます。この乱数を固定することで、実行のたびにモデルの内部構造が微妙に変わることを防ぎ、結果の再現性を保証します。
  • verbose=0: CatBoostは学習中に、何本目の決定木を学習しているかなどの詳細な進捗ログを出力できます。 verbose=0 は「沈黙モード」を意味し、これらのログを非表示にして、最終的な結果だけをクリーンに出力するための設定です。
  • model.fit(X_train, y_train): これが「学習」を実行するコマンドです。訓練データの特徴量(X_train)とそれに対応する正解の降伏強度(y_train)をモデルに渡します。このコマンド一つで、CatBoostは内部で、前の木の予測間違いを次の木が修正していく、というプロセスを何百回も繰り返し、徐々に賢くなっていくのです。

ステップ7 & 8: 予測と性能評価

学習させたモデルがどれほど賢くなったかを、訓練データ(教科書)とテストデータ(模擬試験)の両方で評価します。

# ===================================================================
# 7. 予測の実行(Train & Test両方)
# ===================================================================
print("\nステップ7: 予測を実行します...")
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)
print("予測が完了しました。")

# ===================================================================
# 8. モデルの性能評価(Train & Test両方)
# ===================================================================
print("\nステップ8: モデルの性能を評価します...")

# 訓練データに対する性能評価
mae_train = mean_absolute_error(y_train, y_train_pred)
rmse_train = np.sqrt(mean_squared_error(y_train, y_train_pred))
r2_train = r2_score(y_train, y_train_pred)

# テストデータに対する性能評価
mae_test = mean_absolute_error(y_test, y_test_pred)
rmse_test = np.sqrt(mean_squared_error(y_test, y_test_pred))
r2_test = r2_score(y_test, y_test_pred)

print("\n" + "=" * 50)
print("【モデル性能評価の比較】")
print("\n--- 訓練データ (Train) ---")
print(f"  平均絶対誤差 (MAE)    : {mae_train:.3f} MPa")
print(f"  二乗平均平方根誤差 (RMSE) : {rmse_train:.3f} MPa")
print(f"  決定係数 (R2 Score)      : {r2_train:.3f}")

print("\n--- テストデータ (Test) ---")
print(f"  平均絶対誤差 (MAE)    : {mae_test:.3f} MPa")
print(f"  二乗平均平方根誤差 (RMSE) : {rmse_test:.3f} MPa")
print(f"  決定係数 (R2 Score)      : {r2_test:.3f}")
print("=" * 50 + "\n")
  • model.predict(): 学習済みの model に、特徴量データを渡して予測値を計算させます。これを訓練データ( X_train )とテストデータ( X_test )の両方に対して行います。
  • 性能比較の重要性:
    • 訓練データでの性能: モデルが学習に使ったデータに対してどれだけうまく適合しているか、つまり「教科書の内容をどれだけ暗記できたか」を示します。

    • テストデータでの性能: モデルが一度も見たことのないデータに対してどれだけ正確な予測ができるか、つまり「教科書で学んだ知識を、初見の問題に応用できるか」を示します。

      この2つの性能を比較することで、モデルの「汎化性能」を客観的に評価できます。

ステップ9: 結果の可視化

数値だけでは分かりにくいモデルの性能を、グラフで直感的に理解します。

# ===================================================================
# 9. 結果の可視化
# ===================================================================
print("ステップ9: 予測結果をグラフで可視化します...")
plt.figure(figsize=(8, 8))
plt.style.use("seaborn-v0_8-whitegrid")
plt.scatter(
    y_train, y_train_pred, alpha=0.6, edgecolors="w", s=50, c="blue", label="Train"
)
plt.scatter(y_test, y_test_pred, alpha=0.6, edgecolors="w", s=50, c="red", label="Test")

max_val = max(y.max(), y_train_pred.max(), y_test_pred.max()) * 1.05
min_val = 0
plt.plot([min_val, max_val], [min_val, max_val], "k--", lw=2, label="Ideal (y=x)")

plt.xlabel("Actual Yield Strength (MPa)", fontsize=14)
plt.ylabel("Predicted Yield Strength (MPa)", fontsize=14)
plt.title("Actual vs. Predicted Yield Strength (CatBoost)", fontsize=16)
plt.legend(fontsize=12)
plt.xlim(min_val, max_val)
plt.ylim(min_val, max_val)
plt.grid(True)
plt.show()
  • Parity Plot(実績値 vs 予測値プロット): このグラフの目的は、予測がどれだけ「理想」に近いかを確認することです。
    • 理想線(y=x: 黒い破線は、予測値と実績値が完全に一致した理想的な状態を示します。
    • プロットの意味: 各点がデータサンプルを表し、点がこの理想線に近ければ近いほど、そのサンプルの予測が正確だったことを意味します。
    • 色の意味: 訓練データ(青)とテストデータ(赤)を重ねてプロットすることで、モデルの振る舞いの違いが一目瞭然となります。強力なモデルは訓練データをほぼ完璧に予測するため、青い点は理想線上に密集します。本当に重要なのは、未知のデータである赤い点が、どれだけ理想線に追従しているかです。これがモデルの真の実力を示しています。

ステップ10: 未知の組成に対する予測(推論)

これまでモデルの性能を評価してきましたが、マテリアルズインフォマティクスの最終的な目標は、学習データには存在しない、全く新しい材料の物性を予測することです。このプロセスを「推論(Inference)」と呼びます。

ここでは、学習済みのCatBoostモデルを使って、私たちが任意に設定した仮想の鋼材の降伏強度を予測します。

# ===================================================================
# 10. 未知の組成に対する予測(推論)
# ===================================================================
print("\nステップ10: 未知の組成データで降伏強度を予測します...")

# 予測したい仮想の鋼材の組成を定義 (単位: 重量%)
# ここでは例として、中炭素鋼にCrとMoを添加したような組成を想定
new_composition_input = {
    'C': 0.35, 'Mn': 0.7, 'Si': 0.25, 'Cr': 0.9, 'Mo': 0.15,
    'V': 0.05, 'N': 0.008, 'Al': 0.02
}

# モデルが学習したすべての特徴量(元素)を含む辞書を作成し、0で初期化
full_composition = {element: 0.0 for element in features}

# 入力された組成で値を更新
full_composition.update(new_composition_input)

# Feの含有量を計算 (合計が100%になるように)
sum_other_elements = sum(v for k, v in full_composition.items() if k != 'Fe')
full_composition['Fe'] = 100 - sum_other_elements

# 辞書からPandas DataFrameを作成
# DataFrameのコンストラクタに渡すデータはリストでラップする [full_composition]
new_steel_df = pd.DataFrame([full_composition], columns=features)

print("\n予測対象の組成 (wt%):")
print(new_steel_df.to_string(index=False))

# 学習済みモデルで予測を実行
predicted_strength = model.predict(new_steel_df)

print("\n" + "=" * 50)
print("【未知の組成に対する予測結果】")
print(f"  予測される降伏強度: {predicted_strength[0]:.2f} MPa")
print("=" * 50 + "\n")
print("推論処理が完了しました。")
print("\n処理はすべて完了しました。")
  • 仮想組成の定義new_composition_input という辞書で、予測したい鋼材の化学組成を定義します。ここでは、一般的な元素を組み合わせていますが、この値を変更することで、様々なカスタム合金の強度をシミュレーションできます。
  • データ形式の統一full_composition = {element: 0.0 for element in features} で、モデルが学習した全元素の器を準備します。これにより、入力されなかった元素は自動的に0%として扱われ、モデルが要求するデータ形式と完全に一致させることができます。
  • Fe含有量の自動計算full_composition['Fe'] = 100 - sum_other_elements で、他の全元素の合計を100から引くことで、主成分である鉄(Fe)の含有量を自動的に計算します。

【なぜFeの量を自動計算するのか?】 予測したい組成が決まっているなら、最初からFeの含有量も固定値で入力すれば良いのでは?と疑問に思うかもしれません。この自動計算には、実用性を高めるための重要な理由が3つあります。

①現実の設計プロセスを反映: 材料開発では「鉄(主成分)に、特性を調整する元素をどれだけ加えるか」と考えます。Feの量は「残り全部」として扱われるのが自然なため、コードもその思考プロセスに合わせることで、直感的に使えるようになっています。

②入力ミスと物理的な矛盾の防止: 全元素の合計は厳密に100%になる必要があります。もし手動でFeを入力すると、合計が99.9%や100.1%になるなど、計算ミスが起こりがちです。自動計算なら合計が必ず100%になることを保証でき、物理的にありえない組成でモデルを動かしてしまうリスクを防ぎます。

③シミュレーションの効率化: 「炭素を0.1%増やしたら強度はどうなる?」といった様々な試行錯誤が、このモデルの醍醐味です。この仕組みがあれば、関心のある合金元素の量を変えるだけでFeの量が自動で再計算されるため、手間なく次々と新しい材料の性能を試すことができます。

  • 予測の実行model.predict(new_steel_df) コマンド一つで、定義した新組成の降伏強度(MPa)を瞬時に予測します。

このステップにより、単にモデルの性能を評価するだけでなく、新しい材料設計のための強力なツールとしてAIモデルを活用する道が開かれます。

最後に

今回は、過学習に陥った線形回帰モデルから、高性能なCatBoostモデルへ移行することで、予測精度を飛躍的に向上させ、実際に未知の組成の物性を予測するところまでを実践しました。

この一連のプロセスは、マテリアルズインフォマティクスの典型的なワークフローそのものです。

  • まずシンプルなモデルでベースラインを作る。
  • 性能を評価し、モデルの限界を特定する。
  • より高度なモデルを導入し、ベースラインを超える。
  • モデルの汎化性能を客観的に評価する。
  • 完成したモデルを使い、新しい材料の特性を予測(推論)する。

このステップを踏むことで、闇雲にモデルを作るのではなく、客観的な評価に基づいてプロジェクトを進めることができます。

しかし、この高精度なモデルは「なぜ」その予測をしたのかが分からない、新たな課題「ブラックボックス問題」を生み出しました。次回は、このブラックボックスに光を当てる「説明可能なAI(XAI)」の世界に足を踏み入れ、モデルの判断根拠を解明していきます。

コメントを残す

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