一、賽事背景
在當今科技日新月異的時代,人工智能(AI)技術正以前所未有的深度和廣度滲透到科研領域,特別是在化學及藥物研發中展現出了巨大潛力。精準預測分子性質有助于高效篩選出具有優異性能的候選藥物。以PROTACs為例,它是一種三元復合物由目標蛋白配體、linker、E3連接酶配體組成,靶向降解目標蛋白質。本次大賽聚焦于運用先進的人工智能算法預測其降解效能,旨在激發參賽者創新思維,推動AI技術與化學生物學的深度融合,進一步提升藥物研發效率與成功率,為人類健康事業貢獻智慧力量。通過此次大賽,我們期待見證并孵化出更多精準、高效的分子性質預測模型,共同開啟藥物發現的新紀元。
二、賽事任務
選手根據提供的demo數據集,可以基于demo數據集進行數據增強、自行搜集數據等方式擴充數據集,并自行劃分數據。運用深度學習、強化學習或更加優秀人工智能的方法預測PROTACs的降解能力,若DC50>100nM且Dmax<80% ,則視為降解能力較差(demo數據集中Label=0);若DC50<=100nM或Dmax>=80%,則視為降解能力好(demo數據集中Label=1)。
下面給出代碼流程:
- 數據加載:
- 使用
pandas
庫從Excel文件中加載訓練和測試數據集。
- 使用
- 數據預處理:
- 刪除訓練集中不需要的列('DC50 (nM)'和'Dmax (%)')。
- 檢查測試集中的列,如果某列的非空值少于10個,則將該列從訓練和測試集中刪除。
- 將訓練和測試集合并為一個數據集,以便進行統一處理。
- SMILES轉換:
- 使用
rdkit
庫將SMILES字符串轉換為isomeric SMILES,并將其連接成一個字符串。
- 使用
- TF-IDF計算:
- 使用
TfidfVectorizer
計算SMILES字符串的TF-IDF值,并將其添加到數據集中。
- 使用
- 自然數編碼:
- 對所有對象類型的列進行自然數編碼,即將每個唯一值映射到一個整數。
- 數據分割:
- 將帶有標簽的數據分割為訓練集和驗證集,測試集保持不變(包含NaN標簽)。
- 特征篩選:
- 選擇除'uuid'、'Label'和'smiles_list'之外的所有列作為特征。
- 網格搜索優化參數:
- 使用
GridSearchCV
進行參數優化,找到最佳的CatBoost分類器參數。
- 使用
- 模型訓練和驗證:
- 使用最佳參數訓練CatBoost分類器,并使用驗證集進行早停,以防止過擬合。
- 預測和保存結果:
- 使用訓練好的模型對測試集進行預測,并將預測結果保存為CSV文件。
下面是具體代碼的分享
import numpy as np
import pandas as pd
from catboost import CatBoostClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score
from rdkit import Chem
from rdkit.Chem import Descriptors
from sklearn.feature_extraction.text import TfidfVectorizer
import os, gc, warnings
from sklearn.model_selection import GridSearchCV, KFold
warnings.filterwarnings('ignore') # 數據加載
train_full = pd.read_excel(r'C:\\Users\\admin\\Desktop\\dataset-new\\dataset-new\\traindata-new.xlsx')
test = pd.read_excel(r'C:\\Users\\admin\\Desktop\\dataset-new\\dataset-new\\testdata-new.xlsx') # 數據預處理
train_full = train_full.drop(['DC50 (nM)', 'Dmax (%)'], axis=1)
drop_cols = []
for f in test.columns: if test[f].notnull().sum() < 10: drop_cols.append(f)
train_full = train_full.drop(drop_cols, axis=1)
test = test.drop(drop_cols, axis=1) data = pd.concat([train_full, test], axis=0, ignore_index=True)
cols = data.columns[2:] # 假設前兩列是uuid和Label(或類似的列),這里需要根據實際情況調整 # 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)) # TF-IDF計算
tfidf = TfidfVectorizer(max_df=0.9, min_df=1, sublinear_tf=True)
res = tfidf.fit_transform(data['smiles_list'])
tfidf_df = pd.DataFrame(res.toarray())
tfidf_df.columns = [f'smiles_tfidf_{i}' for i in range(tfidf_df.shape[1])]
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]) labeled_data = data[data.Label.notnull()] train, val = train_test_split(labeled_data, test_size=0.01, random_state=42, stratify=labeled_data['Label']) # 外部驗證集仍然是原始測試集,它包含NaN標簽
test = data[data.Label.isnull()] # 特征篩選
features = [f for f in train.columns if f not in ['uuid', 'Label', 'smiles_list']] # 構建訓練集和驗證集
x_train = train[features]
y_train = train['Label'].astype(int)
x_val = val[features]
y_val = val['Label'].astype(int) # 網格搜索優化參數
params = { 'learning_rate': [0.1], 'depth': [ 6], 'l2_leaf_reg': [1], 'bootstrap_type': ['Bernoulli'], 'od_type': ['Iter'], 'random_seed': [42]
} model = CatBoostClassifier(iterations=20, eval_metric='AUC', verbose=1)
grid_search = GridSearchCV(model, params, cv=5, scoring='f1', verbose=1, n_jobs=-1)
grid_search.fit(x_train, y_train) # 輸出最佳參數
print("Best parameters:", grid_search.best_params_)
print("Best score:", grid_search.best_score_) # 使用最佳參數訓練模型,并使用驗證集進行早停
best_model = CatBoostClassifier(**grid_search.best_params_, iterations=2, eval_metric='AUC', use_best_model=True, verbose=1)
best_model.fit(x_train, y_train, eval_set=[(x_val, y_val)]) # 預測
test_pred = best_model.predict_proba(test[features])[:, 1] # 保存結果
pd.DataFrame({ 'uuid': test['uuid'], 'Label': np.where(test_pred > 0.5, 1, 0)
}).to_csv('submit.csv', index=None)
最后是運行結果: