特征工程(上):元素属性特征与描述符构建

各位同学,咱们今天聊聊特征工程。说实话,在材料性能预测这个领域,我踩过最大的坑就是——模型选得再花哨,特征没做好,照样白搭。特征工程做得好,模型就成功了一半。这话一点不夸张。

一、为什么特征工程这么重要?

你想想看,我们做材料预测,本质上是在干什么?是在找「成分-结构-性能」之间的映射关系。但原始数据(比如元素符号、晶格参数)计算机看不懂啊。我们需要把这些信息翻译成计算机能理解的数字语言——这就是特征工程。

我个人习惯,拿到一个材料数据集,第一件事不是跑模型,而是先花 70% 的时间做特征工程。为什么?因为好的特征能让简单的线性模型跑出深度学习的精度。我在项目中遇到过,同样的数据,特征做得好,R² 从 0.6 直接飙到 0.92。

核心观点:特征工程不是锦上添花,而是雪中送炭。没有好的特征,再牛的模型也是空中楼阁。

二、元素属性特征:最基础也最有效

元素属性特征,说白了就是每个元素自带的天生属性。比如原子半径、电负性、价电子数这些。这些特征为什么好用?因为它们直接反映了元素的化学行为。

2.1 原子半径

原子半径决定了原子的大小。在合金、化合物中,原子半径直接影响晶格常数、键长、甚至相稳定性。我记得有一次做高熵合金的硬度预测,加入原子半径特征后,模型精度提升了 15%。

常用的原子半径数据源:

  • Shannon 离子半径(最常用,适用于离子晶体)
  • Pauling 金属半径(适用于金属和合金)
  • Covalent 半径(适用于共价键体系)
小技巧:我建议同时使用多种半径,让模型自己学习哪种更有效。有时候混合使用效果出奇的好。

2.2 电负性

电负性反映原子吸引电子的能力。这个特征在预测带隙、形成能、甚至催化活性时特别重要。为什么?因为电负性差异决定了化学键的极性,进而影响电子结构。

常用的电负性标度:

  • Pauling 电负性(最经典)
  • Mulliken 电负性(基于电离能和电子亲和能)
  • Allen 电负性(基于光谱数据)

2.3 价电子数

价电子数决定了元素的化学价态和成键能力。在预测形成能、相稳定性时,这个特征几乎是必选的。嗯,这里要注意:不同元素的价电子数可能相同(比如 C 和 Si 都是 4 个),但化学行为完全不同,所以不能只用这一个特征。

元素 原子半径 (pm) 电负性 (Pauling) 价电子数
Fe 126 1.83 8
Co 125 1.88 9
Ni 124 1.91 10
Cu 128 1.90 11

三、组合特征:1+1 > 2 的魔法

单个元素属性虽然有用,但材料性能往往取决于元素之间的相互作用。这时候就需要组合特征了。说白了,就是把多个元素的属性通过数学运算组合起来。

3.1 平均特征

最简单的组合方式。对于 AxBy 这样的化合物,平均原子半径就是 (x * r_A + y * r_B) / (x + y)。

我在项目中遇到过,用平均电负性预测带隙,效果出奇的好。为什么?因为平均电负性反映了整个化合物的电子亲和能力。

3.2 差值特征

差值特征反映元素之间的差异。比如电负性差值越大,化学键极性越强,带隙通常越大。这个特征在预测离子晶体的性质时特别有用。

注意:差值特征对极端值敏感。我曾经用差值特征做回归,结果一个异常点把整个模型带偏了。建议先做异常值检测。

3.3 乘积特征

乘积特征可以捕捉元素之间的协同效应。比如原子半径和电负性的乘积,可能反映某种复杂的相互作用。说实话,乘积特征有时候效果出奇的好,但有时候也会引入噪声。我的经验是:先试,不行就扔掉。

四、描述符构建:从特征到知识

描述符是特征工程的高级形式。它不仅仅是简单的数学组合,而是基于物理化学知识的特征设计。一个好的描述符,应该能抓住材料性能的本质。

4.1 经典描述符示例

以钙钛矿 ABO3 为例,常用的描述符包括:

  • 容忍因子 t:t = (r_A + r_O) / √2(r_B + r_O),用于判断钙钛矿结构的稳定性
  • 八面体因子 μ:μ = r_B / r_O,反映 B-O 键的强度
  • 电负性差 Δχ:Δχ = χ_A - χ_B,反映 A-B 位之间的电荷转移

4.2 描述符构建原则

我个人总结了几条经验:

  1. 物理可解释性:描述符要有明确的物理意义,不能是黑箱
  2. 维度适中:太多描述符会导致过拟合,太少则信息不足
  3. 正交性:描述符之间相关性要低,避免多重共线性

五、实战:构建一个简单的特征集

咱们以二元合金 AxB1-x 为例,看看怎么构建特征集。

import numpy as np
import pandas as pd

# 元素属性字典
elem_props = {
    'Fe': {'radius': 126, 'en': 1.83, 'valence': 8},
    'Co': {'radius': 125, 'en': 1.88, 'valence': 9},
    'Ni': {'radius': 124, 'en': 1.91, 'valence': 10},
    'Cu': {'radius': 128, 'en': 1.90, 'valence': 11}
}

def build_features(A, B, x):
    """构建二元合金特征"""
    props_A = elem_props[A]
    props_B = elem_props[B]
    
    features = {
        # 平均特征
        'avg_radius': x * props_A['radius'] + (1-x) * props_B['radius'],
        'avg_en': x * props_A['en'] + (1-x) * props_B['en'],
        'avg_valence': x * props_A['valence'] + (1-x) * props_B['valence'],
        
        # 差值特征
        'diff_radius': props_A['radius'] - props_B['radius'],
        'diff_en': props_A['en'] - props_B['en'],
        'diff_valence': props_A['valence'] - props_B['valence'],
        
        # 乘积特征
        'prod_radius_en': props_A['radius'] * props_B['en'],
        'prod_valence_radius': props_A['valence'] * props_B['radius']
    }
    
    return features

# 示例:构建 Fe0.5Co0.5 的特征
feats = build_features('Fe', 'Co', 0.5)
print(pd.Series(feats))
经验之谈:我建议先构建一个基础特征集(平均+差值),然后逐步添加乘积特征。不要一次性加太多,否则模型容易过拟合。

六、知识体系总览

下面这张图总结了本章的核心内容,方便你快速回顾:

特征工程(上)知识体系 特征工程 元素属性特征 原子半径 电负性 价电子数 组合特征 平均特征 差值特征 乘积特征 描述符构建 容忍因子 八面体因子 电负性差 核心原则:物理可解释 + 维度适中 + 正交性 好的特征 = 好的模型

七、避坑指南

最后,分享几个我踩过的坑:

  • 不要盲目堆特征:我曾经一口气构建了 200 多个特征,结果模型训练时间长了 10 倍,精度反而下降了。特征不是越多越好。
  • 注意特征尺度:原子半径和电负性的数值范围不同,直接使用会导致模型偏向数值大的特征。记得做标准化。
  • 小心数据泄露:构建组合特征时,不要用到目标变量的信息。比如用测试集的平均值去构建训练集的特征,这是典型的错误。
我曾经犯过的错:有一次做带隙预测,我把形成能也作为特征加进去了。结果模型精度超高,但实际应用时发现——形成能本身就需要计算,根本没法用于预测。这就是典型的数据泄露。

好了,特征工程的上半部分就讲到这里。记住,好的特征工程需要你对材料科学有深入理解,也需要你不断尝试和迭代。没有万能的特征集,只有最适合你问题的特征集。


专注资料整理