4  組成式から特徴量表を作る

材料の化学式そのものは特徴量ではない。
組成式を数値の行に変換する——それが機械学習への翻訳である。

本章では、前章で抽出した記述子辞書(8イオンの物性値)と教師データ(18組成の \(\Delta_1\) 実測値)を組み合わせて、機械学習の入力となる 特徴量テーブル を構築する。

3段階の構成で進める。

  1. B サイト半径のみ: 1変数の最も簡単な特徴量
  2. B サイト4記述子: 半径に加え、イオン化ポテンシャル・電子親和力・電気陰性度
  3. A/B サイト分離の完全版: Sr ドーピング(A サイト)も含めた full table

この3段階は、論文の構造と対応している。論文では最初の物理ベースラインを「有効 B サイト半径 \(r_B\)」で作り、残りの特徴量は残差モデルの入力として使う。つまり、段階1は物理ベースライン、段階3は論文本来のフル入力に対応する。

1 3.1 2つの表の役割を確認する

機械学習の特徴量テーブルを作るには、2つの表が必要である。

ファイル 1行の意味 役割
記述子辞書 descriptor_selected.csv 特定の OS・CN をもつイオン1種 部品表
教師データ teacher_data.csv 組成1つ(組成式 + \(\Delta_1\) 組立指示書

記述子辞書は「部品の性能表」、教師データは「どの部品をどれだけ混ぜるかの指示書」である。この2つを組み合わせて、1行1組成・列が数値のみの特徴量テーブルを作ることが、本章のゴールである。

コード
import pandas as pd
import numpy as np

# 記述子辞書(前章で作成)
desc = pd.read_csv("data/descriptor_selected.csv")
print("記述子辞書:")
desc
記述子辞書:
element atomic_N OS CN Ion_Radius IonizationPotential_eV_ ElectronAffinity_eV_ Electronegativity
0 Al 13 3 6 0.535 5.9858 0.44 1.61
1 Co 27 3 6 0.610 7.8810 0.66 1.88
2 Ga 31 3 6 0.620 5.9993 0.30 1.81
3 Ir 77 3 6 0.680 9.1000 1.57 2.20
4 La 57 3 12 1.360 5.5770 0.50 1.10
5 Rh 45 3 6 0.665 7.4589 1.14 2.28
6 Sr 38 2 12 1.440 5.6948 0.11 0.95
7 Y 39 3 6 0.900 6.2170 0.31 1.22
コード
# 教師データ(18組成)
train = pd.read_csv("data/teacher_data.csv")
print(f"教師データ: {len(train)} 行")
train
教師データ: 18 行
composition system x_A A_sub x_B B_sub delta_1 delta_2
0 LaCoO3 pure 0.00 NaN 0.000 NaN 132 200
1 La0.99Sr0.01CoO3 Sr 0.01 Sr 0.000 NaN 128 170
2 La0.98Sr0.02CoO3 Sr 0.02 Sr 0.000 NaN 120 190
3 La0.97Sr0.03CoO3 Sr 0.03 Sr 0.000 NaN 115 150
4 LaCo0.998Al0.002O3 Al 0.00 NaN 0.002 Al 145 220
5 LaCo0.996Al0.004O3 Al 0.00 NaN 0.004 Al 145 220
6 LaCo0.99Ga0.01O3 Ga 0.00 NaN 0.010 Ga 140 220
7 LaCo0.98Ga0.02O3 Ga 0.00 NaN 0.020 Ga 140 220
8 LaCo0.97Ga0.03O3 Ga 0.00 NaN 0.030 Ga 140 230
9 LaCo0.95Ga0.05O3 Ga 0.00 NaN 0.050 Ga 130 260
10 LaCo0.99Rh0.01O3 Rh 0.00 NaN 0.010 Rh 119 180
11 LaCo0.98Rh0.02O3 Rh 0.00 NaN 0.020 Rh 105 200
12 LaCo0.97Rh0.03O3 Rh 0.00 NaN 0.030 Rh 90 210
13 LaCo0.95Rh0.05O3 Rh 0.00 NaN 0.050 Rh 61 280
14 LaCo0.99Ir0.01O3 Ir 0.00 NaN 0.010 Ir 114 220
15 LaCo0.98Ir0.02O3 Ir 0.00 NaN 0.020 Ir 99 220
16 LaCo0.97Ir0.03O3 Ir 0.00 NaN 0.030 Ir 63 220
17 LaCo0.95Ir0.05O3 Ir 0.00 NaN 0.050 Ir 54 220

小課題 3-1 2つの表の違い

記述子辞書と教師データについて、以下を答えよ。

  1. どちらが「1行1組成」か
  2. どちらが「lookup 用の辞書」か
  3. 教師データの delta_1 列は、記述子辞書に含まれるか

解答例 3-1

  1. 教師データが「1行1組成」である。記述子辞書は「1行1イオン」
  2. 記述子辞書が lookup 用の辞書である
  3. 含まれない。\(\Delta_1\) は実験で測定した値であり、イオンの物性値ではない

2 3.2 記述子辞書を引く仕組みを作る

記述子辞書から値を取り出すには、(元素, OS, CN)の3つ組をキーにする。pandas の set_index でマルチインデックスにすると、辞書引きのように使える。

コード
# マルチインデックスで辞書化
desc_idx = desc.set_index(["element", "OS", "CN"])

def lookup(element, os, cn, key):
    """記述子辞書から値を取り出す"""
    return desc_idx.loc[(element, os, cn), key]

# テスト: Co³⁺(CN=6) と Y³⁺(CN=6) のイオン半径
r_co = lookup("Co", 3, 6, "Ion_Radius")
r_y  = lookup("Y",  3, 6, "Ion_Radius")
print(f"Co³⁺(CN=6) のイオン半径: {r_co:.4f} Å")
print(f"Y³⁺(CN=6)  のイオン半径: {r_y:.4f} Å")
print(f"差: {r_y - r_co:.4f} Å")
Co³⁺(CN=6) のイオン半径: 0.6100 Å
Y³⁺(CN=6)  のイオン半径: 0.9000 Å
差: 0.2900 Å

Y³⁺ は Co³⁺ よりかなり大きい。B サイトに Y を入れると格子に歪みが生じることが、この半径の差からも予想できる。

よくある誤り

lookup("Co", 3, 6, "Ion_Radius")lookup("Co", 2, 6, "Ion_Radius") は異なる値を返す。元素名だけで辞書を引くと、間違った酸化数・配位数の値が混入する。元素名・OS・CN の3つ組で初めてイオンが特定される。

3 3.3 段階1:B サイト半径のみ

最も簡単な特徴量から始める。B サイト置換系(LaCo\(_{1-x}\)M\(_x\)O\(_3\))について、有効 B サイト半径 \(r_B\) を計算する。

\[r_B = (1 - x_B) \cdot r(\text{Co}^{3+}, \text{CN}=6) + x_B \cdot r(M^{3+}, \text{CN}=6)\]

この式の意味は単純である。B サイトの \((1-x_B)\) は Co で占められ、残りの \(x_B\) がドーパント \(M\) で占められる。それぞれのイオン半径を占有率で加重平均したものが \(r_B\) である。

まず、B サイト置換系だけを取り出す。

コード
# B サイト置換系: A サイトは La のみ(x_A = 0)
train_b = train[train["x_A"] == 0.0].copy()
print(f"B サイト置換系: {len(train_b)} 行")
train_b[["composition", "x_B", "B_sub", "delta_1"]]
B サイト置換系: 15 行
composition x_B B_sub delta_1
0 LaCoO3 0.000 NaN 132
4 LaCo0.998Al0.002O3 0.002 Al 145
5 LaCo0.996Al0.004O3 0.004 Al 145
6 LaCo0.99Ga0.01O3 0.010 Ga 140
7 LaCo0.98Ga0.02O3 0.020 Ga 140
8 LaCo0.97Ga0.03O3 0.030 Ga 140
9 LaCo0.95Ga0.05O3 0.050 Ga 130
10 LaCo0.99Rh0.01O3 0.010 Rh 119
11 LaCo0.98Rh0.02O3 0.020 Rh 105
12 LaCo0.97Rh0.03O3 0.030 Rh 90
13 LaCo0.95Rh0.05O3 0.050 Rh 61
14 LaCo0.99Ir0.01O3 0.010 Ir 114
15 LaCo0.98Ir0.02O3 0.020 Ir 99
16 LaCo0.97Ir0.03O3 0.030 Ir 63
17 LaCo0.95Ir0.05O3 0.050 Ir 54

次に、加重平均を計算する関数を作る。

コード
def weighted_bsite(row, key):
    """B サイトの占有率加重平均を計算する"""
    co_val = lookup("Co", 3, 6, key)
    if pd.isna(row["B_sub"]) or row["x_B"] == 0:
        return co_val
    dopant_val = lookup(row["B_sub"], 3, 6, key)
    return (1 - row["x_B"]) * co_val + row["x_B"] * dopant_val

# B サイト有効半径を計算
train_b["r_B"] = train_b.apply(
    lambda r: weighted_bsite(r, "Ion_Radius"), axis=1
)

train_b[["composition", "B_sub", "x_B", "r_B", "delta_1"]]
composition B_sub x_B r_B delta_1
0 LaCoO3 NaN 0.000 0.61000 132
4 LaCo0.998Al0.002O3 Al 0.002 0.60985 145
5 LaCo0.996Al0.004O3 Al 0.004 0.60970 145
6 LaCo0.99Ga0.01O3 Ga 0.010 0.61010 140
7 LaCo0.98Ga0.02O3 Ga 0.020 0.61020 140
8 LaCo0.97Ga0.03O3 Ga 0.030 0.61030 140
9 LaCo0.95Ga0.05O3 Ga 0.050 0.61050 130
10 LaCo0.99Rh0.01O3 Rh 0.010 0.61055 119
11 LaCo0.98Rh0.02O3 Rh 0.020 0.61110 105
12 LaCo0.97Rh0.03O3 Rh 0.030 0.61165 90
13 LaCo0.95Rh0.05O3 Rh 0.050 0.61275 61
14 LaCo0.99Ir0.01O3 Ir 0.010 0.61070 114
15 LaCo0.98Ir0.02O3 Ir 0.020 0.61140 99
16 LaCo0.97Ir0.03O3 Ir 0.030 0.61210 63
17 LaCo0.95Ir0.05O3 Ir 0.050 0.61350 54

小課題 3-2 半径の物理的チェック

出力された表を見て、以下を確認せよ。

  1. LaCoO₃(ドーパントなし)の \(r_B\) は Co³⁺ の半径と一致するか
  2. Rh, Ir 系で \(x_B\) が増えると \(r_B\) はどう変化するか。その方向は物理的に正しいか
  3. Al 系の \(r_B\) は LaCoO₃ の \(r_B\) と比べてどうか

解答例 3-2

  1. LaCoO₃ は \(x_B = 0\) なので、\(r_B = r(\text{Co}^{3+})\) と一致する(加重平均の式でドーパント項が消える)
  2. Rh³⁺, Ir³⁺ は Co³⁺ より大きいので、\(x_B\) の増加とともに \(r_B\) は増加する。大きなイオンを混ぜると平均半径が大きくなるのは物理的に正しい
  3. Al³⁺(CN=6: 0.535 Å)は Co³⁺(CN=6: 0.610 Å)より小さいため、Al 系の \(r_B\) はわずかに減少する。ただし \(x_B\) が小さい(0.002, 0.004)ので変化は微小である
コード
# Stage 1 の CSV を保存
feature_r = train_b[["composition", "delta_1", "r_B"]].copy()
feature_r.to_csv("data/feature_radius_bsite.csv", index=False)
print("feature_radius_bsite.csv を保存した")
feature_r
feature_radius_bsite.csv を保存した
composition delta_1 r_B
0 LaCoO3 132 0.61000
4 LaCo0.998Al0.002O3 145 0.60985
5 LaCo0.996Al0.004O3 145 0.60970
6 LaCo0.99Ga0.01O3 140 0.61010
7 LaCo0.98Ga0.02O3 140 0.61020
8 LaCo0.97Ga0.03O3 140 0.61030
9 LaCo0.95Ga0.05O3 130 0.61050
10 LaCo0.99Rh0.01O3 119 0.61055
11 LaCo0.98Rh0.02O3 105 0.61110
12 LaCo0.97Rh0.03O3 90 0.61165
13 LaCo0.95Rh0.05O3 61 0.61275
14 LaCo0.99Ir0.01O3 114 0.61070
15 LaCo0.98Ir0.02O3 99 0.61140
16 LaCo0.97Ir0.03O3 63 0.61210
17 LaCo0.95Ir0.05O3 54 0.61350

特徴量は、記述子辞書の値を組成比で加重平均したものである。式にすると1行だが、この「辞書引き → 重み付け → 平均」の3ステップが、材料 ML の入力データ構築の本質である。

4 3.4 段階2:4記述子に拡張する

半径だけでは情報が足りない。論文では、以下の4種の記述子を使っている。

記述子 列名 物理的意味
イオン半径 Ion_Radius イオンの大きさ → 格子定数に影響
イオン化ポテンシャル IonizationPotential_eV_ 電子を剥ぎ取るエネルギー → 結合の強さ
電子親和力 ElectronAffinity_eV_ 電子を受け取るエネルギー → 電子構造
電気陰性度 Electronegativity 電子を引きつける力 → 結合の極性

段階1で半径だけに適用した weighted_bsite() を、4記述子すべてに適用すればよい。同じ処理を4回繰り返すだけである。

コード
keys = [
    "Ion_Radius",
    "IonizationPotential_eV_",
    "ElectronAffinity_eV_",
    "Electronegativity",
]

for key in keys:
    train_b[f"B_{key}"] = train_b.apply(
        lambda r, k=key: weighted_bsite(r, k), axis=1
    )

# 特徴量列だけを取り出す
feat_cols = [f"B_{k}" for k in keys]
feature_b4 = train_b[["composition", "delta_1"] + feat_cols].copy()
feature_b4
composition delta_1 B_Ion_Radius B_IonizationPotential_eV_ B_ElectronAffinity_eV_ B_Electronegativity
0 LaCoO3 132 0.61000 7.881000 0.66000 1.88000
4 LaCo0.998Al0.002O3 145 0.60985 7.877210 0.65956 1.87946
5 LaCo0.996Al0.004O3 145 0.60970 7.873419 0.65912 1.87892
6 LaCo0.99Ga0.01O3 140 0.61010 7.862183 0.65640 1.87930
7 LaCo0.98Ga0.02O3 140 0.61020 7.843366 0.65280 1.87860
8 LaCo0.97Ga0.03O3 140 0.61030 7.824549 0.64920 1.87790
9 LaCo0.95Ga0.05O3 130 0.61050 7.786915 0.64200 1.87650
10 LaCo0.99Rh0.01O3 119 0.61055 7.876779 0.66480 1.88400
11 LaCo0.98Rh0.02O3 105 0.61110 7.872558 0.66960 1.88800
12 LaCo0.97Rh0.03O3 90 0.61165 7.868337 0.67440 1.89200
13 LaCo0.95Rh0.05O3 61 0.61275 7.859895 0.68400 1.90000
14 LaCo0.99Ir0.01O3 114 0.61070 7.893190 0.66910 1.88320
15 LaCo0.98Ir0.02O3 99 0.61140 7.905380 0.67820 1.88640
16 LaCo0.97Ir0.03O3 63 0.61210 7.917570 0.68730 1.88960
17 LaCo0.95Ir0.05O3 54 0.61350 7.941950 0.70550 1.89600

小課題 3-3 列名に B_ を付ける理由

  1. なぜ Ion_Radius ではなく B_Ion_Radius という列名にしたのか
  2. もし B_ を付けずに Ion_Radius のまま段階3に進めたら、何が起きるか

解答例 3-3

  1. 段階3で A サイトの特徴量を追加する際に、A サイトと B サイトの同名列を区別する必要がある。列名にサイト情報を含めておくことで、混同を防ぐ
  2. A サイトの Ion_Radius と名前が衝突し、片方が上書きされるか、DataFrame のマージで意図しない結果になる。列名設計も特徴量設計の一部である
コード
# Stage 2 の CSV を保存
feature_b4.to_csv("data/feature_4desc_bsite.csv", index=False)
print("feature_4desc_bsite.csv を保存した")
print(f"列数: {len(feature_b4.columns)} ({len(feat_cols)} 特徴量 + composition + delta_1)")
feature_4desc_bsite.csv を保存した
列数: 6 (4 特徴量 + composition + delta_1)

lambda と変数キャプチャ

lambda r, k=key: ...k=key は、ループ変数 key の値をその場で固定するためのテクニックである。k=key を省略して lambda r: weighted_bsite(r, key) と書くと、ループ終了後の key(= Electronegativity)が全列に適用されてしまう。Python のクロージャの落とし穴として覚えておくとよい。

5 3.5 段階3:A/B サイト分離の完全版

ここまでは B サイト置換系(15組成)だけを扱ってきた。しかし、教師データには La\(_{1-x}\)Sr\(_x\)CoO\(_3\) 系の A サイト置換(3組成)も含まれている。論文では全18組成をまとめて学習しているので、ここでもフルデータを使った特徴量テーブルを作る。

A サイトの加重平均は、B サイトと同じ考え方である。

\[D_A = (1 - x_A) \cdot D(\text{La}^{3+}, \text{CN}=12) + x_A \cdot D(\text{Sr}^{2+}, \text{CN}=12)\]

\[D_B = (1 - x_B) \cdot D(\text{Co}^{3+}, \text{CN}=6) + x_B \cdot D(M^{3+}, \text{CN}=6)\]

A サイトは12配位(CN=12)、B サイトは6配位(CN=6)であることに注意する。配位数の違いは、ペロブスカイト構造における A サイトと B サイトの幾何学的な環境の違いを反映している(前章 2.6 節参照)。

コード
# 全18組成を使う
train_full = train.copy()

def weighted_asite(row, key):
    """A サイトの占有率加重平均を計算する"""
    la_val = lookup("La", 3, 12, key)
    if pd.isna(row["A_sub"]) or row["x_A"] == 0:
        return la_val
    dopant_val = lookup(row["A_sub"], 2, 12, key)
    return (1 - row["x_A"]) * la_val + row["x_A"] * dopant_val

# A サイト・B サイトそれぞれ4記述子を計算
for key in keys:
    train_full[f"A_{key}"] = train_full.apply(
        lambda r, k=key: weighted_asite(r, k), axis=1
    )
    train_full[f"B_{key}"] = train_full.apply(
        lambda r, k=key: weighted_bsite(r, k), axis=1
    )

# 特徴量テーブルを構成
a_cols = [f"A_{k}" for k in keys]
b_cols = [f"B_{k}" for k in keys]
feature_full = train_full[["composition", "delta_1"] + a_cols + b_cols].copy()
feature_full
composition delta_1 A_Ion_Radius A_IonizationPotential_eV_ A_ElectronAffinity_eV_ A_Electronegativity B_Ion_Radius B_IonizationPotential_eV_ B_ElectronAffinity_eV_ B_Electronegativity
0 LaCoO3 132 1.3600 5.577000 0.5000 1.1000 0.61000 7.881000 0.66000 1.88000
1 La0.99Sr0.01CoO3 128 1.3608 5.578178 0.4961 1.0985 0.61000 7.881000 0.66000 1.88000
2 La0.98Sr0.02CoO3 120 1.3616 5.579356 0.4922 1.0970 0.61000 7.881000 0.66000 1.88000
3 La0.97Sr0.03CoO3 115 1.3624 5.580534 0.4883 1.0955 0.61000 7.881000 0.66000 1.88000
4 LaCo0.998Al0.002O3 145 1.3600 5.577000 0.5000 1.1000 0.60985 7.877210 0.65956 1.87946
5 LaCo0.996Al0.004O3 145 1.3600 5.577000 0.5000 1.1000 0.60970 7.873419 0.65912 1.87892
6 LaCo0.99Ga0.01O3 140 1.3600 5.577000 0.5000 1.1000 0.61010 7.862183 0.65640 1.87930
7 LaCo0.98Ga0.02O3 140 1.3600 5.577000 0.5000 1.1000 0.61020 7.843366 0.65280 1.87860
8 LaCo0.97Ga0.03O3 140 1.3600 5.577000 0.5000 1.1000 0.61030 7.824549 0.64920 1.87790
9 LaCo0.95Ga0.05O3 130 1.3600 5.577000 0.5000 1.1000 0.61050 7.786915 0.64200 1.87650
10 LaCo0.99Rh0.01O3 119 1.3600 5.577000 0.5000 1.1000 0.61055 7.876779 0.66480 1.88400
11 LaCo0.98Rh0.02O3 105 1.3600 5.577000 0.5000 1.1000 0.61110 7.872558 0.66960 1.88800
12 LaCo0.97Rh0.03O3 90 1.3600 5.577000 0.5000 1.1000 0.61165 7.868337 0.67440 1.89200
13 LaCo0.95Rh0.05O3 61 1.3600 5.577000 0.5000 1.1000 0.61275 7.859895 0.68400 1.90000
14 LaCo0.99Ir0.01O3 114 1.3600 5.577000 0.5000 1.1000 0.61070 7.893190 0.66910 1.88320
15 LaCo0.98Ir0.02O3 99 1.3600 5.577000 0.5000 1.1000 0.61140 7.905380 0.67820 1.88640
16 LaCo0.97Ir0.03O3 63 1.3600 5.577000 0.5000 1.1000 0.61210 7.917570 0.68730 1.88960
17 LaCo0.95Ir0.05O3 54 1.3600 5.577000 0.5000 1.1000 0.61350 7.941950 0.70550 1.89600

小課題 3-4 完全版テーブルの構造

  1. feature_full の特徴量列数はいくつか。なぜその数になるか
  2. Sr 系の組成(例: La\(_{0.97}\)Sr\(_{0.03}\)CoO\(_3\))では、B サイト特徴量はどうなるか
  3. LaCoO₃(純物質)の A サイト特徴量と B サイト特徴量は、それぞれ何の値と一致するか

解答例 3-4

  1. 8列(A サイト4 + B サイト4)。記述子4種をそれぞれ A/B サイトに分けているため
  2. Sr 系は B サイト置換がないので、B サイト特徴量はすべて Co³⁺(CN=6) の値と一致する。変化するのは A サイト特徴量のみ
  3. LaCoO₃ は \(x_A = x_B = 0\) なので、A サイト = La³⁺(CN=12) の値、B サイト = Co³⁺(CN=6) の値とそのまま一致する
コード
# Stage 3 の CSV を保存
feature_full.to_csv("data/feature_site_split_full.csv", index=False)
print("feature_site_split_full.csv を保存した")
print(f"形状: {feature_full.shape[0]} 行 × {feature_full.shape[1]} 列")
print(f"特徴量: {a_cols + b_cols}")
feature_site_split_full.csv を保存した
形状: 18 行 × 10 列
特徴量: ['A_Ion_Radius', 'A_IonizationPotential_eV_', 'A_ElectronAffinity_eV_', 'A_Electronegativity', 'B_Ion_Radius', 'B_IonizationPotential_eV_', 'B_ElectronAffinity_eV_', 'B_Electronegativity']

Sr 置換の近似について

La\(_{1-x}\)Sr\(_x\)CoO\(_3\) では、Sr\(^{2+}\) が La\(^{3+}\) を置換するため、電荷バランスを保つために Co の平均価数が変化しうる(Co\(^{3+}\) → Co\(^{3+}\)/Co\(^{4+}\) 混合)。本書では、Co のイオンは一律 Co\(^{3+}\)(CN=6) として扱っている。これは論文のパイプラインと同じ近似であるが、物理的には簡略化であることを認識しておくべきである。この近似の妥当性は、モデルの予測精度を通じて間接的に検証される。

6 3.6 3段階のまとめと論文との対応

3つの特徴量テーブルを振り返る。

段階 ファイル 行数 特徴量数 論文との対応
1 feature_radius_bsite.csv 15 1 (\(r_B\)) 物理ベースラインの入力
2 feature_4desc_bsite.csv 15 4 (B サイト) B サイトのみの残差モデル入力
3 feature_site_split_full.csv 18 8 (A+B サイト) 論文本来のフル入力
コード
# 3つの表の形状を確認
for name, path in [
    ("Stage 1", "data/feature_radius_bsite.csv"),
    ("Stage 2", "data/feature_4desc_bsite.csv"),
    ("Stage 3", "data/feature_site_split_full.csv"),
]:
    df_check = pd.read_csv(path)
    n_feat = len(df_check.columns) - 2  # composition と delta_1 を除く
    print(f"{name}: {df_check.shape[0]} 行 × {n_feat} 特徴量")
Stage 1: 15 行 × 1 特徴量
Stage 2: 15 行 × 4 特徴量
Stage 3: 18 行 × 8 特徴量
flowchart LR
    A["組成式<br>LaCo₁₋ₓMₓO₃"] --> B["教師データ表<br>(組成, x, Δ₁)"]
    C["記述子辞書<br>(イオン, OS, CN,<br>物性値)"] --> D["lookup<br>(元素, OS, CN)"]
    B --> E["加重平均<br>(1-x)·D_host<br>+ x·D_dopant"]
    D --> E
    E --> F["特徴量テーブル<br>1行1組成<br>列=数値のみ"]
図 1: 組成式から特徴量テーブルへの変換パイプライン

論文では、この特徴量テーブルに対してさらに以下の前処理を行ってからモデルに投入している。

  1. 欠損補完: 列平均で補完
  2. 標準化: StandardScaler で平均0・分散1に変換

これらの前処理は、モデル構築の一部として次章で扱う。本章では 表を作ること に集中した。

7 3.7 酸素を含めない理由

ペロブスカイト ABO₃ には、A サイトと B サイトのほかに酸素 O\(^{2-}\) がある。しかし、論文の特徴量には酸素の記述子が含まれていない。

理由は、全18組成で酸素の化学状態(O\(^{2-}\), CN=6)が同一だからである。全行で同じ値をとる特徴量は、予測に寄与しない。したがって、酸素を除外しても情報は失われない。

小課題 3-5 全行同一の特徴量

もし特徴量テーブルに「全18行で同じ値をとる列」があった場合、回帰モデルにどのような影響があるか。StandardScaler との相性も考えよ。

解答例 3-5

全行同一の列は分散がゼロであり、目的変数との相関もゼロになるため、モデルの予測には寄与しない。scikit-learn の StandardScaler は定数列をゼロ列に変換するだけでエラーにはならないが、情報を持たない列を残すと解釈を濁す原因になる。情報量のない列は、事前に除外するのが正しい。

組成式を機械学習の表に翻訳する手順は、3段階に分解できる。(1) 記述子辞書からイオンの物性値を引く、(2) 組成比で加重平均する、(3) サイトごとに列を分けて1行1組成の表にする。この翻訳が正しくできなければ、どんな高度なモデルを使っても意味のある予測はできない。

8 章末演習

演習 3-1 LaCo\(_{0.95}\)Y\(_{0.05}\)O\(_3\) の B サイト有効半径 \(r_B\) を、手計算で求めよ。Co\(^{3+}\)(CN=6) と Y\(^{3+}\)(CN=6) のイオン半径は descriptor_selected.csv から読み取ること。

演習 3-2 段階1(半径のみ)と段階2(4記述子)の表を見比べ、「半径だけの表で失われる情報は何か」を150字以内で説明せよ。

演習 3-3 以下の2つの表の違いを、「行数」「列数」「情報の範囲」の3点で整理せよ。

  • feature_4desc_bsite.csv(段階2)
  • feature_site_split_full.csv(段階3)

演習 3-4 Sr 置換系(La\(_{1-x}\)Sr\(_x\)CoO\(_3\))において、「A サイトだけ加重平均すれば十分か」が問題になる理由を、150字以内で説明せよ。ヒント: 電荷バランスと Co の価数を考えよ。