机器学习在材料方向的应用(lightgbm+贝叶斯优化调参)

from pymatgen import Composition, Element
import pandas as pd
import urllib.request
import numpy as np
from sklearn.model_selection import train_test_split

import lightgbm as lgb
from sklearn import datasets
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
from sklearn import datasets
from bayes_opt import BayesianOptimization

#文件获取地址
url = 'https://raw.githubusercontent.com/onecoinbuybus/Database_chemoinformatics/master/bondgap_database.csv'
urllib.request.urlretrieve(url, 'bondgap_database.csv')

#获取文件
trainFile = pd.read_csv('bondgap_database.csv', sep=',', header=None) 
trainFile.columns = ['formula', 'bondgap']
#数据集是二元系的无机分子式以及能隙数据一共4096个。
print(trainFile.shape) #(4096, 2)
print(trainFile.head())

#之后我们把它丢给pymatgen,这里的处理有点类似于将有机分子转化成mol文件的过程。
form=trainFile['formula']
#将化学式拆分
materials=list(map(lambda x: Composition(x), form))
print(materials)

#下面是计算描述子的函数
#这里使用了这么几个描述子,
# atomic_number:第一个和第二个原子的原子序数,
# electronegativity是电负性,element_group是周期。
# 最后还有fraction,这里我用sort让一个分子式里的原子数量按照从大到小配比然后求一个比例值。
# 就这么几个简单的东西作为X来预测y能隙。
def mat_descriptor_calculation(material):
    #将化学式拆分
    mat=Composition(material)
    #lambda x: mat.get_atomic_fraction(x), mat  mat为lambda x中x的参数
    #mat.get_atomic_fraction(x) x为mat中的元素,获取该元素在化学式中的成分比
    fraction_list=list(map(lambda x: mat.get_atomic_fraction(x), mat))
    #降序
    sort_frac=fraction_list.sort(reverse=True)
    if sort_frac is not None:
        fraction=sort_frac[0]/sort_frac[1]
    else:
        fraction=1
    #原子叙述
    atomic_number=list(map(lambda x: x.Z, mat))
    #电负性
    electronegativity=list(map(lambda x: x.X, mat))
    #周期
    element_group=list(map(lambda x: x.group, mat))
    #将上述相加
    descriptor=atomic_number+electronegativity+element_group
    #附加原子数比值
    descriptor.append(fraction)
    return descriptor

#将上述下载得到的数据集中元素都计算其描述子
X=np.array(list(map(lambda x: mat_descriptor_calculation(x), materials)))
#单独获取bondgap列,作为数据集结果
y=trainFile['bondgap']
#拆分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.8, random_state=369)

#这里试了lightbgm和贝叶斯优化随便选了几个参数进行调参。
#首先对参数范围,初期点数量以及迭代次数进行设定。
#num_leaves:每个树上的叶子数,树模型复杂度,默认31
#max_depth:树模型的最大深度
#n_estimators:随机森林中树的数量
#learning_rate:学习率
pbonds={
    'num_leaves': (5,100),
    'max_depth': (2,10),
    'n_estimators': (300,700),
    'learning_rate': (0.001,0.8)
}
init_points= 5
n_iter= 20

#然后调参。这里用的标准是r2。
def rfc_cv(num_leaves, max_depth, n_estimators, learning_rate, data, targets):
    estimator = lgb.LGBMRegressor(
        num_leaves=num_leaves,
        max_depth=max_depth,
        n_estimators=n_estimators,
        learning_rate=learning_rate,
        random_state=9527
    )
    cval = cross_val_score(estimator, data, targets,scoring='r2', cv=5)
    return cval.mean()

def optimize_rfc(data, targets):
    def rfc_crossval(num_leaves, max_depth, n_estimators, learning_rate):
        return rfc_cv(
            num_leaves=int(num_leaves),
            max_depth=int(max_depth),
            n_estimators=int(n_estimators),
            learning_rate=max(min(learning_rate, 0.999), 1e-3),
            data=data,
            targets=targets,
        )

    optimizer = BayesianOptimization(
        f=rfc_crossval,
        pbounds=pbonds,
        random_state=2234,
        verbose=2
    )
    optimizer.maximize(n_iter=n_iter,init_points=init_points)
    params=optimizer.max['params']
    modify_para=list(params.values())

    best_param={
        'learning_rate':round(modify_para[0],3),
        'max_depth':int(modify_para[1]),
        'n_estimators':int(modify_para[2]),
        'num_leaves':int(modify_para[3])
               }
    print(best_param)
    print(round(optimizer.max['target'],4))
    return(best_param)

optimize_rfc(X_train, y_train)
#最后使用调出来的参数代到模型然后对训练集进行预测:
best_para={'learning_rate': 0.321, 'max_depth': 5, 'n_estimators': 390, 'num_leaves': 16}
clf=lgb.LGBMRegressor(**best_para)
clf.fit(X_train,y_train)
y_pred=clf.predict(X_test)
#最后对结果进行预测:
from sklearn.metrics import r2_score
from sklearn.metrics import mean_squared_error
import math
R2 = r2_score(y_test, y_pred)
RMSE = math.sqrt(mean_squared_error(y_test, y_pred))
print('R2:{}'.format(R2))
print('RMSE:{}'.format(RMSE))
print()

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萌新待开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值