3  特徴量辞書を読む

同じコバルトでも、価数と配位数が違えば別のイオンである。
機械学習の入力は「元素名」ではなく「環境つきのイオン情報」である。

本章では、論文で使われた 記述子辞書(descriptor dictionary)を Python で読み込み、論文が実際に使った8種のイオンを抽出する。機械学習を行う前に、よい入力表を作ることが研究の半分であるということを体感する章である。

1 2.1 記述子辞書とは何か

前章で確認したとおり、この論文の入力特徴量はイオン半径・イオン化ポテンシャル・電子親和力・電気陰性度の4種である。これらの数値は、各イオンの酸化数(OS)と配位数(CN)ごとにまとめられた参照テーブルから取得される。このテーブルを 記述子辞書 と呼ぶ。

重要な点は、この Excel ファイルは 学習データ(教師データ)ではない ということである。学習データは「組成 → \(\Delta_1\)」の対応表であり、次章で構築する。記述子辞書は、その構築に使う部品表にすぎない。

記述子辞書の1行は「材料試料」ではなく「特定の酸化数・配位数をもつイオン1種」を表している。

2 2.2 Excel 全体を眺める

まず、記述子辞書を読み込んで全体像を確認する。

コード
import pandas as pd

df = pd.read_excel("data/R6_0520_ShData_EN.xlsx", sheet_name="Sheet1")
print(f"形状: {df.shape[0]} 行 × {df.shape[1]} 列")
print(f"列名: {df.columns.tolist()}")
形状: 474 行 × 8 列
列名: ['atomic_N', 'r_a', 'OS', 'CN', 'IonizationPotential_eV_', 'ElectronAffinity_eV_', 'Ion_Radius', 'Electronegativity']
コード
df.head(10)
atomic_N r_a OS CN IonizationPotential_eV_ ElectronAffinity_eV_ Ion_Radius Electronegativity
0 3 167 1 4 5.3917 0.62 0.59 0.98
1 3 167 1 6 5.3917 0.62 0.76 0.98
2 3 167 1 8 5.3917 0.62 0.92 0.98
3 4 112 2 3 9.3226 0.00 0.16 1.57
4 4 112 2 4 9.3226 0.00 0.27 1.57
5 4 112 2 6 9.3226 0.00 0.45 1.57
6 5 87 3 3 8.2980 0.28 0.01 2.04
7 5 87 3 4 8.2980 0.28 0.11 2.04
8 5 87 3 6 8.2980 0.28 0.27 2.04
9 6 67 4 4 11.2603 1.26 0.15 2.55

474行×8列の表であり、各列の意味は以下のとおりである。

列名 意味 役割
atomic_N 原子番号 イオンの識別子(特徴量ではない)
OS 酸化数(Oxidation State) イオンの文脈を決める
CN 配位数(Coordination Number) イオンの文脈を決める
Ion_Radius イオン半径 記述子(特徴量の素材)
IonizationPotential_eV_ イオン化ポテンシャル [eV] 記述子
ElectronAffinity_eV_ 電子親和力 [eV] 記述子
Electronegativity 電気陰性度 記述子
r_a 原子半径 補助情報(本書ではあまり使わない)

小課題 2-1 なぜ Co が1行ではないのか

この表で原子番号 27(Co)の行は何行あるか、確認せよ。なぜ1行ではないのか、理由を説明せよ。

コード
co_rows = df[df["atomic_N"] == 27]
print(f"Co の行数: {len(co_rows)}")
co_rows[["atomic_N", "OS", "CN", "Ion_Radius"]]
Co の行数: 7
atomic_N OS CN Ion_Radius
112 27 4 4 0.400
113 27 4 6 0.530
114 27 2 4 0.580
115 27 3 6 0.610
116 27 2 5 0.670
117 27 2 6 0.745
118 27 2 8 0.900

解答例 2-1

Co は酸化数が 2, 3, 4 の3種、配位数も 4, 5, 6, 8 など複数あり、それぞれの組み合わせでイオン半径が異なる。たとえば Co\(^{2+}\)(CN=6)と Co\(^{3+}\)(CN=6)では半径が違う。同じ元素でも、化学的な環境が変われば物性値が変わるためである。

3 2.3 小さな見本表で考える

474行全体を眺めていても見通しが悪い。まず、この論文に関係する8元素だけを抜き出した見本表を作る。

対象は、A サイト(La, Sr)と B サイト(Co, Al, Ga, Rh, Ir, Y)の合計8元素である。

コード
# 対象元素の原子番号
z_to_symbol = {
    13: "Al",
    27: "Co",
    31: "Ga",
    38: "Sr",
    39: "Y",
    45: "Rh",
    57: "La",
    77: "Ir",
}

df["element"] = df["atomic_N"].map(z_to_symbol)

# 対象元素だけを抽出
sample = df[df["atomic_N"].isin(z_to_symbol)].copy()
sample = sample.sort_values(["element", "OS", "CN"])
print(f"見本表の行数: {len(sample)}")
見本表の行数: 34
コード
sample[["element", "atomic_N", "OS", "CN", "Ion_Radius"]].head(20)
element atomic_N OS CN Ion_Radius
35 Al 13 3 4 0.390
36 Al 13 3 5 0.480
37 Al 13 3 6 0.535
114 Co 27 2 4 0.580
116 Co 27 2 5 0.670
117 Co 27 2 6 0.745
118 Co 27 2 8 0.900
115 Co 27 3 6 0.610
112 Co 27 4 4 0.400
113 Co 27 4 6 0.530
135 Ga 31 3 4 0.470
136 Ga 31 3 5 0.550
137 Ga 31 3 6 0.620
375 Ir 77 3 6 0.680
374 Ir 77 4 6 0.625
373 Ir 77 5 6 0.570
261 La 57 3 6 1.032
262 La 57 3 7 1.100
263 La 57 3 8 1.160
264 La 57 3 9 1.216

この見本表を見ると、たとえば以下のことが分かる。

  • La は OS=3 で CN=6, 7, 8, 9, 10, 12 を持つ
  • Sr は OS=2 で CN=6, 7, 8, 9, 12 を持つ
  • Co は OS=2, 3, 4 を持ち、CN も複数ある
  • Y は OS=3 で CN=6, 7, 8, 9 を持つ

つまり、元素名だけでは行を特定できない。OS と CN の組み合わせまで指定して初めて、1つのイオンが定まる。

小課題 2-2 どの行を選ぶべきか

LaCoO₃ のペロブスカイト構造では、A サイトは12配位、B サイトは6配位である。この情報をもとに、以下の3つのイオンについて、見本表のどの行を選ぶべきか答えよ。

  1. A サイトの La
  2. B サイトの Co
  3. B サイト候補としての Y

解答例 2-2

  1. La³⁺, CN=12(A サイトは12配位)
  2. Co³⁺, CN=6(B サイトは6配位、LaCoO₃ では Co は3価)
  3. Y³⁺, CN=6(B サイト候補として OS=3, CN=6 で絞る)

4 2.4 原子番号を元素記号に変換する

atomic_N はイオンの識別子として便利だが、人間が読むには元素記号の方が直感的である。先ほど作った辞書 z_to_symbol を使って変換する。

コード
# map() で変換(対象外の元素は NaN になる)
print(df["element"].value_counts())
element
Co    7
La    6
Sr    5
Y     4
Ga    3
Al    3
Rh    3
Ir    3
Name: count, dtype: int64

よくある誤り

map() を使うと、辞書にない原子番号の行は NaN になる。これはバグではなく、対象外の元素が NaN で表示されているだけである。慌てて全元素の辞書を作る必要はない。

atomic_N は元素の識別子にすぎず、論文が使う特徴量そのものではない。特徴量は、酸化数(OS)と配位数(CN)で行を特定したうえで読み取るイオンの物性値(半径、イオン化ポテンシャル等)である。ただし、この辞書で OS/CN 依存性を強く持つのは主にイオン半径であり、イオン化ポテンシャル・電子親和力・電気陰性度は原子番号ごとに一定の値が格納されている。つまり、後者の 3 記述子は実質的に「元素記述子」として扱われている。

5 2.5 OS・CN で必要なイオンを抽出する

いよいよ、論文が実際に使った8種のイオンを抽出する。条件は以下のとおりである。

イオン OS CN サイト
La³⁺ 3 12 A
Sr²⁺ 2 12 A
Co³⁺ 3 6 B(ホスト)
Al³⁺ 3 6 B(ドーパント)
Ga³⁺ 3 6 B(ドーパント)
Rh³⁺ 3 6 B(ドーパント)
Ir³⁺ 3 6 B(ドーパント)
Y³⁺ 3 6 B(候補)

この抽出には、条件を直接書くよりも、正解の条件を小さな表にまとめて merge する方法が読みやすい。

コード
target_ions = pd.DataFrame([
    {"element": "La", "atomic_N": 57, "OS": 3, "CN": 12},
    {"element": "Sr", "atomic_N": 38, "OS": 2, "CN": 12},
    {"element": "Co", "atomic_N": 27, "OS": 3, "CN": 6},
    {"element": "Al", "atomic_N": 13, "OS": 3, "CN": 6},
    {"element": "Ga", "atomic_N": 31, "OS": 3, "CN": 6},
    {"element": "Rh", "atomic_N": 45, "OS": 3, "CN": 6},
    {"element": "Ir", "atomic_N": 77, "OS": 3, "CN": 6},
    {"element": "Y",  "atomic_N": 39, "OS": 3, "CN": 6},
])

selected = df.merge(
    target_ions[["atomic_N", "OS", "CN"]],
    on=["atomic_N", "OS", "CN"],
    how="inner"
)

cols = ["element", "atomic_N", "OS", "CN",
        "Ion_Radius", "IonizationPotential_eV_",
        "ElectronAffinity_eV_", "Electronegativity"]
selected = selected[cols].sort_values("element")

print(f"抽出結果: {len(selected)} 行")
selected
抽出結果: 8 行
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
7 Ir 77 3 6 0.680 9.1000 1.57 2.20
6 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
3 Sr 38 2 12 1.440 5.6948 0.11 0.95
4 Y 39 3 6 0.900 6.2170 0.31 1.22

8行が得られれば正解である。代表的な値を確認しておこう。

  • La³⁺(CN=12): Ion_Radius = 1.36 Å
  • Co³⁺(CN=6): Ion_Radius ≈ 0.55〜0.61 Å
  • Y³⁺(CN=6): Ion_Radius = 0.90 Å

Y³⁺ の半径は Co³⁺ よりかなり大きい。B サイトに Y を入れると格子に歪みが生じることが、半径の比較からも予想できる。この半径差は、前章で見た異方的格子応答の有力な起点の一つでありうる。

コード
# CSV として保存(次章の出発点になる)
selected.to_csv("data/descriptor_selected.csv", index=False)
print("descriptor_selected.csv を保存した")
descriptor_selected.csv を保存した

機械学習の入力は、元素名ではなく「環境つきのイオン情報」である。同じコバルトでも、Co\(^{2+}\)(CN=4)と Co\(^{3+}\)(CN=6)では半径が大きく異なる。ただし、この辞書ではイオン化ポテンシャルや電気陰性度は OS/CN によらず原子番号で決まる値が使われている点に注意せよ。環境依存性を最も強く反映するのはイオン半径であり、だからこそ半径が特徴量の中核になる。

6 2.6 ペロブスカイト構造と配位数

最後に、なぜ A サイトが CN=12、B サイトが CN=6 なのかを整理する。

ペロブスカイト構造 ABO₃ では、

  • A サイト(La, Sr): 12個の酸素に囲まれた大きなサイト → CN=12
  • B サイト(Co, ドーパント): 6個の酸素で八面体を形成する小さなサイト → CN=6

つまり、理想ペロブスカイトでは A サイトの名目配位数は 12、B サイトは 6 と構造的に決まる。サイトの幾何が配位環境を規定するのである。ただし、実際にどの元素がどのサイトに安定に入るかは、イオンサイズ・価数・共有結合性・局所緩和などの要因が左右する。

小課題 2-3 半径と配位数の関係

抽出した8イオンの Ion_Radius を見比べよ。A サイト(CN=12)のイオンと B サイト(CN=6)のイオンで、半径の大きさにどのような傾向があるか。

解答例 2-3

A サイトのイオン(La³⁺: 1.36 Å, Sr²⁺: 1.44 Å)は B サイトのイオン(Co³⁺: ~0.55-0.61 Å, Y³⁺: 0.90 Å)よりも明らかに大きい。配位数が大きいサイトには大きなイオンが入る傾向がある。ただし Y³⁺ は B サイト候補の中で最も大きく、Co³⁺ との半径差が格子歪みの原因になりうる。

よくある誤り まとめ

  1. and& の混同: pandas の条件式では & を使い、各条件を括弧で囲む。(df["OS"] == 3) & (df["CN"] == 6) が正しい
  2. 括弧の不足: df["OS"] == 3 & df["CN"] == 6 と書くと、&3df["CN"] に先に適用され、意図通りに動かない
  3. map() の NaN: 辞書にないキーは NaN になるが、対象外の元素なので正常動作である
  4. r_a 列の深追い: この列は原子半径であり、論文の特徴量としては直接使われない。今は保留でよい

7 章末演習

演習 2-1 descriptor_selected.csv の8行について、各イオンが A サイトか B サイトか、また論文中での役割(ホスト/ドーパント/候補)を表にまとめよ。

演習 2-2 「同じ元素でも価数や配位数でイオン半径が変わる」理由を、150字以内で説明せよ。

演習 2-3 この記述子辞書に含まれる全元素の数(atomic_N のユニーク数)と、OS の範囲、CN の範囲を求めよ。

演習 2-4 次章では、記述子辞書と教師データ(組成 → \(\Delta_1\) の対応表)を組み合わせて特徴量テーブルを作る。「記述子辞書」と「教師データ」は何が違うのか、1文で説明せよ。