DataWhale AI夏令营-催化反应速率预测(机器学习方向思路)

@[TOC](DataWhale AI夏令营-催化反应速率预测(机器学习方向思路))

(无特征工程)

个人的机器学习竞赛上分之路分享

因为自己也是机器学习竞赛方面的小白嘛,所以就总结了一下自己一步一步调优的思路吧。

首先是baseline的调优,刚接触催化反应速率预测这个任务的时候没什么思路,就是简单的调参,跟着网上的一些教程,还有AI,接触了网格搜索调参、贝叶斯调参。然后调到一定位置的时候基本想长分就开始困难了。

就开始接触换模型,这部分试了一些感觉更高级的模型,比如之前写到的梯度提升回归模型、XGBoost模型等等,相较于baseline也有不小的提升。

试过很多模型,但上分空间还是有限,看了一些大佬的笔记,了解到了stacking,基本的概念就是通过堆叠一些一级模型的结果,交给一个二级模型学习,能得到更好的效果,刚好自己之前试过很多模型参数调的也都比较好,很适合拿来做一级模型,就用了一个简单的线性回归作为二级模型没想到效果出奇的好。查阅了一些资料,如果增加一级模型也能够使结果得到提升,或者使用更复杂的二级模型学习更多的非线性的知识也能取得更好的效果,就又在不断的尝试。

Stacking

纯分享没干货怎么行。下面是一份我使用随机森林、梯度提升回归模型和XGBoost模型作为一级模型,二级模型选择最简单的线性回归的一份代码,现在我只简单的跑了一次是拿到了0.37+的分数。大家也可以去尝试一下。

在阿里云CPU就可以运行,但是如果你换了更复杂的二级模型,就需要用GPU来跑了,不然带不动

python 复制代码
# 导入库
import pickle
import pandas as pd
from tqdm import tqdm
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor, StackingRegressor
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from rdkit.Chem import rdMolDescriptors
from rdkit import RDLogger, Chem
import numpy as np
from xgboost import XGBRegressor
RDLogger.DisableLog('rdApp.*')

def mfgen(mol, nBits=2048, radius=2):
    # 返回分子的位向量形式的Morgan fingerprint
    fp = rdMolDescriptors.GetMorganFingerprintAsBitVect(mol, radius=radius, nBits=nBits)
    return np.array(list(map(int, list(fp.ToBitString()))))

# 加载数据
def vec_cpd_lst(smi_lst):
    smi_set = list(set(smi_lst))
    smi_vec_map = {}
    for smi in tqdm(smi_set):  # tqdm:显示进度条
        mol = Chem.MolFromSmiles(smi)
        smi_vec_map[smi] = mfgen(mol)
    smi_vec_map[''] = np.zeros(2048)

    vec_lst = [smi_vec_map[smi] for smi in smi_lst]
    return np.array(vec_lst)

dataset_dir = '../dataset'   # 注:如果是在AI Studio上,将这里改为'dataset'

train_df = pd.read_csv(f'{dataset_dir}/round1_train_data.csv')
test_df = pd.read_csv(f'{dataset_dir}/round1_test_data.csv')

print(f'Training set size: {len(train_df)}, test set size: {len(test_df)}')

# 从csv中读取数据
train_rct1_smi = train_df['Reactant1'].to_list()
train_rct2_smi = train_df['Reactant2'].to_list()
train_add_smi = train_df['Additive'].to_list()
train_sol_smi = train_df['Solvent'].to_list()

# 将SMILES转化为分子指纹
train_rct1_fp = vec_cpd_lst(train_rct1_smi)
train_rct2_fp = vec_cpd_lst(train_rct2_smi)
train_add_fp = vec_cpd_lst(train_add_smi)
train_sol_fp = vec_cpd_lst(train_sol_smi)
# 在dim=1维度进行拼接。即:将一条数据的Reactant1, Reactant2, Additive, Solvent字段的morgan fingerprint拼接为一个向量。
train_x = np.concatenate([train_rct1_fp, train_rct2_fp, train_add_fp, train_sol_fp], axis=1)
train_y = train_df['Yield'].to_numpy()

# 测试集也进行同样的操作
test_rct1_smi = test_df['Reactant1'].to_list()
test_rct2_smi = test_df['Reactant2'].to_list()
test_add_smi = test_df['Additive'].to_list()
test_sol_smi = test_df['Solvent'].to_list()

test_rct1_fp = vec_cpd_lst(test_rct1_smi)
test_rct2_fp = vec_cpd_lst(test_rct2_smi)
test_add_fp = vec_cpd_lst(test_add_smi)
test_sol_fp = vec_cpd_lst(test_sol_smi)
test_x = np.concatenate([test_rct1_fp, test_rct2_fp, test_add_fp, test_sol_fp], axis=1)

# 划分训练集和验证集
X_train, X_val, y_train, y_val = train_test_split(train_x, train_y, test_size=0.2, random_state=42)

# 定义一级模型
rf_model = RandomForestRegressor(n_estimators=200, max_depth=None, max_features='sqrt', min_samples_leaf=1, min_samples_split=5, n_jobs=-1)
gb_model = GradientBoostingRegressor(n_estimators=200, learning_rate=0.05, max_depth=20, max_features='sqrt', min_samples_leaf=1, min_samples_split=6)
xgb_model = XGBRegressor(n_estimators=300, learning_rate=0.05, max_depth=20, min_child_weight=3, subsample=0.8, colsample_bytree=0.4, n_jobs=-1)

# 定义堆叠模型
stacking_model = StackingRegressor(
    estimators=[('rf', rf_model), ('gb', gb_model), ('xgb', xgb_model)],
    final_estimator=LinearRegression()
)

# 训练堆叠模型
stacking_model.fit(X_train, y_train)

# 在验证集上进行预测并评估模型
y_val_pred = stacking_model.predict(X_val)
print(f'Validation MSE: {mean_squared_error(y_val, y_val_pred):.4f}')

# 使用整个训练集训练堆叠模型
stacking_model.fit(train_x, train_y)

# 保存模型
with open('./stacking_model.pkl', 'wb') as file:
    pickle.dump(stacking_model, file)

# 加载模型
with open('stacking_model.pkl', 'rb') as file:
    loaded_model = pickle.load(file)

# 预测\推理
test_pred = loaded_model.predict(test_x)

ans_str_lst = ['rxnid,Yield']
for idx, y in enumerate(test_pred):
    ans_str_lst.append(f'test{idx+1},{y:.4f}')
with open('./submit.txt', 'w') as fw:
    fw.writelines('\n'.join(ans_str_lst))
相关推荐
开发者每周简报10 分钟前
求职市场变化
人工智能·面试·职场和发展
AI前沿技术追踪23 分钟前
OpenAI 12天发布会:AI革命的里程碑@附35页PDF文件下载
人工智能
余~~1853816280030 分钟前
稳定的碰一碰发视频、碰一碰矩阵源码技术开发,支持OEM
开发语言·人工智能·python·音视频
galileo20161 小时前
LLM与金融
人工智能
DREAM依旧1 小时前
隐马尔科夫模型|前向算法|Viterbi 算法
人工智能
ROBOT玲玉1 小时前
Milvus 中,FieldSchema 的 dim 参数和索引参数中的 “nlist“ 的区别
python·机器学习·numpy
GocNeverGiveUp1 小时前
机器学习2-NumPy
人工智能·机器学习·numpy
浊酒南街2 小时前
决策树(理论知识1)
算法·决策树·机器学习
B站计算机毕业设计超人2 小时前
计算机毕业设计PySpark+Hadoop中国城市交通分析与预测 Python交通预测 Python交通可视化 客流量预测 交通大数据 机器学习 深度学习
大数据·人工智能·爬虫·python·机器学习·课程设计·数据可视化
学术头条2 小时前
清华、智谱团队:探索 RLHF 的 scaling laws
人工智能·深度学习·算法·机器学习·语言模型·计算语言学