当前位置:   article > 正文

datawhale AI 夏令营——分子AI预测赛Task2笔记

datawhale AI 夏令营——分子AI预测赛Task2笔记

进阶baseline详解

导入模块

导入Python中用于数据分析、机器学习建模和化学信息学所需的库。以下是每个库的简要说明:

  • numpy: 提供强大的多维数组对象和相应的操作。

  • pandas: 提供高性能、易用的数据结构和数据分析工具

  • catboost: 一个用于机器学习的库,特别是分类和回归任务。

  • sklearn.model_selection: 包含模型选择的多种方法,如交叉验证。

  • sklearn.metrics: 包含评估模型性能的多种指标。

  • rdkit: 一个化学信息学和机器学习软件,用于处理化学结构。

  • sklearn.feature_extraction.text: 提供将文本转换为特征向量的Tf-idf向量化器。

  • tqdm: 用于在长循环中添加进度条的库。

  • sys: 与Python解释器密切相关的模块,提供访问由解释器使用或维护的变量和函数。

  • os: 提供与操作系统交互的功能。

  • gc: 垃圾收集器接口,用于手动标记对象为可删除。

  • re: 正则表达式库,用于字符串搜索和替换。

  • argparse: 用于编写用户友好的命令行接口。

  • warnings: 用于发出警告的库,这里用来忽略警告信息

  1. import numpy as np
  2. import pandas as pd
  3. from catboost import CatBoostClassifier
  4. from sklearn.model_selection import StratifiedKFold, KFold, GroupKFold
  5. from sklearn.metrics import f1_score
  6. from rdkit import Chem
  7. from rdkit.Chem import Descriptors
  8. from sklearn.feature_extraction.text import TfidfVectorizer
  9. import tqdm, sys, os, gc, re, argparse, warnings
  10. warnings.filterwarnings('ignore')

数据预处理

  1. train = pd.read_excel('./dataset-new/traindata-new.xlsx')
  2. test = pd.read_excel('./dataset-new/testdata-new.xlsx')
  3. # test数据不包含 DC50 (nM) 和 Dmax (%)
  4. train = train.drop(['DC50 (nM)', 'Dmax (%)'], axis=1)
  5. # 定义了一个空列表drop_cols,用于存储在测试数据集中非空值小于10个的列名。
  6. drop_cols = []
  7. for f in test.columns:
  8. if test[f].notnull().sum() < 10:
  9. drop_cols.append(f)
  10. # 使用drop方法从训练集和测试集中删除了这些列,以避免在后续的分析或建模中使用这些包含大量缺失值的列
  11. train = train.drop(drop_cols, axis=1)
  12. test = test.drop(drop_cols, axis=1)
  13. # 使用pd.concat将清洗后的训练集和测试集合并成一个名为data的DataFrame,便于进行统一的特征工程处理
  14. data = pd.concat([train, test], axis=0, ignore_index=True)
  15. cols = data.columns[2:]

特征工程

特征工程指的是把原始数据转变为模型训练数据的过程,目的是获取更好的训练数据特征。特征工程能使得模型的性能得到提升,有时甚至在简单的模型上也能取得不错的效果。

  1. # 将SMILES转换为分子对象列表,并转换为SMILES字符串列表
  2. data['smiles_list'] = data['Smiles'].apply(lambda x:[Chem.MolToSmiles(mol, isomericSmiles=True) for mol in [Chem.MolFromSmiles(x)]])
  3. data['smiles_list'] = data['smiles_list'].map(lambda x: ' '.join(x))
  4. # 使用TfidfVectorizer计算TF-IDF
  5. tfidf = TfidfVectorizer(max_df = 0.9, min_df = 1, sublinear_tf = True)
  6. res = tfidf.fit_transform(data['smiles_list'])
  7. # 将结果转为dataframe格式
  8. tfidf_df = pd.DataFrame(res.toarray())
  9. tfidf_df.columns = [f'smiles_tfidf_{i}' for i in range(tfidf_df.shape[1])]
  10. # 按列合并到data数据
  11. data = pd.concat([data, tfidf_df], axis=1)
  12. # 自然数编码
  13. def label_encode(series):
  14. unique = list(series.unique())
  15. return series.map(dict(zip(
  16. unique, range(series.nunique())
  17. )))
  18. for col in cols:
  19. if data[col].dtype == 'object':
  20. data[col] = label_encode(data[col])
  21. train = data[data.Label.notnull()].reset_index(drop=True)
  22. test = data[data.Label.isnull()].reset_index(drop=True)
  23. # 特征筛选
  24. features = [f for f in train.columns if f not in ['uuid','Label','smiles_list']]
  25. # 构建训练集和测试集
  26. x_train = train[features]
  27. x_test = test[features]
  28. # 训练集标签
  29. y_train = train['Label'].astype(int)

代码执行了以下步骤:

  1. SMILES转换:使用RDKit库将数据集中的SMILES字符串转换回SMILES字符串的列表。这里看起来有些冗余,因为您已经拥有SMILES字符串,但可能您想确保所有SMILES都是以相同的方式(例如,考虑异构体信息)处理的。

  2. 字符串处理:将SMILES字符串列表转换为单个字符串,每个SMILES之间用空格分隔。

  3. TF-IDF计算:使用TfidfVectorizer从处理后的SMILES字符串创建TF-IDF特征矩阵。

  4. 转换为DataFrame:将TF-IDF矩阵转换为DataFrame,以便与原始数据集结合。

  5. 自然数编码:定义了一个函数label_encode,用于将分类特征(对象类型)转换为整数编码。

  6. 特征和标签准备

    1. 对于所有的特征列(cols),如果它们的数据类型是对象(通常表示为字符串),则应用自然数编码。

    2. 从合并后的数据集中分离出训练集和测试集,其中训练集包含标签(Label),测试集不包含。

  7. 特征和标签的筛选:从训练集和测试集中筛选出特征列(不包括uuidLabelsmiles_list),并从训练集中提取标签列。

  8. 数据类型转换:将标签列Label转换为整数类型,以便于模型训练。

模型训练与预测

  1. def cv_model(clf, train_x, train_y, test_x, clf_name, seed=2022):
  2. kf = KFold(n_splits=5, shuffle=True, random_state=seed)
  3. train = np.zeros(train_x.shape[0])
  4. test = np.zeros(test_x.shape[0])
  5. cv_scores = []
  6. for i, (train_index, valid_index) in enumerate(kf.split(train_x, train_y)):
  7. print('************************************ {} {}************************************'.format(str(i+1), str(seed)))
  8. 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]
  9. params = {'learning_rate': 0.1, 'depth': 6, 'l2_leaf_reg': 10, 'bootstrap_type':'Bernoulli','random_seed':seed,
  10. 'od_type': 'Iter', 'od_wait': 100, 'allow_writing_files': False, 'task_type':'CPU'}
  11. model = clf(iterations=20000, **params, eval_metric='AUC')
  12. model.fit(trn_x, trn_y, eval_set=(val_x, val_y),
  13. metric_period=100,
  14. cat_features=[],
  15. use_best_model=True,
  16. verbose=1)
  17. val_pred = model.predict_proba(val_x)[:,1]
  18. test_pred = model.predict_proba(test_x)[:,1]
  19. train[valid_index] = val_pred
  20. test += test_pred / kf.n_splits
  21. cv_scores.append(f1_score(val_y, np.where(val_pred>0.5, 1, 0)))
  22. print(cv_scores)
  23. print("%s_score_list:" % clf_name, cv_scores)
  24. print("%s_score_mean:" % clf_name, np.mean(cv_scores))
  25. print("%s_score_std:" % clf_name, np.std(cv_scores))
  26. return train, test
  27. cat_train, cat_test = cv_model(CatBoostClassifier, x_train, y_train, x_test, "cat")
  28. pd.DataFrame(
  29. {
  30. 'uuid': test['uuid'],
  31. 'Label': np.where(cat_test>0.5, 1, 0)
  32. }
  33. ).to_csv('submit.csv', index=None)

代码定义了一个名为 cv_model 的函数,用于使用交叉验证训练分类模型,并对测试集进行预测。以下是代码的详细步骤和说明:

  1. 函数定义cv_model 函数接受分类器对象 clf,训练特征集 train_x 和标签集 train_y,测试特征集 test_x,分类器名称 clf_name,以及可选的随机种子 seed

  2. 交叉验证设置:使用 KFold 进行5折交叉验证,shuffle=True 表示在分折前打乱数据。

  3. 初始化变量:创建两个数组 traintest 来存储交叉验证过程中的训练集预测和测试集预测。

  4. 循环执行交叉验证

    1. 对每一折数据,使用训练索引 train_index 和验证索引 valid_index 分割训练集和验证集。

    2. 打印当前折数和随机种子。

    3. 设置 CatBoost 分类器的参数 params

  5. 模型训练:使用 CatBoost 分类器训练模型,iterations=20000 表示最大迭代次数,eval_metric='AUC' 表示使用 AUC 作为评估指标。

  6. 模型评估

    1. 使用验证集 val_xval_y 对模型进行评估,获取预测概率 val_pred

    2. 使用测试集 test_x 获取测试集预测概率 test_pred

  7. 保存结果:将验证集的预测结果存储在 train 数组中,将测试集的预测结果累加到 test 数组中,并计算当前折的 F1 分数。

  8. 输出结果:打印所有折的 F1 分数、平均值和标准差。

  9. 返回结果:返回训练集预测结果 train 和测试集预测结果 test

  10. 模型应用

    1. 使用 cv_model 函数训练 CatBoost 分类器,并将返回的测试集预测结果 cat_test 用于生成提交文件。

    2. 根据预测概率 cat_test 生成二元标签,概率大于0.5的预测为1,否则为0。

  11. 生成提交文件:创建一个包含 uuid 和预测标签 Label 的 DataFrame,并将其保存为 CSV 文件。

附加学习资料

TF-IDF学习

TF-IDF(Term Frequency-Inverse Document Frequency)是一种用于信息检索与文本挖掘的常用加权技术。它是一种统计方法,用以评估一个词语对于一个文件集或一个语料库中的其中一份文件的重要程度。它的主要思想是:如果某个词语在一篇文章中出现的频率高(Term Frequency,TF),并且在其他文章中很少出现(Inverse Document Frequency,IDF),则认为这个词语具有很好的类别区分能力,对这篇文章的内容有很好的指示作用。

基本使用

TF-IDF通常用于以下方面:

  • 文本挖掘:帮助识别文档中的关键词条。

  • 信息检索:评估词条在文档中的重要性,用于搜索引擎中对搜索结果进行排序。

  • 特征提取:在机器学习算法中,将文本转换为TF-IDF向量,作为输入特征。

 使用步骤

  1. 文本预处理:包括去除标点符号、转换为小写、去除停用词等。

  2. 分词:将文本分割成词条(关键字)。

  3. 计算TF:统计每个词条在文档中出现的频率,并进行归一化。

  4. 计算IDF:统计词条在所有文档中出现的频率,计算其IDF值。

  5. 计算TF-IDF:将TF和IDF相乘,得到每个词条在一个文档中的重要性得分。

代码实现

在Python中,可以使用scikit-learn库中的TfidfVectorizer来方便地实现TF-IDF向量化:

  1. from sklearn.feature_extraction.text import TfidfVectorizer
  2. # 假设我们有以下文档集
  3. documents = [
  4. "这是一个例子文档。",
  5. "这是第二个文档,其中包含一些相同的词。",
  6. "第三个文档完全不同。"
  7. ]
  8. # 初始化TF-IDF向量化器
  9. vectorizer = TfidfVectorizer()
  10. # 转换文档集
  11. tfidf_matrix = vectorizer.fit_transform(documents)
  12. # 查看TF-IDF矩阵
  13. print(tfidf_matrix)

这段代码会输出一个稀疏矩阵,其中包含了每个词条在每个文档中的TF-IDF得分。

TF-IDF是一种简单而强大的文本表示方法,尤其适用于处理大量文本数据。

交叉验证学习

交叉验证(Cross-Validation)是一种统计方法,用于评估并提高模型的预测性能,特别是在样本数量有限的情况下。它可以帮助我们评估模型的泛化能力,即在未知数据上的表现能力,从而减少模型过拟合的风险。

基本思想

将数据集分成几个子集,每次用一个子集作为测试集,其余子集联合起来作为训练集。这个过程重复进行多次,每次选择不同的子集作为测试集,最终得到多个模型评估结果,然后对这些结果进行平均,得到模型性能的综合评估。

主要类型

  1. K-折交叉验证(K-Fold Cross-Validation)

    1. 将数据集随机分成K个子集(或“折”)。

    2. 每次迭代中,选择其中一个子集作为测试集,其余K-1个子集联合作为训练集。

    3. 重复K次,每次选择不同的子集作为测试集。

  2. 留一交叉验证(Leave-One-Out Cross-Validation, LOOCV)

    1. 当数据集较小时使用,每次只留下一个样本作为测试集,其余所有样本作为训练集。

  3. 分层交叉验证(Stratified Cross-Validation)

    1. 特别适用于分类问题,确保每个折中类别的比例与整个数据集保持一致。

  4. 时间序列交叉验证(Time Series Cross-Validation)

    1. 适用于时间序列数据,确保测试集总是来自时间序列的末端。

核心步骤

  1. 分割数据:根据选择的交叉验证类型,将数据集分割成多个子集。

  2. 训练和测试:对每个子集进行训练和测试,记录模型在测试集上的性能。

  3. 性能评估:计算所有迭代中模型性能的平均值和标准差。

  4. 选择模型:根据交叉验证的结果选择表现最好的模型或参数。

 使用优点

  • 减少过拟合:通过在多个训练集上训练模型,可以减少模型对特定训练数据的依赖。

  • 更准确的性能评估:提供了模型在不同数据集上表现的更全面视图。

  • 利用所有数据:每个样本都被用作训练和测试,充分利用了可用数据。

局限性

  • 计算成本:需要多次训练和测试模型,这可能会增加计算时间。

  • 随机性:K-折交叉验证中的随机分割可能导致结果的随机性。

 Catboost学习

CatBoost是一个开源的梯度提升库,由俄罗斯的搜索引擎公司Yandex开发。它专为处理分类和回归任务而设计,尤其擅长处理具有大量类别特征(categorical features)的数据集。CatBoost的名称来源于“Categorical Boosting”,即对类别特征进行增强的算法。

核心优点

  1. 自动处理类别特征:无需对类别特征进行独热编码(One-Hot Encoding),CatBoost可以直接处理类别特征。

  2. 处理缺失值:CatBoost能够自动处理数据中的缺失值。

  3. 提升算法:CatBoost使用梯度提升决策树(GBDT)作为基学习器。

  4. 模型的可解释性:CatBoost提供了特征重要性评估和模型的可解释性工具。

  5. 多任务学习:CatBoost支持多任务学习,即同时学习多个输出。

  6. 支持大数据:CatBoost使用基于GPU和CPU的并行计算,可以高效处理大规模数据集。

使用基本步骤

  1. 数据准备:准备训练数据和测试数据,数据可以是数值型或类别型。

  2. 创建CatBoost模型:使用CatBoost的CatBoostClassifierCatBoostRegressor类创建模型实例。

  3. 设置参数:根据需要设置模型参数,如迭代次数、学习速率、深度等。

  4. 训练模型:使用训练数据训练模型。

  5. 模型评估:使用测试数据评估模型性能。

  6. 应用模型:使用训练好的模型进行预测。

示例代码

  1. from catboost import CatBoostClassifier, Pool
  2. from sklearn.model_selection import train_test_split
  3. from sklearn.metrics import accuracy_score
  4. 假设X是特征数据,y是目标变量
  5. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
  6. 创建CatBoost模型
  7. model = CatBoostClassifier(
  8. iterations=100,
  9. learning_rate=0.1,
  10. depth=6,
  11. loss_function='Logloss',
  12. random_seed=42,
  13. verbose=False
  14. )
  15. 训练模型
  16. model.fit(X_train, y_train)
  17. 预测测试数据
  18. y_pred = model.predict(X_test)
  19. 评估模型
  20. accuracy = accuracy_score(y_test, y_pred)
  21. print(f'Accuracy: {accuracy:.2f}')

 注意事项

  • 在使用CatBoost之前,需要确保安装了CatBoost库,可以通过pip install catboost命令安装。

  • CatBoost的参数众多,可以根据具体问题进行调整以优化模型性能。

  • CatBoost的模型训练速度和内存消耗可能比其他一些梯度提升库要高,特别是在使用大量数据或复杂模型时。

CatBoost是一个强大的机器学习工具,尤其适合处理包含类别特征的数据集,并且提供了许多高级功能来提高模型的性能和可解释性。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/830223
推荐阅读
相关标签
  

闽ICP备14008679号