学习笔记
从0开始学习机器学习·实践
第一节 建立材料数据库01
写在前面的话
在这个系列的学习笔记中,可以学习从建立材料数据库到解析结构数据,再进行深度学习等完整的机器学习实践。后续,也将陆续撰写其他如计算材料学(VASP,Gromacs,Gaussian等)还有机器学习理论等从0开始系列笔记。
数据库构建
基于统计概率的机器学习,模型离不开大量的数据,在材料学中,这些数据可以是材料结构或是材料的性质。结构决定性质,因此无论是从结构预测出性质,还是从性质反推出结构,都离不开大量的数据。为此,这方面,Materials Project等大量材料数据库被建立。 这里,我们将学习到如何从这些数据库中拉取我们想要获取的材料数据,本文以钙钛矿晶体结构为例,拉取MP数据库中的钙钛矿以及类钙钛矿的材料数据。
在下面的例子中,不仅能够学习到如何构建数据库,还能够学习或巩固python的用法或技巧。
在python中 # 以及”’XXX”’代表了注释,python脚本在编译运行的过程中会自动跳过这些内容,这些内容都是我在学习过程中,帮助我理解和整理思路时的笔记,希望对你也有所帮助。
materials project
导入包以及常量
from mp_api.client import MPRester
import csv
from tqdm import tqdm
#https://next-gen.materialsproject.org/api 注册获得API_KEY
API_KEY = "APIKEY"
OUTPUT_FILE = "perovskite_dataset.csv"
通过API调用MP数据库,拉取Description中含有perovskite 字段的结构。
mpr.materials.robocrys.search(keywords=[“perovskite”]
这是MPRester包中的固定写法,使用时,仅需要更换关键词即可搜索其他的材料结构。
def get_robo_perovskites(mpr):
docs = mpr.materials.robocrys.search(keywords=["perovskite"])
'''
等价写法:用set可以避免重复统计
rob_ids()
for doc in docs:
rob_ids.add(doc.material_id)
'''
return set(doc.material_id for doc in docs)
拉取Tags标签或remarks标记中含有perovskite 字段的结构。
#材料ID,标签,备注信息
def get_tag_perovskites(mpr):
'''
如返回信息:
MPDataDoc<ProvenanceDoc>(
material_id=MPID(mp-1244953),
remarks=['Amorphous'], ->表明非晶体
tags=['Amorphous'],
fields_not_requested=['builder_meta', 'nsites', 'elements', 'nelements',
'composition', 'composition_reduced', 'formula_pretty', 'formula_anonymous',
'chemsys', 'volume', 'density', 'density_atomic', 'symmetry', 'deprecated',
'deprecation_reasons', 'last_updated', 'origins', 'warnings', 'structure',
'property_name', 'created_at', 'references', 'authors', 'theoretical',
'database_IDs', 'history']
)]
'''
docs = mpr.materials.provenance.search(
fields=["material_id", "tags", "remarks"]
)
ids = []
for doc in docs:
'''
取"tags"字段,如果没有,则返回[]
等价于
if "tags" in doc:
tags=doc["tags"]
else:
tags=[]
or []防止key不存在,直接返回[]
'''
tags = doc.get("tags", []) or []
remarks = doc.get("remarks", []) or []
'''
tags + remarks:拼接列表
等价为:
for x in (tags+remarks):
#str(x).lower():将xstring化,小写化
if "perovskite" in str(x).lower():
ids.append(doc.get("material_id"))
return False
'''
if any("perovskite" in str(x).lower() for x in (tags + remarks)):
ids.append(doc.get("material_id"))
return set(ids)
获取结构性质
def fetch_summary(mpr, material_ids):
results = []
batch_size = 1000
ids_list = list(material_ids)
'''
range(0,len(ids_list),batch_size):从0开始,ids_list的长度结束,步长为batch_size
tqdm():进度条工具表
'''
for i in tqdm(range(0, len(ids_list), batch_size)):
#batch_ids:每一次取1000个数据
batch_ids = ids_list[i:i + batch_size]
docs = mpr.materials.summary.search(
material_ids=batch_ids,
fields=[
"material_id",
"formula_pretty",#结构表达式
"energy_above_hull",#凸包能
"formation_energy_per_atom",#形成能
"band_gap",
"density",
"volume",
"nsites"#晶胞内的原子数
]
)
results.extend(docs)
return results
存入csv文件
import pandas as pd
rows = []
def save_to_csv(data, filename):
print("Saving to CSV...")
df=pd.DataFrame([
{
"material_id": d.material_id,
"formula": d.formula_pretty,
"energy_above_hull": d.energy_above_hull,
"formation_energy": d.formation_energy_per_atom,
"band_gap": d.band_gap,
"density": d.density,
"volume": d.volume,
"nsites": d.nsites
}
for d in data
])
df.to_csv(filename,index=True,encoding="utf-8")
print("CSV saved!")
主函数调用所有方法
def main():
with MPRester(API_KEY) as mpr:
robo_ids=get_robo_perovskite(mpr)
tags_ids=get_tag_perovskite(mpr)
#取并集
all_ids=robo_ids|tags_ids
print(f"Total perovskites:{len(all_ids)}")
data=fetch_summary(mpr,all_ids)
save_to_csv(data,OUTPUT_FILENAME)
点击run,运行文件后,可以看到控制台中开始拉取数据库中的数据,运行结束后,文件夹内会存入一个名为“perovskite_dataset.csv”的文件。到此,整个拉取的过程就结束了。打开csv文件,可以看到MP数据库中所有有关钙钛矿的结构以及相应的性质数据。
