首页 / 资讯中心 / 文章详情

蛋白质亚细胞定位预测:从序列到机器学习建模的完整指南

蛋白质亚细胞定位预测:从序列到机器学习建模的完整指南 ★ FEATURED ARTICLE
简介一份面向生物信息学研究者与机器学习初学者的专业文献聚焦蛋白质亚细胞定位预测这一经典课题系统梳理了数据集构建、序列特征刻画和分类算法选择等关键环节适合作为课题入门或方法综述参考。资源为PDF格式共1个文件压缩包大小514KB内容为中山大学学者发表于《计算机科学》的期刊论文包含摘要、引言、方法总结与展望等完整章节。目前已有191人学习可作为快速了解该领域研究脉络的便捷材料。读者可在其中获得关于SVM、随机森林、神经网络等算法在亚细胞定位预测中的适用场景对比以及PSSM、氨基酸组成等特征提取技术的具体应用思路同时了解数据不平衡与特征表示等现存挑战和未来方向。1. 蛋白质亚细胞定位预测为什么用机器学习模型而不是查数据库一个刚拿到新蛋白序列的研究者最想知道的往往不是它的折叠结构而是“它跑到细胞哪里去了”。细胞核、线粒体、内质网、细胞膜、溶酶体……这个位置标签直接决定了下游实验怎么设计要不要做膜蛋白提取要不要走分泌途径验证药物靶点靠不靠谱。实验定位主要靠荧光成像和分级分离成本高、周期长通量撑不起全蛋白组筛选于是大家把目光转向了机器学习模型——用已有实验注释的蛋白做训练集从序列本身挖特征让模型学会“什么样的序列大概率待在哪个区室”。这个方向看起来是个标准的序列分类问题但真正动手会碰上一堆机器学习方法里不常讲的麻烦标签是多标签而不是互斥、序列同源性会悄悄污染验证集、PSSM特征让维度一下子涨到几千。这篇文章就按“数据集 → 特征 → 模型 → 调参 → 避坑 → 落地”的顺序把一整条能跑通的流程拆给你看。适合刚接触生物信息学的机器学习入门者也适合想把自己模型做得更严谨的有经验工程师。2. 先定标签再谈模型多标签数据集的下载、过滤与去冗余2.1 标签不是“细胞核”“细胞质”二选一多标签和层级标签是常态大多数人第一次听到亚细胞定位直觉上会把它当成一个多分类问题每个蛋白属于且仅属于一个位置。真去翻注释才知道不是这样。一个蛋白可能同时出现在细胞核和细胞质比如很多转录因子在胞质里被修饰后再入核也可能既在质膜上又在内体里循环。UniProt 的亚细胞定位注释本身就是多值的而且带着层级线粒体外膜、线粒体内膜、线粒体基质这三级子位置彼此之间不是独立标签而是共享一个“线粒体”父类。第一步就是要决定预测粒度。粗粒度细胞核、细胞质、线粒体、内质网、高尔基体、质膜、溶酶体、过氧化物酶体、胞外、液泡等十来个类做出来实用性强注释覆盖率高适合大多数下游筛选细粒度线粒体外膜 vs 内膜需要的数据量成倍增加类间相似性也高新手很容易被类不均衡拖死。我一般建议第一版先做粗粒度多标签把每个位置当成独立标签用多输出模型一支一支训练而不是强行把“多个位置”压成“一个主位置”。还有一个容易踩的坑是注释里的修饰词。UniProt 的定位注释经常带 Some evidence、Probable、By similarity 这样的置信度标记或者带 “Note” 说明。如果不过滤模型会在“实验证据”和“同源推断”的混合标签上学习测试指标看着高实际用在异构蛋白上却虚得很。过滤原则很简单优先保留有实验证据的注释至少别让 By similarity 占比超过一半。2.2 从 UniProt 拉取金标准集REST 下载与字段清洗常见做法是直接从 UniProt REST API 拉取 reviewedSwiss-Prot条目查询条件限定物种和必须包含亚细胞定位注释。下面这段代码用 Python 的 requests 一次拉全需要的字段注意超时时间要放宽注释字段内容很长。import requests import pandas as pd # reviewed:true 即 Swiss-Protorganism_id:9606 是人类 query (reviewed:true) AND (organism_id:9606) AND (cc_subcellular_location:*) params { query: query, format: tsv, fields: ( accession,protein_name,length, cc_subcellular_location,sequence ), size: 500, } url https://rest.uniprot.org/uniprotkb/stream r requests.get(url, paramsparams, timeout300) r.raise_for_status() lines [line.rstrip(\n).split(\t) for line in r.text.strip().split(\n)] header, rows lines[0], lines[1:] df pd.DataFrame(rows, columnsheader) print(df.shape) print(df[Sub cellular location].head())逻辑说明size500是单次拉取上限超过这个数量时 REST 接口会自动分页稳妥做法是把响应头里的next链接循环取完这里为了演示只拿第一页cc_subcellular_location:*是“注释里存在该字段”的查询条件实际使用的字段名在 TSV 里会被转成Sub cellular location解析列名时要留意。拿到原始注释后下一步做标签清洗。# 取每个注释的第一行主定位并过滤低置信度词 allowed_hint set([evidence, experimental, inferred]) def parse_location(text: str): if pd.isna(text): return [] lines str(text).split(;) # UniProt 每条子位置一般以分号结束 locs [] for ln in lines: if Note in ln or Predicted in ln: continue part ln.strip() # 只保留第一部分作为位置名不做细粒度拆分 locs.append(part.split(Probable)[0].split(By similarity)[0].strip()) return list(set([x for x in locs if x])) df[locations] df[Sub cellular location].map(parse_location) df df[df[locations].map(len) 0].reset_index(dropTrue) print(df[locations].head(10))这里把每一条注释按分号切块跳过 Note 和 Predicted 开头的部分再把 Probable/By similarity 这种词从位置名里剥掉。实际项目中我会把过滤条件提得更靠前统计每个位置名的样本量少于 50 条的位置直接合并到父类或丢弃避免后面训练时少数类完全学不出来。2.3 用 CD-HIT 去掉同源冗余序列相似度对划分的破坏数据集建完机器学习方法里最像“玄学”的一个环节来了如果你的训练集和测试集里存在两条序列一致性超过 70% 的蛋白模型根本不需要学习“定位信号”它只要记住序列片段就能把测试集猜对。这种同源泄漏在蛋白质预测里远比普通表格数据里的数据泄漏隐蔽因为序列相似性不是简单的“同一行复制”你可能完全看不出训练集和测试集有交集。解决办法是先用 CD-HIT 对全量序列去冗余。CD-HIT 按给定相似度阈值把序列聚成簇每个簇内取一条代表序列。对亚细胞定位数据集0.7 是一个比较常见且不太伤害样本量的阈值。# 把数据集里的序列整理成 fasta 后运行 cd-hit -i all_proteins.fa -o nr_proteins.fa \ -c 0.7 -n 3 -M 8000 -T 4参数说明-c 0.7是序列相似度阈值-n 3是 word lengthCD-HIT 要求阈值在 0.7 附近时用 3-M 8000限制内存为 8000 MB-T 4用 4 个线程。跑完后nr_proteins.fa里每个簇只留一条代表序列。注意一点去冗余本身会让类不均衡更严重因为相似序列往往扎堆在同一个家族里抽取后少数类可能更少要重看一遍类别分布。更严格的划分是聚类后用簇 ID 做分组划分即同一簇的所有蛋白要么全在训练集、要么全在验证集而不是简单对去冗余后的代表序列做随机切分后者仍然会让同一簇的旁系序列混进验证集。3. 把一条蛋白序列变成特征向量AAC、DPC 与 PSSM 的取舍3.1 第一版特征氨基酸组成与二肽组成跑通最小流程机器学习基础告诉我们模型吃的是固定维度的向量。蛋白序列长度从几十到几千不定直接塞给树模型或神经网络都不合适所以得从序列里抽一组长度固定的数值特征。最朴素的特征有两个氨基酸组成AAC20 维和二肽组成DPC400 维。AAC 统计二十种氨基酸各自的出现频率DPC 统计相邻两个氨基酸组成的 400 种二肽频率。代码很简单但它能抓到的信号有限——它完全丢弃了氨基酸的位置信息而很多定位信号恰恰在 N 端或跨膜区这种特定位置。AA_LIST ACDEFGHIKLMNPQRSTVWY def aac(seq: str) - list: 氨基酸组成返回20维向量 seq seq.upper() n len(seq) return [seq.count(aa) / n for aa in AA_LIST] def dpc(seq: str) - list: 二肽组成返回400维向量 seq seq.upper() n len(seq) vec [] for a in AA_LIST: for b in AA_LIST: di a b # count 在长序列上比较慢但第一版可读性优先 vec.append(seq.count(di) / (n - 1)) return vec逻辑说明这里把序列全转大写再计数避免输入的小写混入导致频率总和不为 1。AAC 向量的第 i 维代表第 i 种氨基酸占比DPC 的第 i*20j 维代表“第 i 种氨基酸接第 j 种氨基酸”的二肽占比。注意短序列上二肽占比的分母是n-1当 n 小于 2 时这个特征直接没有意义所以建特征前要把长度小于 30 的序列过滤掉——很多短肽其实是注释错误的残段留着只会增加噪音。AACDPC 一共有 420 维作为第一版特征足够和基线模型跑通全流程但它做了不到 0.75 的 F1 别意外这是正常的下一步升级特征才是关键。3.2 升级特征PSSM 与头部位置统计把定位信号提出来序列进化学里最好用的蛋白特征之一是位置特异性打分矩阵PSSM。它把一条序列拿去和同源蛋白做多序列比对得到每个位置上二十种氨基酸的出现倾向相当于用进化信息替你把“序列的哪些位置保守”这种信号显式化。对亚细胞定位来说很多信号本身就在保守的功能位点或信号肽区域里PSSM 比单纯序列组成有效得多。生成 PSSM 的常见做法是用 PSI-BLAST。先对 2.3 节去冗余后的蛋白库建库再对每条目标序列迭代搜索同源序列并输出 PSSM 文件。makeblastdb -in nr_proteins.fa -dbtype prot -out nr_db -parse_seqids # 对单条序列迭代3轮输出PSSM psiblast -query query_protein.fa -db nr_db \ -num_iterations 3 -evalue 0.001 \ -out_ascii_pssm query_protein.pssm \ -num_threads 4参数说明-num_iterations 3是迭代轮数轮数越多同源信息越全但越慢也会把太远的同源序列拉进来-evalue 0.001是纳入多序列比对的阈值越严格保留的同源序列越少-out_ascii_pssm指定输出纯文本 PSSM。对一个几千条蛋白的数据集这一步通常要跑几小时到半天是整套流程里最耗时的部分。跑完后 PSSM 文件是一个L×20的打分矩阵L 是查询序列长度。拿到 PSSM 矩阵后不能直接拼进模型因为每条序列的 L 不一样。常见做法是把它折叠成固定维度我一般用“头部位置统计 全局统计”的组合取矩阵前 1%、2%、3%、4%、5% 行分别算均值和标准差再接上全矩阵的均值和标准差。import numpy as np def pssm_to_feature(pssm_path: str, seq_len: int) - np.ndarray: rows [] with open(pssm_path, r, encodingutf-8) as f: for line in f: parts line.split() # PSSM数据行恰好为1索引20个氨基酸字母20个score2个附加列 if len(parts) 44: try: rows.append([float(x) for x in parts[2:22]]) except ValueError: continue arr np.array(rows) # L x 20 if arr.shape[0] 30: return None feats [] # 对前1%~5%的头部位置做统计 for k in range(1, 6): cut max(1, int(seq_len * k / 100)) top arr[:cut, :] feats.append(top.mean(axis0)) feats.append(top.std(axis0)) feats.append(arr.mean(axis0)) feats.append(arr.std(axis0)) return np.concatenate(feats)逻辑说明len(parts) 44是对 PSSM 数据行的一个稳妥判断——PSI-BLAST 输出的数据行包含序号、20 个氨基酸字母、20 个分值、保守性两个字段空行和注释行都不会触发这个条件。头部位置统计的动机是N 端的信号肽和跨膜螺旋对整个定位贡献很大直接取全序列均值会把 N 端的强信号稀释掉。seq_len * k / 100得到头部若干行对它们做均值与标准差得到 2025200 维头部特征再拼全矩阵均值、标准差最后每个蛋白得到 240 维 PSSM 特征。3.3 特征拼接与标准化顺序、量纲与降维的坑AAC、DPC、PSSM 特征拼起来一共 660 维方向没问题但有两个细节会让机器学习算法悄悄翻车。第一个是量纲AAC 和 DPC 是频率范围在 [0, 1]PSSM 的分值是整数范围可能从 -7 到 14量纲差异对距离类模型是灾难对树模型影响小一些但拼一起做标准化总没错。第二个是拼接顺序我习惯把特征按「序列组成 → 进化信息」的顺序拼这样特征列名可读性也高排查问题时不至于对着几百个匿名列发懵。from sklearn.preprocessing import StandardScaler all_features [] for _, row in tqdm(df.iterrows(), totallen(df)): f1 aac(row[Sequence]) f2 dpc(row[Sequence]) f3 pssm_to_feature(row[pssm_path], len(row[Sequence])) if f3 is None: continue all_features.append(np.concatenate([f1, f2, f3])) X np.vstack(all_features) scaler StandardScaler() X_scaled scaler.fit_transform(X)这里有个坑想提醒一下StandardScaler必须在训练集上 fit再分别 transform 训练集和验证集而不是在合并后的全量数据上 fit。很多人先拼完数据再切分再统一做标准化这属于典型的数据泄漏会让验证集指标虚高。还有一点特征维度涨到 660 时确实有降维冲动但我不建议对这类序列特征直接上 PCA 然后丢前几百维——PSSM 的头部统计里各维之间有实际生物含义PCA 组分很难解释万一模型在验证集上表现差了你根本看不出是信号丢了还是模型欠拟合。真要做特征选择用树模型的特征重要性或者线性模型的 L1 惩罚更直白。4. 训练与调参用 LightGBM 多输出模型完成一次完整训练4.1 为什么不用普通多分类标签相关性要吃进模型里做亚细胞定位预测最省事的想法是把“细胞核”“细胞质”“线粒体”这些位置拼成一个互斥标签套用多分类。这个做法在第一版可以快速看效果但它和生物事实是对不上的。一个蛋白同时注释为“细胞核 细胞质”时你没法把它塞进任何一个互斥类别若强行取第一个注释位置相当于扔掉了生物注释里本来就存在的信息。更稳妥的是把多标签拆成多个独立二分类每个位置一个分类器输出 0/1。这就是 sklearn 里的MultiOutputClassifier内部为每个标签单独训练一个模型。优点是简单可靠不会因为标签之间的相关性产生奇怪的耦合缺点是完全没有建模标签之间的相关性比如“细胞外”和“内质网”在分泌通路里其实强相关。但对第一版来说独立二分类的收益远大于风险先跑通再优化。要注意多标签的评估指标也跟着变不能只看 accuracy。标签矩阵里绝大多数位置是 0样本不均衡会让 accuracy 虚高。我习惯同时看 macro F1每个标签算 F1 再取平均和 Hamming Loss预测错误的位置标签占总标签数的比例。macro F1 对少数类不友善但正好能逼你把少数类的问题暴露出来。4.2 可复现的训练脚本多输出 LightGBM 与评估指标这里给出一个可以直接跑的训练脚本。切分数据时我用train_test_split但在正式项目里建议改成按 CD-HIT 聚类分组划分避免同源序列跨集合泄漏。import lightgbm as lgb import numpy as np from sklearn.model_selection import train_test_split from sklearn.multioutput import MultiOutputClassifier from sklearn.metrics import f1_score, hamming_loss # Y 是 (n_samples, n_labels) 的01矩阵列名与位置标签对应 Y df_label_matrix[location_labels].values X_train, X_val, Y_train, Y_val train_test_split( X_scaled, Y, test_size0.15, random_state42, stratifyNone ) base lgb.LGBMClassifier( n_estimators800, learning_rate0.05, num_leaves31, min_data_in_leaf20, class_weightbalanced, random_state42, verbosity-1, ) model MultiOutputClassifier(base, n_jobs4) model.fit(X_train, Y_train) Y_pred model.predict(X_val) print(Macro F1:, f1_score(Y_val, Y_pred, averagemacro)) print(Hamming Loss:, hamming_loss(Y_val, Y_pred))逻辑说明MultiOutputClassifier会对每一列标签训练一个独立的LGBMClassifierclass_weightbalanced是按该标签的正负样本比例自动调整权重解决单个标签内部的不均衡n_jobs4让各个标签的模型并行训练这里不是单棵树内部的线程数。Y_pred是 0/1 矩阵评估用 macro F1 比 accuracy 诚实得多。输出 Hamming Loss 作为辅助参考两个指标一起看能避免只盯着一个数自我安慰。第一次跑如果 macro F1 在 0.75 上下说明特征没问题接下来就是调参和查坑。4.3 四个必调参数与参数搜索顺序LightGBM 在蛋白序列特征上有四组参数直接影响过拟合和效果按优先级排num_leaves、min_data_in_leaf、learning_rate、n_estimators。这里不写一键网格搜索因为蛋白数据量通常只有几千条粗网格搜索会把计算耗在无意义的组合上先手动定两组再细调更实用。num_leaves控制单棵树的复杂度默认 31 在表格数据上没问题在小样本蛋白数据集上容易过大导致单棵树记住样本可以先从 15 试起验证集 F1 不再涨了就停下。min_data_in_leaf是每片叶子最少样本数这是 LightGBM 防过拟合最有力的旋钮2050 比较常见样本少时我直接设 40。learning_rate和n_estimators是一对learning_rate 越小需要的树越多0.05 800 是一个起步组合如果验证集还有提升空间把 learning_rate 降到 0.03 同时把 n_estimators 提到 1500。from sklearn.model_selection import GridSearchCV param_grid { estimator__num_leaves: [15, 31], estimator__min_data_in_leaf: [20, 40], estimator__learning_rate: [0.03, 0.05], } grid GridSearchCV( MultiOutputClassifier(lgb.LGBMClassifier(n_estimators800, class_weightbalanced, random_state42, verbosity-1)), param_grid, scoringf1_macro, cv3, n_jobs4, ) grid.fit(X_train, Y_train) print(grid.best_params_)这里有两点要说明。第一f1_macro是 sklearn 提供的多标签全局评估它把每个标签的 F1 平均但不会告诉你少数类标签死了几个所以搜完参还要单独打印每个标签的 F1。第二网格搜索的cv3用在几千条样本上是可以接受的但如果特征已经到几千维、蛋白数上万建议换成随机搜索或先固定一半参数再调另一半。搜索完成后用最优参数在验证集上重新评估并保留模型用于 6.2 节的可解释性分析。5. 避坑蛋白质亚细胞定位预测中最常翻车的 5 个坑5.1 验证集F1虚高到0.85一到新蛋白就垮——同源泄漏现象训练集和测试集随机切分后 macro F1 冲到 0.85但拿去预测另一个物种的蛋白F1 直接掉到 0.55甚至比随机好不了多少。原因这是蛋白质机器学习模型里最普遍、最隐蔽的一个坑——测试集里混着与训练蛋白高度同源的序列。序列相似度不是“同一行数据复制”那种肉眼可见的泄漏它藏在进化关系里随机切分根本无法避开。解决在 2.3 节 CD-HIT 去冗余后用聚类簇 ID 做分组切分。sklearn 里有现成的GroupShuffleSplit把每条序列所属的簇 ID 作为 group 传进去保证同一个簇的序列全部落在同一侧。from sklearn.model_selection import GroupShuffleSplit gss GroupShuffleSplit(n_splits1, test_size0.15, random_state42) train_idx, val_idx next(gss.split(X, Y, groupscluster_ids)) X_train, X_val X[train_idx], X[val_idx] Y_train, Y_val Y[train_idx], Y[val_idx]用聚类分组划分后 F1 掉到 0.7 以下别慌这属于把水挤干之后留下的真实水平。外部验证集最好选一个亲缘关系较远的物种比如人类训练、酵母验证能暴露模型是不是只记住了某个保守家族的特征。5.2 单标签分类器吃多标签数据少数类位置被雪藏现象用普通多分类训练预测时少数类位置几乎永远不被选中检查数据发现大量蛋白同时有“细胞核”和“细胞质”注释强行取主位置后信息丢失。原因把多标签折叠成单标签时样本量较少的位置更难被分到而且同时出现在多个位置的真实信号被“只能选一个”的规则强行抹掉了。解决改用MultiOutputClassifier独立预测每个标签。另外检查“位置重叠”程度如果某两个标签经常成对出现比如细胞核细胞质可以在后续考虑标签间依赖但第一版不建议上复杂模型先保住每个标签的独立召回率。5.3 PSSM脚本解析翻车blast列变、路径与内存不足现象pssm_to_feature跑出一堆 None或者维度对不上报错信息指向数组越界。原因PSI-BLAST 输出的.pssm文件在不同版本下列数不一样有的行末尾没有保守性那两列有的版本输出 42 列有的 44 列盲目按固定索引切片会让解析结果整个错位。另外query_protein.fa如果包含换行符不一致的序列BLAST 直接报错或静默跳过。解决解析时不要依赖列数猜改用正则匹配每行的第一个位置序号并检查行首是否是数字同时读文件前先看行数是否和序列长度一致。建议在特征提取前跑一个快速自检统计 PSSM 文件的有效数据行数和输入序列长度差异超过 2 行就报错不要等模型训练完才发现特征矩阵是歪的。5.4 只看accuracy模型把少数定位位点全判成胞质现象验证集 accuracy 0.9但每个类别单独看时内质网、溶酶体这些少数类的 recall 接近 0模型把所有不确定的蛋白全分到了“细胞质”。原因亚细胞定位数据集天然高度不均衡细胞质和细胞核占了绝大多数少数类样本少的可能只有几十条。accuracy 在这种分布下完全失去鉴别力。解决从第一天就看 macro F1、每个标签的 precision/recall而不是 accuracy。类别不均衡真正动手做时我一般先靠class_weightbalanced不够再加少数类过采样对序列数据不要直接上 SMOTE它不认序列语义合成出来的“伪氨基酸序列”在生物学上可能是垃圾。5.5 特征维度过高、样本太少树模型开始背样本现象验证集 F1 很高但 SHAP 值乱成一团特征重要性前几名是几个无意义的二肽组合把训练标签随机打乱后重训F1 居然还有 0.5 以上。原因特征 600 多维样本只有两三千条且特征之间有大量冗余树模型开始走捷径记住训练样本。解决调小num_leaves、调大min_data_in_leaf是第一板斧第二板斧是砍特征——先取树模型的特征重要性前 200 维重新跑一遍或者用线性模型做 L1 筛选第三板斧是不要把 PCA 当默认降维PCA 会毁掉 PSSM 头部统计的可解释性且对这种稀疏高维特征提升有限。判断模型有没有背样本有一个土办法把标签 shuffle 后重新训练如果 F1 还有 0.5 上下说明你的管道里一定哪里漏了。6. 落地技巧把预测结果变成可解释的可信位置6.1 用概率阈值替代硬标签在不同标签上找各自阈值训练完成后的模型默认用 0.5 做阈值这个值对多数标签太武断。细胞核样本多模型概率估计偏高0.5 可能太保守溶酶体样本少模型普遍不敢给高分0.5 又会把真实正例全滤掉。常见做法是对每个标签单独在验证集上找一个 F1 最大的阈值。for i, label in enumerate(location_labels): proba model.predict_proba(X_val)[i][:, 1] # 第i个标签的正类概率 best_th, best_f1 0.5, 0 for t in np.arange(0.25, 0.85, 0.05): yp (proba t).astype(int) f1 f1_score(Y_val[:, i], yp, zero_division0) if f1 best_f1: best_th, best_f1 t, f1 print(label, best_threshold:, round(best_th, 2), f1:, round(best_f1, 3))逻辑说明predict_proba在MultiOutputClassifier里返回一个列表每个元素是 (n_samples, 2) 的数组[i]取第 i 个标签[:, 1]取正类概率。阈值搜索范围取 0.250.85 而不是从 0 开始因为概率低于 0.25 的位置基本不值得输出。最终每个标签的阈值可能相差很大这很正常。输出预测时把“未达到阈值的标签”移除再把剩下的位置名按概率降序排列这样给到生信合作者的结果更接近一个“候选位置列表”而不是一个武断的硬标签。6.2 SHAP 解释看 N 端信号是不是真在推动预测模型训练完不能只当黑匣子用尤其要拿去发表或做决策支撑时得能解释“为什么这个蛋白被预测到线粒体”。SHAP 是配合树模型最好用的解释工具对单个样本能输出每个特征的贡献值。import shap # 以第一个标签为例解释其模型 explainer shap.TreeExplainer(model.estimators_[0]) shap_values explainer.shap_values(X_val, check_additivityFalse) shap.summary_plot(shap_values, X_val, feature_namesfeature_names, max_display20)这里model.estimators_[0]是第 0 个标签比如线粒体对应的 LightGBM 模型shap_values是该模型在每个验证集样本上的 SHAP 值矩阵。看 summary plot 时优先找那些“高值和高 SHAP 同时出现”的特征。如果 PSSM 头部统计特征排在最前说明模型确实在利用 N 端信号这和生物学直觉一致如果排在最前的是几个二肽频率特征就要怀疑模型学到的是某种奇怪的模式需要回调特征或加数据。用小样本蛋白集跑 SHAP 通常几秒到十几秒就能完成不要嫌慢。取 Top 特征再看个案是习惯动作别一次解释所有特征。最后说一个我自己的教训早期做这类预测时验证集 F1 一到 0.8 就急着发表直到换物种验证才发现模型学的是序列同源而不是定位信号。后来我把 CD-HIT 聚类分组划分当成默认配置每条序列的簇 ID 进数据库每次切分都带上模型迭代过程中保留一个与训练物种亲缘关系足够远的外部验证集这个外部集从不过拟合只看最终版本。不管特征做得多花哨、模型换得多先进这一步都不能省。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站