1478 字
7 分钟
datawhale笔记|分子预测大模型竞赛-baseline精读分享|笔记one
1.需要会使用Python一些基本的库
如 os sys re numpy之类的 这里知道了一个新库rdkit,这是一个用于处理化学结构的库
时间和期末考试时间冲突了5号会吧笔记补充完整
库引用部分
import numpy as npimport pandas as pdfrom catboost import CatBoostClassifierfrom sklearn.model_selection import StratifiedKFold, KFold, GroupKFoldfrom sklearn.metrics import f1_scorefrom rdkit import Chemfrom rdkit.Chem import Descriptorsfrom sklearn.feature_extraction.text import TfidfVectorizerimport tqdm, sys, os, gc, re, argparse, warningswarnings.filterwarnings('ignore')2.数据预处理部分
train = pd.read_excel('./dataset-new/traindata-new.xlsx')test = pd.read_excel('./dataset-new/testdata-new.xlsx')
# test数据不包含 DC50 (nM) 和 Dmax (%)train = train.drop(['DC50 (nM)', 'Dmax (%)'], axis=1)
# 定义了一个空列表drop_cols,用于存储在测试数据集中非空值小于10个的列名。drop_cols = []for f in test.columns: if test[f].notnull().sum() < 10: drop_cols.append(f)
# 使用drop方法从训练集和测试集中删除了这些列,以避免在后续的分析或建模中使用这些包含大量缺失值的列train = train.drop(drop_cols, axis=1)test = test.drop(drop_cols, axis=1)
# 使用pd.concat将清洗后的训练集和测试集合并成一个名为data的DataFrame,便于进行统一的特征工程处理data = pd.concat([train, test], axis=0, ignore_index=True)cols = data.columns[2:]
drop_cols = []for f in test.columns: if test[f].notnull().sum() < 10: drop_cols.append(f)此处不删除数据,可以提升精度,但是需要对数据进行更加精细的分析
3.特征工程
# 将SMILES转换为分子对象列表,并转换为SMILES字符串列表data['smiles_list'] = data['Smiles'].apply(lambda x:[Chem.MolToSmiles(mol, isomericSmiles=True) for mol in [Chem.MolFromSmiles(x)]])data['smiles_list'] = data['smiles_list'].map(lambda x: ' '.join(x))
# 使用TfidfVectorizer计算TF-IDFtfidf = TfidfVectorizer(max_df = 0.9, min_df = 1, sublinear_tf = True)res = tfidf.fit_transform(data['smiles_list'])
# 将结果转为dataframe格式tfidf_df = pd.DataFrame(res.toarray())tfidf_df.columns = [f'smiles_tfidf_{i}' for i in range(tfidf_df.shape[1])]
# 按列合并到data数据data = pd.concat([data, tfidf_df], axis=1)
# 自然数编码def label_encode(series): unique = list(series.unique()) return series.map(dict(zip( unique, range(series.nunique()) )))
for col in cols: if data[col].dtype == 'object': data[col] = label_encode(data[col])
train = data[data.Label.notnull()].reset_index(drop=True)test = data[data.Label.isnull()].reset_index(drop=True)
# 特征筛选features = [f for f in train.columns if f not in ['uuid','Label','smiles_list']]
# 构建训练集和测试集x_train = train[features]x_test = test[features]
# 训练集标签y_train = train['Label'].astype(int)代码执行了以下步骤:
- SMILES转换 :使用RDKit库将数据集中的SMILES字符串转换回SMILES字符串的列表。这里看起来有些冗余,因为您已经拥有SMILES字符串,但可能您想确保所有SMILES都是以相同的方式(例如,考虑异构体信息)处理的。
- 字符串处理 :将SMILES字符串列表转换为单个字符串,每个SMILES之间用空格分隔。
- TF-IDF计算 :使用
TfidfVectorizer从处理后的SMILES字符串创建TF-IDF特征矩阵。 - 转换为DataFrame :将TF-IDF矩阵转换为DataFrame,以便与原始数据集结合。
- 自然数编码 :定义了一个函数
label_encode,用于将分类特征(对象类型)转换为整数编码。 - 特征和标签准备 :
- 对于所有的特征列(
cols),如果它们的数据类型是对象(通常表示为字符串),则应用自然数编码。 - 从合并后的数据集中分离出训练集和测试集,其中训练集包含标签(
Label),测试集不包含。
- 对于所有的特征列(
- 特征和标签的筛选 :从训练集和测试集中筛选出特征列(不包括
uuid、Label和smiles_list),并从训练集中提取标签列。 - 数据类型转换 :将标签列
Label转换为整数类型,以便于模型训练。
3.模型训练与预测
def cv_model(clf, train_x, train_y, test_x, clf_name, seed=2022):
kf = KFold(n_splits=5, shuffle=True, random_state=seed)
train = np.zeros(train_x.shape[0]) test = np.zeros(test_x.shape[0])
cv_scores = [] # 100, 1 2 3 4 5 # 1 2 3 4 5 # 1 2 3 5。 4 # 1 for i, (train_index, valid_index) in enumerate(kf.split(train_x, train_y)): print('************************************ {} {}************************************'.format(str(i+1), str(seed))) trn_x, trn_y, val_x, val_y = train_x.iloc[train_index], train_y[train_index], train_x.iloc[valid_index], train_y[valid_index]
params = {'learning_rate': 0.1, 'depth': 6, 'l2_leaf_reg': 10, 'bootstrap_type':'Bernoulli','random_seed':seed, 'od_type': 'Iter', 'od_wait': 100, 'allow_writing_files': False, 'task_type':'CPU'}
model = clf(iterations=20000, **params, eval_metric='AUC') model.fit(trn_x, trn_y, eval_set=(val_x, val_y), metric_period=100, cat_features=[], use_best_model=True, verbose=1)
val_pred = model.predict_proba(val_x)[:,1] test_pred = model.predict_proba(test_x)[:,1]
train[valid_index] = val_pred test += test_pred / kf.n_splits cv_scores.append(f1_score(val_y, np.where(val_pred>0.5, 1, 0)))
print(cv_scores)
print("%s_score_list:" % clf_name, cv_scores) print("%s_score_mean:" % clf_name, np.mean(cv_scores)) print("%s_score_std:" % clf_name, np.std(cv_scores)) return train, test
cat_train, cat_test = cv_model(CatBoostClassifier, x_train, y_train, x_test, "cat")
pd.DataFrame( { 'uuid': test['uuid'], 'Label': np.where(cat_test>0.5, 1, 0) }).to_csv('submit.csv', index=None)代码定义了一个名为 cv_model 的函数,用于使用交叉验证训练分类模型,并对测试集进行预测。以下是代码的详细步骤和说明:
- 函数定义 :
cv_model函数接受分类器对象clf,训练特征集train_x和标签集train_y,测试特征集test_x,分类器名称clf_name,以及可选的随机种子seed。 - 交叉验证设置 :使用
KFold进行5折交叉验证,shuffle=True表示在分折前打乱数据。 - 初始化变量 :创建两个数组
train和test来存储交叉验证过程中的训练集预测和测试集预测。 - 循环执行交叉验证 :
- 对每一折数据,使用训练索引
train_index和验证索引valid_index分割训练集和验证集。 - 打印当前折数和随机种子。
- 设置 CatBoost 分类器的参数
params。
- 对每一折数据,使用训练索引
- 模型训练 :使用 CatBoost 分类器训练模型,
iterations=20000表示最大迭代次数,eval_metric='AUC'表示使用 AUC 作为评估指标。 - 模型评估 :
- 使用验证集
val_x和val_y对模型进行评估,获取预测概率val_pred。 - 使用测试集
test_x获取测试集预测概率test_pred。
- 使用验证集
- 保存结果 :将验证集的预测结果存储在
train数组中,将测试集的预测结果累加到test数组中,并计算当前折的 F1 分数。 - 输出结果 :打印所有折的 F1 分数、平均值和标准差。
- 返回结果 :返回训练集预测结果
train和测试集预测结果test。 - 模型应用 :
1. 使用
cv_model函数训练 CatBoost 分类器,并将返回的测试集预测结果cat_test用于生成提交文件。 2. 根据预测概率cat_test生成二元标签,概率大于0.5的预测为1,否则为0。 - 生成提交文件 :创建一个包含
uuid和预测标签Label的 DataFrame,并将其保存为 CSV 文件。
官方学习文档https://datawhaler.feishu.cn/wiki/YgNbwUJHKiMuCekhoZ9cEzgxnZc
datawhale笔记|分子预测大模型竞赛-baseline精读分享|笔记one
https://blog.fiveqm.com/archives/158