第1章:材料数据获取与清洗——打好智能发现的第一仗

各位工程师朋友,大家好。我是老张,在材料信息学这个坑里摸爬滚打了七八年。今天咱们聊的这章,是整个智能发现新材料流程里最枯燥、但也是最要命的一环——数据获取与清洗。

你想想看,再牛的AI模型,喂进去的是垃圾,吐出来的只能是更垃圾。我在项目里见过太多团队,模型调得飞起,结果数据有问题,最后白忙活三个月。所以,这一章咱们把地基打牢。

核心观点:材料数据工作占整个项目时间的60%-80%,但决定了90%的成败。

材料数据获取与清洗知识体系 数据获取与清洗 公开数据库 实验数据与文献挖掘 清洗与标准化 缺失值处理策略 Materials Project OQMD · AFLOW · NOMAD PDF解析 · 表格提取 NLP命名实体识别 单位统一 · 格式规范 异常值检测 · 去重 删除 · 均值填充 KNN · 模型预测 数据质量 = 模型效果的上限

1.1 公开数据库——你的免费材料宝库

做材料数据挖掘,第一个要搞定的就是数据源。我个人最常用的两个公开数据库是 Materials Project 和 OQMD。说白了,它们就是材料界的「维基百科」,但比维基百科靠谱得多。

Materials Project(https://materialsproject.org)

  • 由MIT和LBNL联合开发,目前收录了超过15万种无机材料
  • 提供晶体结构、能带结构、态密度、弹性常数等计算数据
  • 支持Python API(pymatgen库)直接调用,非常方便

OQMD(Open Quantum Materials Database)

  • 西北大学出品,收录了超过100万种材料
  • 侧重于热力学稳定性数据,形成能计算很全
  • 同样提供RESTful API,可以批量查询

我的经验:刚开始用Materials Project时,我习惯直接网页下载CSV。后来发现用API批量拉数据才是正道。一次拉几千条,写个脚本自动处理,省时省力。

来看一段用pymatgen拉数据的示例代码:

from pymatgen.ext.matproj import MPRester

# 注意:需要去官网申请API Key
API_KEY = "你的API_KEY"

with MPRester(API_KEY) as mpr:
    # 查询所有含Li和Fe的氧化物
    criteria = {"elements": {"$all": ["Li", "Fe"], "$in": ["O"]}}
    properties = ["material_id", "formula_pretty", "formation_energy_per_atom", "band_gap"]
    
    data = mpr.query(criteria, properties)
    print(f"共找到 {len(data)} 条记录")
    for d in data[:5]:
        print(d["formula_pretty"], d["formation_energy_per_atom"], d["band_gap"])

注意:API有调用频率限制,免费用户每分钟最多50次请求。批量拉数据时记得加time.sleep(),不然会被封IP。我曾经一次拉5万条数据没加延时,结果被禁了三天...

1.2 实验数据与文献挖掘——从纸堆里淘金

公开数据库虽好,但很多新材料数据还在文献里躺着。怎么把这些数据挖出来?我总结了三板斧。

第一板斧:PDF解析

用Python的pdfplumber或PyMuPDF库,把论文里的表格提取出来。但说实话,准确率也就70%-80%。很多论文的表格是图片格式,那就得用OCR了。

import pdfplumber
import pandas as pd

with pdfplumber.open("paper.pdf") as pdf:
    for page in pdf.pages:
        tables = page.extract_tables()
        for i, table in enumerate(tables):
            df = pd.DataFrame(table[1:], columns=table[0])
            print(f"第{i+1}个表格提取完成,共{len(df)}行")

第二板斧:NLP命名实体识别

用ChemDataExtractor或自训练的BERT模型,从论文正文中自动识别材料名称、合成条件、性能指标。这个技术门槛稍高,但效果拔群。

第三板斧:人工校验

嗯,这里要实话实说。自动提取的数据,我建议至少抽20%做人工核对。我在一个项目中用NLP提取了2000条催化性能数据,结果发现30%的单位都标错了——有的用mmol/g,有的用μmol/g,差了一千倍。

避坑指南:文献数据挖掘最大的坑是「单位不统一」。我建议在数据入库前,先建立一个单位映射表,把所有数据强制转换成标准单位(比如eV/atom、kJ/mol等)。

1.3 数据清洗与标准化流程

数据拿到手了,接下来就是最磨人的清洗环节。我一般按以下流程走:

  1. 格式统一——所有化学式转成标准形式(如"Fe2O3"而不是"Fe2O3"或"Fe2 O3")
  2. 单位转换——建立单位字典,自动转换
  3. 异常值检测——用IQR或Z-score方法,标记离群点
  4. 去重——同一材料、同一性能,保留最新或最可靠的数据
  5. 一致性检查——比如带隙不能为负数,形成能异常高的要标记

来看一个清洗示例:

import pandas as pd
import numpy as np

def clean_material_data(df):
    # 1. 化学式标准化
    df["formula"] = df["formula"].str.replace(" ", "").str.replace("₂", "2")
    
    # 2. 单位转换(假设原始数据单位是kcal/mol,转成eV/atom)
    df["formation_energy"] = df["formation_energy"] * 0.04336
    
    # 3. 异常值检测(Z-score方法)
    z_scores = np.abs((df["formation_energy"] - df["formation_energy"].mean()) / df["formation_energy"].std())
    df = df[z_scores < 3]
    
    # 4. 去重
    df = df.drop_duplicates(subset=["formula", "property"], keep="first")
    
    return df

小技巧:清洗后的数据,我习惯生成一份「清洗日志」,记录删除了多少条、转换了多少单位、标记了多少异常。这样出了问题可以追溯,也方便写论文时交代数据来源。

1.4 数据缺失值处理策略

真实数据永远有缺失。你想想看,1000条材料数据里,可能只有600条有带隙值,800条有形成能。怎么办?

我常用的策略有四种:

策略 适用场景 优点 缺点
直接删除 缺失率<5%,且随机缺失 简单快速 可能丢失信息
均值/中位数填充 数值型特征,缺失率10%-30% 保持数据分布 降低方差
KNN填充 有相似样本可参考 利用相似性,效果较好 计算量大
模型预测填充 缺失率较高,且特征间相关性强 精度最高 可能过拟合

我个人最常用的是KNN填充。为什么呢?因为材料数据往往有内在规律——比如同族元素、同晶型的材料,性能往往相近。用KNN正好能捕捉这种相似性。

from sklearn.impute import KNNImputer
import numpy as np

# 假设X是特征矩阵,有缺失值
imputer = KNNImputer(n_neighbors=5, weights="distance")
X_imputed = imputer.fit_transform(X)

print(f"填充前缺失值数量: {np.sum(np.isnan(X))}")
print(f"填充后缺失值数量: {np.sum(np.isnan(X_imputed))}")

重要提醒:千万不要在训练集和测试集上一起做填充!一定要先分训练集和测试集,然后在训练集上fit imputer,再transform测试集。否则会造成数据泄露,模型效果虚高。这个坑我踩过,后来审稿人直接拒了...

好了,关于数据获取与清洗,今天就聊到这儿。记住一句话:数据清洗不是一次性工作,而是贯穿整个项目的持续过程。每次加入新数据,都要重新跑一遍清洗流程。

下一章咱们聊聊特征工程——怎么从原始数据中提炼出真正有用的特征。到时候见。


公众号:蓝海资料掘金营,微信deep3321