2024 Datawhale 夏令营 零基础入门AI(机器学习)竞赛 Task3

#AI夏令营 #Datawhale #夏令营 #Task3

记录自己参加 Datawhale 夏令营期间的学习心得,欢迎交流讨论

这一版笔记主要是对 Baseline 的进阶和代码分析,主要分为三部分:数据预处理特征工程模型训练与预测(Task 3)

准备工作

获取数据

赛事链接 https://challenge.xfyun.cn/h5/detail?type=molecular-properties&ch=dw24_3Gp2Ih

导入核心库

  • numpy: 提供强大的多维数组对象和相应的操作。
  • pandas: 提供高性能、易用的数据结构和数据分析工具。
  • catboost: 一个用于机器学习的库,特别是分类和回归任务。
  • sklearn.model_selection: 包含模型选择的多种方法,如交叉验证。主要用到了 K-折交叉验证
  • sklearn.metrics: 包含评估模型性能的多种指标。主要采用 f1 分数评估
  • rdkit: 一个化学信息学和机器学习软件,用于处理化学结构。
  • sklearn.feature_extraction.text: 提供将文本转换为特征向量的 TF-IDF 向量化器。

一 数据预处理

处理数据,目的是筛选出可用数据,提高特征辨别性,最终改善模型训练效果。

1 去除多余标签

test 数据不包含标签 DC50 (nM) 和 Dmax (%),使用 drop 将其去除

train = train.drop(['DC50 (nM)', 'Dmax (%)'], axis=1)

2 删除缺失值较多项

避免较多空缺值(此处取 10 位界限)对训练和分析的影响,使用 drop 去除

drop_cols = [] 
for f in test.columns: 
    if test[f].notnull().sum() < 10: 
        drop_cols.append(f)

train = train.drop(drop_cols, axis=1)
test = test.drop(drop_cols, axis=1)

3 合并数据

将清洗后的训练集和测试集合并,便于进行统一的特征工程处理

data = pd.concat([train, test], axis=0, ignore_index=True) 
cols = data.columns[2:]

二 特征工程

将原始数据转变为模型训练数据以获得特征,使得模型性能提升。

1 选择特征

  • 竞赛的目的是分析 PROTACs 技术在靶向降解目标蛋白质方面的潜力,作为一种化学物质,其化学结构显然可以作为特征。
  • Smiles 是一种用于描述化学结构的文本字符串,它能够被用于输入化学信息学软件。如:
NC1=NC=NC2=C1C(C1=CC=C(OC3=CC=CC=C3)C=C1)=NN2[C@@H]1CCCN(C(=O)C2=CN(CCOCCOCCOCCCC3=CC=CC4=C3CN(C3CCC(=O)NC3=O)C4=O)N=N2)C1
# 将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))

2 筛选特征

  • 特征的目的是高区分度
  • TF-IDF 的主要思想简单来说就是:此处频率高(Term Frequency, TF),别处频率低(Inverse Document Frequency, IDF)
  • 采用 TF-IDF 进行特征评估
# 使用 TfidfVectorizer 计算 TF-IDF 
tfidf = 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)

3 转换形式

  • 采用编码为自然数的方式转换特征
# 自然数编码 
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])

4 构建训练、测试集

# 分离训练、测试集
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)

三 模型训练与预测

正式开始模型训练(搓手)
利用输入的数据,通过模型(可理解为分类器)去输出一个类别,其中包含训练,预测以及统计学的验证等过程。

1 定义函数

  • 定义用于交叉验证训练分类模型的函数
    • 分类器
    • 训练集
    • 标签集
    • 测试集
    • 种子
  • 循环交叉验证
  • 模型训练与评估
def cv_model(clf, train_x, train_y, test_x, clf_name, seed=2022):
    # 5 折交叉验证
    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]
        
        # 设置 CatBoost 分类器的参数      
        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'}
        
        # 模型训练,使用 AUC 作为评估指标
        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)
    
    # 打印所有折的 F1 分数、平均值和标准差
    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

2 应用模型

# 模型应用,使用 cv_model 函数训练 CatBoost 分类器
cat_train, cat_test = cv_model(CatBoostClassifier, x_train, y_train, x_test, "cat")

# 将返回的测试集预测结果 cat_test 用于生成提交文件
pd.DataFrame(
    {
        # 根据预测概率 cat_test 生成二元标签,概率大于 0.5 的预测为 1,否则为 0
        'uuid': test['uuid'],
        'Label': np.where(cat_test>0.5, 1, 0)
    }
).to_csv('submit.csv', index=None)

其他想法

  • 特征非常重要,特征越多,效果越明显
    • 具体来说,比如 InChI 是由一系列部分组成,提供了关于分子结构的详细信息。
      开头标识、分子式、连接表、氢原子计数、多可旋转键计数、立体化学信息、同分异构体信息、混合物或互变异构体信息、电荷和自旋多重度信息等
  • 尝试其他模型也可以得到不同的结果,不同模型的适用性不同
    • lightgbm、xgboost 和 catboost 模型等等
  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值