背景介绍
- 酶的稳定性是影响其实际应用的关键因素之一。通过定点突变可以改善酶的稳定性,但实验筛选稳定性突变体的成本较高。
- 预测突变对酶稳定性的影响,加速筛选稳定性更高的酶突变体。
概念解释
-
突变前的角度 θ:
- 在突变发生之前,红色的 X 残基 位于中心,蓝色的 Y 残基 和 紫色的 Z 残基 分别位于它的两侧。它们之间形成了一个特定的角度 θ。
- 这个角度 θ 表示的是 Y 和 Z 残基通过中心残基 X 的空间几何关系。这个角度可能与蛋白质的功能(如活性位点的构象)密切相关。
-
突变后的角度 θ':
- 当 红色的 X 残基 发生突变时(例如从一种氨基酸变为另一种氨基酸),它的侧链结构或电荷特性发生变化,导致其在三维空间中的位置发生移动。
- X 残基 的移动可能会牵拉或推动相邻的 蓝色 Y 残基 和 紫色 Z 残基,导致它们之间的角度发生变化。新的角度用 θ' 表示。
- 突变后的角度 θ' 可能与原先的角度 θ 不同,这种变化可能会影响蛋白质的整体结构和功能。
数据解释
train.csv和train_updates_20220929.csv: 训练数据集,包含已知序列及其稳定性(熔点tm)的数据。模型可以从中学习序列与稳定性之间的关系。
test.csv: 测试数据集,包含目标酶(GenBank: KOC15878.1)的2,413个单点突变体的序列。参赛者需要预测这些突变体的tm值。
sample_submission.csv: 预测结果提交的格式示例文件。
wildtype_structure_prediction_af2.pdb: 目标酶的野生型三维结构,由AlphaFold2预测得到。这为基于结构的特征提取和建模提供了重要先验信息
这个数据中包含了对某个蛋白质序列(protein_sequence)进行突变(mutation)后的稳定性预测信息。解释下各列的具体含义:
seq_id: 突变的唯一编号,可能是为了区分不同的突变而设置的流水号。
protein_sequence: 完整的蛋白质氨基酸序列。
pH: 进行稳定性预测时设定的pH值,这里为8。蛋白质的稳定性会受pH影响。
location: 发生突变的位点,即突变前的氨基酸在序列中的位置。
wild_type: 突变前的野生型氨基酸。
mutation: 突变后的氨基酸。如果该列为空,表示是一个deletion突变,即缺失突变。
mutation_type: 突变的类型,这里有substitution(替换突变)和deletion(缺失突变)两种。
因此这个数据详细记录了在某pH值下,蛋白质序列中的特定位点发生特定突变后,对其稳定性产生的影响。这种计算突变对蛋白质稳定性影响的方法,可用于指导蛋白质工程和定向进化实验,筛选出稳定性更高的蛋白质突变体。
这个数据展示了蛋白质的一个位点(ResID为1,野生型氨基酸为V)发生不同突变后,对蛋白质稳定性的影响。详细解释:
chain: 表示这些突变发生在蛋白质的A链上。蛋白质可能由多条肽链组成,用不同字母区分。
WT: 表示Wild Type,即野生型氨基酸,这里为V(Valine,缬氨酸)。
ResID: 表示Residue ID,即残基编号,这里为1,表示突变发生在肽链的第一个氨基酸上。
Mut: 表示Mutant,即突变后的氨基酸。这里列出了除V以外的19种氨基酸,分别用它们的单字母代码表示。
ddG (kcal/mol): 表示每个突变对蛋白质稳定性的影响,单位为kcal/mol。
- ddG > 0表示突变后蛋白质变得更稳定
- ddG < 0表示突变后蛋白质变得更不稳定
从数据可以看出,所有可能的单点突变(即V突变为其他19种氨基酸)都会降低蛋白质的稳定性(ddG都为负值)。
方案一
DeepDDG方法简介
- DeepDDG是一个用于预测蛋白质点突变引起的稳定性变化(ΔΔG值)的深度学习方法。
- 它基于蛋白质的三维结构,提取突变位点及其周围残基的结构特征和进化特征,用神经网络建模并预测突变引起的ΔΔG值。
- 提取的特征包括:二面角(φ,ψ,ω)、溶剂可及表面积(SASA)、二级结构(onehot编码)、氢键数量、残基间Ca-Ca距离、残基间取向(Ca-Ca,Ca-C,Ca-N的单位向量)、位置特异性打分矩阵(PSSM)、多序列比对位点出现频率(PFS)、深度突变扫描(DMS)等。
- DeepDDG利用了蛋白质数据库中大量已有的实验测定的ΔΔG数据进行训练。训练数据集中包含了与待预测蛋白质同源性较高的一些蛋白质。
测试集
新增列
- 每个突变体的 edit 数量(除了一个完全匹配野生型序列的)
- 点突变的类型:插入(insertion)、缺失(deletion)或替换(substitution)
- 突变发生在野生型序列中的位置索引
- 野生型该位置的氨基酸残基
- 突变体中插入或替换的氨基酸残基(如有)
import Levenshtein
def get_mutation_info(_row, _wildtype="VPVNPEPDATSVENVALKTGSGDSQSDPIKADLEVKGQSALPFDVDCWAILCKGAPNVLQ" \
"RVNEKTKNSNRDRSGANKGPFKDPQKWGIKALPPKNPSWSAQDFKSPEEYAFASSLQGGT" \
"NAILAPVNLASQNSQGGVLNGFYSANKVAQFDPSKPQQTKGTWFQITKFTGAAGPYCKAL" \
"GSNDKSVCDKNKNIAGDWGFDPAKWAYQYDEKNNKFNYVGK"):
terminology_map = {"replace":"substitution", "insert":"insertion", "delete":"deletion"}
req_edits = Levenshtein.editops(_wildtype, _row["protein_sequence"])
_row["n_edits"] = len(req_edits) # 计算突变数量
if _row["n_edits"]==0: # 如果没有突变,则其他突变信息为空
_row["edit_type"] = _row["edit_idx"] = _row["wildtype_aa"] = _row["mutant_aa"] = pd.NA
else:
_row["edit_type"] = terminology_map[req_edits[0][0]] # 获取突变类型
_row["edit_idx"] = req_edits[0][1] # 获取突变位置索引
_row["wildtype_aa"] = _wildtype[_row["edit_idx"]] # 获取野生型氨基酸
_row["mutant_aa"] = _row["protein_sequence"][req_edits[0][2]] if _row["edit_type"]!="deletion" else pd.NA # 获取突变型氨基酸
return _row
def revert_to_wildtype(protein_sequence, edit_type, edit_idx, wildtype_aa, mutant_aa):
if pd.isna(edit_type):
return protein_sequence
elif edit_type!="insertion":
new_wildtype_base = protein_sequence[:edit_idx]
if edit_type=="deletion":
new_wildtype=new_wildtype_base+wildtype_aa+protein_sequence[edit_idx:]
else:
new_wildtype=new_wildtype_base+wildtype_aa+protein_sequence[edit_idx+1:]
else:
new_wildtype=protein_sequence[:edit_idx]+wildtype_aa+protein_sequence[edit_idx:]
return new_wildtype
test_df = test_df.progress_apply(get_mutation_info, axis=1) # 对测试集逐行进行突变信息提取
test_df[["protein_sequence", "edit_type", "edit_idx", "wildtype_aa", "mutant_aa"]]
在原有 test_df
的基础上增加了一些新的列,包括:
n_edits
: 突变的数量edit_type
: 突变的类型(substitution, insertion, deletion)edit_idx
: 突变发生的位置索引wildtype_aa
: 突变位置的野生型氨基酸mutant_aa
: 突变后的氨基酸(如果是deletion则为空)
DeepDDG服务器预测ΔΔG
DeepDDG服务器预测单点突变引起的折叠自由能变化(ΔΔG)具体步骤为:
- 使用 AlphaFold2 预测野生型酶的3D结构
- 将野生型结构文件提交到 DeepDDG 服务器
- 服务器预测每个可能的突变位点的 ΔΔG 值
- 将预测结果与测试集突变数据匹配,得到每个突变体的预测 ΔΔG
import pandas as pd
import numpy as np
#helper function
def read_list_from_file(list_file):
with open(list_file) as f:
lines = f.readlines()
return lines
#读取DeepDDG预测结果
ddg = read_list_from_file('../input/submit-novozymes-00/wildtype_structure_prediction_af2.deepddg.ddg.txt')
header = ddg[0]
data = [s.split() for s in ddg[1:]]
df = pd.DataFrame(data, columns = ['chain', 'WT', 'ResID', 'Mut', 'ddG'])
df.ddG = df.ddG.astype(np.float32)
df.ResID = df.ResID.astype(int)
df.loc[:,'location'] = df.ResID -1 #change to 0-indexing
#读取测试集突变信息
test_df = pd.read_csv('../input/submit-novozymes-00/test.more.csv')
test_df.location = test_df.location.fillna(-1)
test_df.location = test_df.location.astype(int)
#生成提交文件
if 1:
df.loc[:,'mut_string'] = df.WT+df.location.astype(str)+df.Mut
test_df.loc[:,'mut_string'] = test_df.wild_type+test_df.location.astype(str)+test_df.mutation
test_df = test_df.merge(df[['ddG','mut_string']], on='mut_string',how='left') # 将预测的ddG值与测试集突变信息匹配
submit_df = pd.DataFrame({
'seq_id': test_df.seq_id.values,
'tm': test_df.ddG.values, # 直接使用ddG作为Tm预测值
})
submit_df.tm = submit_df.tm.fillna(0)
submit_df.to_csv('deepddg-ddg.csv', index=False) #lb0.335
print(submit_df)
print('submit_df ok!')
问题思考
- DeepDDG 的训练数据中是否包含与测试酶相似的蛋白?
- ΔΔG 与目标值 ΔTm 之间有何关联?
- AlphaFold2 预测的结构特征对本次比赛的作用如何?
- DeepDDG 的网络结构是怎样的?
方案二
特征工程
1.使用突变残基周围21个残基的三维坐标信息构建结构特征,包括相对距离、夹角。
受这篇论文[1]的启发,我选择了离突变残基最近的21个残基来构建结构特征
2.利用B-factor、BLOSUM矩阵、DeMaSk、SASA等已有特征。
3.使用Facebook预训练的蛋白质transformer ESM提取序列嵌入特征。
4.使用PCA对嵌入特征进行降维。
构建三个XGB模型
1.XGB1:使用1800+行的训练集,特征包括ESM提取特征、B_factor、相对距离等。
2.XGB2:使用来自30个同源、相同pH组的986个突变的训练集,特征与XGB1相同。
3.XGB3:使用外部数据集中6000多行不稳定突变样本,仅使用结构特征。
集成多个公共模型
1.NESP 3D geometry:使用突变残基与蛋白质中心之间的距离作为特征。
2.FoldX:利用FoldX软件计算ddG值。
3.ThermoNet v2:使用体素化的3D结构特征和辅助的dTm目标训练CNN模型。
4.Relaxed rosetta scores:使用Rosetta软件计算relax结构的能量分数。
5.RMSD:根据分子动力学模拟轨迹计算每个残基的RMSD。
6.Different pLDDT:计算突变型与野生型的pLDDT差异。
XGB模型和公共模型进行加权集成
构建三个XGBoost模型的策略允许利用不同的数据集和特征,从多个角度学习蛋白质稳定性与突变之间的关系,并通过集成学习提高最终预测的鲁棒性和准确性。这种方法在处理复杂的生物学问题时非常有效。
相关知识
Lesson1:酶预测大赛1_蛋白质tm值-CSDN博客
kaggle酶稳定性预测第三名解决方案分享_侧链表面积与每个残基的无规卷曲值的比例 溶剂暴露-CSDN博客
残基接触图_残基接触图分析-CSDN博客
[lb0.335] DeepDGG server benchmark | Kaggle (方案一)