简介:面向生物信息学与基因工程方向的开发者及研究者,这份资料聚焦用机器学习设计密码子优化DNA序列以提升蛋白表达,适合具备Python基础、希望把序列特征工程与神经网络预测落到实处的学习者。资源包共15个文件,约36.65MB,以Python脚本为核心,配合JSON词表配置、HDF5模型权重、训练历史与评估记录、说明文档等,形成从序列编码、模型训练到结果校验的完整链路。目前已有706人学习下载。内容围绕密码子使用偏斜、G+C含量等特征展开,涵盖数据预处理、模型训练与调优、序列预测及生物学规则后处理,并附带中文仓鼠CDS数据与分词配置,可帮助读者复现RNN建模流程、理解词表与模型文件的组织方式,也便于对照评估记录分析优化策略的效果,为后续实验验证提供可操作的参考。
1. 密码子优化到底在改什么:同一道菜,换一种下锅顺序
同样一份蛋炒饭,先下蛋还是先下饭,出来的口感能差一截。密码子优化干的正是这件事:蛋白质的氨基酸序列一个都不动,只把编码它的 DNA 序列换一种写法。遗传密码自带一层冗余,20 种氨基酸对应 61 个有义密码子,同一个氨基酸往往有好几个“同义词”。挑哪几个同义词、按什么顺序排,直接决定细胞里的核糖体读得顺不顺、mRNA 稳不稳、最后能产出多少蛋白质。这几年机器学习被拉进来做这件事,是因为“哪个同义词更好”不再靠一条频率规则拍板,而是让模型从成千上万条实测序列里把规律学出来。搞懂这套逻辑,你就明白为什么同一段基因换个写法,产量能差出几十倍。
2. 为什么同一段蛋白有成千上万种写法:冗余与偏好
一段 300 个氨基酸的蛋白,理论上能写出天文数字种不同的 DNA 序列,翻译出来的蛋白质却一模一样。这种“写法多得离谱”的特性,既是密码子优化存在的理由,也是它麻烦的来源。要理解后面所有方法为什么长成那个样子,得先把这套编码规则里的两个事实弄清楚:密码子表本身是冗余的,而细胞对同义词并不是一视同仁。
2.1 61 个有义密码子:一套自带同义词表的编码
DNA 用四个字母写句子,每三个字母一组读成一个氨基酸,这一组就叫密码子。四个字母里取三个、允许重复,一共 4×4×4=64 种组合。其中三个是终止信号,剩下 61 个负责指名道姓地点氨基酸,而要命的是氨基酸总共只有 20 种——平均下来每个氨基酸能分到三个密码子,多的能分到六个。
这套冗余在生物学上叫简并性。它意味着大多数氨基酸位置都有两到六种写法可以挑,只有色氨酸和甲硫氨酸是“独生子”,各自只有一个密码子。甲硫氨酸那个密码子还兼任起始信号,所以一条编码序列的开头基本是钉死的,优化算法在这一点上没有任何腾挪空间。
分配得也不均匀。亮氨酸、丝氨酸、精氨酸各有六个密码子,属于选择最多的位置;色氨酸、甲硫氨酸只有一个,属于完全没得选的位置。一条序列里真正能被优化的位置,通常只占三分之二左右,剩下的动一下就改变了氨基酸,那是蛋白工程,不是密码子优化。
提示:不同宿主使用的密码子表并不完全一致,线粒体和某些原生生物的读法与标准表存在出入。动手之前先确认目标宿主按哪张表读,这一步省不得,弄错了整条序列从第一个密码子起就是错的。
2.2 密码子偏好性:为什么不同物种偏爱不同的同义词
如果同义词真的可以随便挑,密码子优化这个行当就不会存在。麻烦在于细胞对同义词有明确偏好,这套偏好叫密码子偏好性,说白了就是“这个物种习惯用哪几个词”。
最直接的原因是 tRNA 的供应量。每个 tRNA 由对应的基因编码,基因组里不同 tRNA 基因的拷贝数差别很大,拷贝多的 tRNA 数量充足,对应的密码子被核糖体读得更快;拷贝少的 tRNA 供不应求,核糖体走到那儿就得等。细胞里还流行一种“最优密码子对应单一高频 tRNA”的搭配方式,让高表达基因能用最少的资源跑出最快的速度。
这种偏好不是偶然,是长期选择的结果。高表达的基因,比如核糖体蛋白、延伸因子这些,往往把密码子用得高度顺口;低表达基因就随意得多,稀有密码子随处可见。所以拿一批高表达基因去统计频率,能反推出这个物种“喜欢”哪些同义词,这也是后面要讲的 CAI 指标的由来。
偏好还带着明显的物种和地方色彩。大肠杆菌偏爱 A 或 T 结尾的密码子,G 或 C 结尾的相对少见;酵母和哺乳动物细胞则偏向 G 或 C 结尾。同一条基因,把宿主从细菌换成酵母,原来那套“最优写法”未必还是最优。所以密码子优化天生是相对宿主而言的,没有绝对最好的序列,只有针对某个宿主、某个表达系统、某套培养条件的较优解。
顺带说一句,偏好还会被基因自身的碱基组成、密码子前后邻居甚至 mRNA 结构牵着走,并不完全由 tRNA 丰度决定。这也是为什么单纯按频率表替换,效果常常达不到预期。
2.3 稀有密码子不等于坏密码子:翻译节奏的另一面
早期做法非常直白:把每个氨基酸都换成宿主最高频的那个密码子,让整条序列尽可能“顺口”。这套做法在不少常规场景里确实够用,但它背后藏着一个假设——翻译越快越好,每个位置都用最顺口的词最好。真实情况要复杂得多。
核糖体并不是匀速滑过 mRNA 的。碰上稀有密码子,对应的 tRNA 稀少,核糖体要停一停。如果某个基因里连续出现好几个稀有密码子,等待时间叠加,翻译效率断崖式下跌,严重的甚至中途脱落,产出一条残缺的肽链。这就是为什么“稀有密码子成簇”是优化里必须清掉的硬伤。
但单个位置上的那次暂停,反而是有功能的。新生肽链从核糖体出口出来的那一刻就开始折叠,它需要时间找到正确的构象,暂停正好给了这个窗口。有实验观察到,把稀有密码子统统换成高频版本,蛋白产量不升反降,可溶性也变差,折叠出了问题。所以“稀有”和“坏”不能画等号,真正要管的是节奏。
这就是密码子优化里最像玄学的一块:快和慢本身不分高下,关键是该快的地方快、该慢的地方慢,而这个“该”目前很大程度上还得靠实验去摸。加上密码子好不好还跟前后邻居、跟整条 mRNA 折叠成什么形状有关,逐位打分再相加的模型在这里特别容易翻车——它默认每个位置独立,而 mRNA 是个会自己抱团的分子。
3. 机器学习怎么插手:从“按频率打分”到“序列进、表达出”
把优化目标交给模型,本质上换了一套裁判逻辑。频率法问的是“这个密码子在本物种里常见吗”,机器学习问的是“这条完整序列,实测能产出多少蛋白”。前者只需要一张统计表,后者需要成千上万条带标签的真实数据,以及一套能把 DNA 变成数字再变回来的流程。这一章把这套流程拆开看。
3.1 传统做法的天花板:CAI 与它的盲区
密码子适应指数 CAI 是最经典的指标。做法是从宿主的一批高表达基因里统计每个密码子的相对使用频率,给每个密码子算一个 0 到 1 之间的权重,再对整条序列取几何平均。CAI 越接近 1,说明这条序列越贴近宿主的“用词习惯”。
它的好处很实在:算得快、可解释、不需要任何实验数据,一条序列几毫秒就出结果。缺点同样硬。它只统计了频率,完全没有位置概念,不知道 5′ 端长什么样,不知道序列会不会折叠成死结,也看不出稀有密码子是不是扎堆出现。在真实数据上,CAI 与实测表达量的相关性常常只有中等水平,拿它当唯一目标去优化,很容易优化出一条“看起来很标准”却产量平平的序列。
于是思路转向数据驱动:既然表达量是测出来的,那就收集大量“序列—表达量”配对样本,训一个模型直接预测表达量,再拿它当裁判去搜索序列。这就是机器学习在密码子优化里最核心的角色——它不生成序列,它只负责打分,找序列是另一套算法的事。
3.2 训练数据从哪来:标签质量决定模型上限
模型能学到什么,完全取决于喂进去的数据长什么样。常见的几类来源各有各的脾气。
报告基因文库是最干净的一类。把成千上万条同义变体挂在同一个启动子、同一个荧光蛋白后面,测荧光强度,序列和表达量一一对应,噪声可控。缺点是它测的是“报告基因在特定构建下的表现”,换一个基因、换一个载体,规律未必迁得过去。
核糖体印迹测的是核糖体在 mRNA 上的分布密度,能间接反映翻译速率和暂停位置,对理解节奏很有用,但它不是直接的产量数据。
蛋白组与转录组配对能提供大规模的真实观测,可惜噪声大,mRNA 丰度和蛋白丰度之间隔着翻译效率、降解速率、折叠质量好几层,模型学到的是混合效应。
小规模定点饱和突变数据质量最高,几十上百条,覆盖范围却很窄,通常只够做验证或微调。
注意:用荧光报告库训出来的模型,学到的多是“翻译效率”相关的规律;用蛋白组数据训的模型,预测的是最终产量,中间混进了稳定性、降解、折叠等因素。这两个靶子经常被混为一谈,实际并不是一回事。
还有一个容易忽略的坑是分布偏移。训练集里的序列大多是围绕某几个天然基因做的同义变体,彼此相似度很高。拿这样的模型去预测一条完全无关的工业基因,外推能力要打个问号。稳妥的做法是先用一批自己体系里的序列做小规模标定,看看模型的排序能力和真实数据对不对得上,再决定要不要信它的绝对分数。
3.3 把 DNA 变成模型能读的数字
模型不认识字母,只认识数字。最常用的编码方式是 one-hot:四种碱基各占一个维度,某个位置是什么碱基就把对应维度置 1,其余置 0。按密码子切分之后,每个密码子拼成 12 维向量,一段 300 个氨基酸的序列就变成 300×12 的矩阵。
import numpy as np # 四种碱基映射到 0~3,顺序固定,训练和推理必须一致 BASE_IDX = {"A": 0, "C": 1, "G": 2, "T": 3} def one_hot_cds(cds: str) -> np.ndarray: """把编码序列编码成 (密码子数, 12) 的 one-hot 矩阵。 cds 长度必须是 3 的倍数,且首尾密码子(起始/终止)不做优化。""" cds = cds.upper().replace("U", "T") # 兼容 RNA 写法 assert len(cds) % 3 == 0, "长度必须是 3 的倍数" idx = [BASE_IDX[b] for b in cds] arr = np.zeros((len(cds), 4), dtype=np.float32) arr[np.arange(len(cds)), idx] = 1.0 return arr.reshape(len(cds) // 3, 12) # 每个密码子 3 碱基 × 4 维这段代码解决的是“表示”问题。12 维是碱基级 one-hot 的拼接,优点是保留了每个碱基的位置信息,卷积网络可以在上面滑窗捕捉局部模式,比如相邻密码子的搭配、某个区域的 GC 起伏。另一种常见做法是密码子级 one-hot,每个位置 64 维,只保留“这里是什么密码子”,丢掉了碱基顺序但维度更紧凑,适合序列较长的场景。
再往上一层是 k-mer 计数:统计整条序列里所有 3-mer、4-mer、6-mer 的出现次数,做成一个稀疏向量喂给梯度提升树或线性模型。这种做法实现简单、训练快,对中小规模数据集往往比深度模型更稳,代价是彻底丢掉了位置信息。选哪种编码,取决于你的数据量级和要捕捉的效应——数据少就老老实实用 k-mer,数据多了再上卷积或注意力结构。
3.4 模型打分,算法搜索:在 3 的 L 次方里找一条好序列
有了打分模型,接下来的问题是怎么找。一条 300 个氨基酸的序列,平均每个位置三种可选密码子,搜索空间是 3 的 300 次方,穷举是想都别想的事。可行的手段有模拟退火、遗传算法、整数规划,以及把离散选择松弛成概率分布的梯度方法。模拟退火最容易上手,效果也够用。
import math, random def build_synonym_table(codon_table): """反查密码子表:氨基酸 -> 该氨基酸的全部同义密码子列表""" table = {} for codon, aa in codon_table.items(): table.setdefault(aa, []).append(codon) return table def mutate(cds, syn_table, codon_table): """随机挑一个非首尾的位置,换成同一氨基酸的另一个密码子""" n = len(cds) // 3 k = random.randrange(1, n - 1) # 跳过起始和终止密码子 cur = cds[3 * k:3 * k + 3] choices = [c for c in syn_table[codon_table[cur]] if c != cur] if not choices: return cds # 该氨基酸只有一个密码子,跳过 return cds[:3 * k] + random.choice(choices) + cds[3 * k + 3:] def anneal(cds, score_fn, codon_table, steps=20000, t0=1.0, alpha=0.9995): """模拟退火:score_fn 越大越好,返回最优序列和它的分数""" syn_table = build_synonym_table(codon_table) cur, cur_s = cds, score_fn(cds) best, best_s = cur, cur_s t = t0 for _ in range(steps): cand = mutate(cur, syn_table, codon_table) cand_s = score_fn(cand) # Metropolis 准则:变好就接受,变差按温度概率接受,避免卡在局部最优 if cand_s >= cur_s or random.random() < math.exp((cand_s - cur_s) / t): cur, cur_s = cand, cand_s if cand_s > best_s: best, best_s = cand, cand_s t *= alpha # 温度衰减,后期几乎只接受改进 return best, best_s几个参数值得说清楚。steps决定搜索预算,两万步对一条几百个氨基酸的序列通常够用,太短会停在半路,太长只是浪费算力。t0是初始温度,要和score_fn的取值范围匹配——如果分数在 0 到 1 之间,初始温度取 0.1 以下更合适;分数是任意实数时,先跑几百步看看分数波动幅度再定。alpha控制降温速度,0.9995 配上两万步,温度从头降到接近零,属于比较稳的节奏;想快就调到 0.999,代价是更容易早停。
mutate里那个跳过首尾的细节很关键:起始密码子和终止密码子一旦被换掉,整条序列直接报废,而且报废得悄无声息——模型照样给你一个分数,测序回来才发现读框错了。这类坑踩过一次就忘不掉。
4. 优化目标不止“表达量高”:几个必须同时盯住的约束
把表达量预测当唯一目标去优化,得到的序列大概率合成不出来,或者合成出来测不到信号。原因不复杂:模型学的是数据里的统计规律,它不知道合成公司的报价单,也不知道细胞里还有什么在捣乱。所以真实流程里,模型分数只是打分函数的第一项,后面还挂着一串惩罚项。
4.1 GC 含量与重复序列:先过合成这一关
序列要变成实物,第一道关卡是化学合成。GC 含量极端的区域难合成、难测序、难扩增:GC 太高容易形成发夹和聚合酶滑移,GC 太低则会出现富含 AT 的长片段,本身就容易断裂,在细菌里还可能被当成启动子信号误读。
业界常见的经验区间是整体 GC 控制在 40% 到 60%,局部窗口(比如 50 个碱基一段)不超过 75% 到 80%。这不是硬标准,不同合成方和不同宿主的容忍度有差异,但越界越多,失败概率越高。
重复序列是第二个雷。同一个 8 到 10 个碱基的片段反复出现,合成时的拼接容易出错,进了宿主细胞还可能引发同源重组,把好不容易构建好的质粒切掉一块。同碱基连续串(比如六个以上的 A 或 G)也常被合成方标红,既是合成难点,也是测序时的信号衰减点。这些约束都可以写成简单规则,在搜索时直接过滤候选序列,成本极低,收益极高。
4.2 mRNA 二级结构与 5′ 起跑区:别在起跑线上绊倒
mRNA 不是一条松垮的线,它会在自身碱基配对下折叠成各种茎环结构。折叠本身不是坏事,但折叠在错误的位置就是灾难。
细菌里,核糖体结合位点要和 mRNA 配对才能招募核糖体,如果这段序列被卷进茎环里藏起来,翻译起始效率会断崖式下降。真核细胞里,核糖体从 5′ 帽子往下扫描,5′ 端如果有一坨特别稳定的二级结构,扫描就会卡住,同样起不来。
所以密码子优化在实际操作中常常顺手做一件事:把编码区最前面 30 到 60 个核苷酸换成 GC 较低的同义密码子,让这一段的折叠自由能别太负,把起跑区打开。这一步用规则就能做,不需要模型,但对产量的影响可能比后面几百个位置加起来还大。
提示:起始密码子前后的序列环境也会影响识别效率,真核体系里起始密码子 -3 位和 +4 位的碱基偏好是有共识的。优化时把这两个位置固定下来,别让算法乱动。
4.3 把约束折进打分函数:加权惩罚的写法
模型给一个表达量预测,规则检查给出若干条违规程度,两者合成一个总分。写法有很多种,最直观的是线性加权惩罚:预测值减去各项惩罚乘以权重。
def gc_content(seq: str) -> float: return (seq.count("G") + seq.count("C")) / len(seq) def score(seq, predict_expr, fold_energy, longest_homopolymer, weights): """综合打分:模型预测的表达量减去各类违规惩罚,越大越好。 weights 里的三个系数决定'多在乎'每一类约束,需要按体系调。""" expr = predict_expr(seq) # 模型预测,越大越好 gc = gc_content(seq) pen_gc = max(0.0, abs(gc - 0.5) - 0.05) # 只在偏离 45%~55% 时开罚 pen_run = max(0, longest_homopolymer(seq) - 6) # 同碱基连续超过 6 开始罚 pen_fold = max(0.0, -fold_energy(seq[:60]) - 10.0) # 5′端 60nt 折叠能太负就罚 return (expr - weights["gc"] * pen_gc * 100 - weights["run"] * pen_run - weights["fold"] * pen_fold)三个惩罚项的设计思路是一样的:设一个“容忍区间”,区间内不罚,越界之后线性增长。pen_gc用 0.45 到 0.55 做容忍带,是因为轻微偏离对合成没影响,罚得太早会把搜索空间无谓地砍掉一大块,反而限制了模型发挥。pen_run从连续 6 个同碱基起罚,对应的是合成方常见的标注阈值。pen_fold只算 5′ 端前 60 个核苷酸的折叠自由能,因为那一段才是起始的关键区,整条序列的折叠能算出来意义不大。
权重的调法有个实用顺序:先把模型分数那一项关掉,只用惩罚项跑一遍,确认算法能稳定产出“完全合规”的序列;再把模型权重慢慢加回来,观察违规解是不是逐渐被淘汰。反过来做,很容易得到一条分数漂亮但合成不出来的序列,白忙一场。
4.4 模型分数不等于摇瓶里的产量:中间还隔着几道关
一条序列在打分函数上拿到高分,只说明它符合模型学到的规律,不说明它在你的体系里一定高产。中间至少还隔着几道关。
合成与克隆是第一关,前面说的 GC 和重复序列就卡在这里。表达测试是第二关,荧光、免疫检测、电泳,不同手段测的是不同东西,荧光强不代表可溶性好。可溶性与包涵体是第三关,尤其对复杂蛋白,产量高但全在包涵体里,等于白做。宿主自身的配套是第四关,稀有 tRNA 的补充、伴侣蛋白的共表达、培养温度,都会让同一条序列在不同条件下表现迥异。
真正让机器学习在密码子优化里显出价值的,不是一次预测多准,而是把实验循环起来:设计一批序列、测回来、把实测数据回填进训练集、重新训模型、再设计下一批。这套闭环在学界叫主动学习或贝叶斯优化,几轮下来,模型对特定体系的拟合会明显好于通用模型。代价是需要稳定的实验通量和一段不短的时间,不是一周能跑完的事。
5. 易混概念与常见误区:这五组词别搅在一起
密码子优化这个领域术语密集,很多争论其实是双方在说不同的事。下面五组是初学者最容易混的,混了之后做出来的方案往往方向就偏了。
5.1 密码子优化 ≠ 基因合成
易混点:两个词经常一起出现,听起来像同一件事的两个说法。
为什么混:实际操作中它们确实前后脚发生——先设计序列,再下单合成,中间隔了几天,容易在脑子里合成一个步骤。
怎么区分:基因合成是制造工艺,解决的是“怎么把这条 DNA 造出来”,涉及寡核苷酸拼接、纠错、克隆验证;密码子优化是信息层的工作,解决的是“该造哪条序列”,输入是氨基酸序列和宿主信息,输出是一串字母。合成有成功率和成本问题,优化有预测准确率问题,两套评价标准完全不同。
5.2 同义密码子 ≠ 完全等价
易混点:既然密码子编码同一个氨基酸,换一下应该没有影响。
为什么混:教科书里“简并性”的表述容易给人一种“多对一,冗余无害”的印象,加上“沉默突变”这个词本身就带着误导性。
怎么区分:同义替换改变的是 mRNA 的序列和结构,进而影响翻译速率、核糖体暂停位置、mRNA 半衰期,甚至影响剪接和 miRNA 结合。同一个氨基酸的不同写法,在细胞里的表现可以差出好几倍。把同义替换当成无操作,是这一行最贵的错觉。
5.3 CAI 高 ≠ 表达量高
易混点:CAI 是“密码子适应指数”,名字听起来就像是表达量的预测值。
为什么混:早期文献里 CAI 确实和表达水平有正相关,相关系数也常被拿来做卖点,久而久之被简化成“越高越好”。
怎么区分:CAI 是一个统计描述量,衡量序列贴近宿主高频密码子程度的几何平均,取值范围 0 到 1,与任何实测数据无关。它不看位置、不看结构、不看上下文。CAI 从 0.8 提到 0.95,表达量可能纹丝不动,也可能反而下降。把它当参考指标可以,当优化目标就危险了。
5.4 密码子偏好性 ≠ 表达量预测模型
易混点:两者都在描述“哪种写法更好”,看起来是同一件事的初级版和高级版。
为什么混:预测模型的输入特征里常常包含密码子频率类特征,输出又和“偏好”方向一致,容易被当成同一件事的量化。
怎么区分:密码子偏好性是一张静态的统计表,描述物种层面的用词习惯,不需要标签,不需要训练,也不需要验证。表达量预测模型是一个带参数的函数,需要“序列—实测值”配对数据来拟合,需要留出集来评估,换一个数据集结论可能就变了。前者是后者的输入之一,不是它的替代品。
5.5 密码子优化 ≠ 蛋白改造
易混点:都是想让蛋白表现更好,听起来像同一个目标下的两种手段。
为什么混:实际项目里两件事经常一起做,先改几个氨基酸提高稳定性,再做密码子优化提高产量,报告写在一起,界限就模糊了。
怎么区分:密码子优化有一条铁律——氨基酸序列一个都不能变。任何导致氨基酸改变的改动都属于蛋白工程,涉及结构、功能、免疫原性的重新评估,风险等级完全不同。判断方法很简单:把优化后的序列翻译回氨基酸,与原序列逐位比对,但凡有一处不同,就不是纯粹的密码子优化了。这一步必须做成自动检查,别靠眼睛看。
6. 什么时候该用机器学习,什么时候老实按频率改
判断标准其实不复杂,就看三件事:有没有标签数据、约束多不多、试错成本高不高。
| 场景 | 更稳的做法 | 原因 |
|---|---|---|
| 目标基因不到 300 bp,单宿主常规表达 | 按频率替换 + 规则过滤 | 搜索空间小,试错便宜,模型的边际收益有限 |
| 手上只有一两条序列,没有任何实测数据 | CAI 或频率法 + 手工避开极端 GC 与重复 | 没有标签就训不了模型,通用模型外推风险大 |
| 工业菌株,产量要榨到极致,有稳定的表达测试能力 | 模型打分 + 主动学习闭环 | 有标签、有迭代预算,模型才可能收敛到体系特有的规律 |
| 多基因通路或操纵子 | 逐基因优化后再整体评估 | 单基因最优不等于通路最优,还要防同源重组 |
| 复杂蛋白,需要共翻译折叠 | 保留甚至刻意设计翻译暂停 | 节奏比速度重要,一味求快容易出包涵体 |
| 序列要交给合成方 | 先把合成规则跑一遍 | 有些“最优解”根本合成不出来,白算 |
最该克制的场景是“没有数据也想上模型”。通用模型能在公开数据集上刷出好看的相关系数,但挪到你的宿主、你的载体、你的培养条件里,排序能力可能比 CAI 强不了多少。这时候先用一批自己的序列做小规模标定,二十条也够看出趋势,成本远低于盲目相信一个分数。
另一个容易过度设计的场景是短序列。一条 200 个氨基酸的基因,能用得上的同义位置就几百个,随手替换一下、规则过滤一遍,测一轮就知道行不行。上模型要走数据收集、训练、调参、验证一整套,时间成本反而更高。
真正值得上机器学习的是那些约束缠在一起的活儿:既想表达量高,又要过合成关,还不能有长重复,5′ 端结构要打开,中间某几个位置必须保留天然密码子。这种多目标互相拉扯的局面,人脑排不出最优解,规则法只能一刀切,模型的加权打分加搜索就能显出优势。
我自己的教训是有一回赶进度,跳过规则过滤直接拿模型输出的最高分序列去下单,合成方回邮件说有三处连续重复和一个 12 个碱基的富含 GC 区域建议修改。改完之后模型分数掉了不少,摇瓶里的产量却比之前那版高。从那以后我每次拿到一条要优化的编码序列,都强制走一遍固定流程:先确认宿主密码子表,再检查有没有可用的实测标签,然后把约束写成可回退的打分项,最后才让算法去搜。顺序反过来,很容易得到一条分数漂亮、却哪儿都用不上的序列。
这份资料里把打分函数、模拟退火搜索、以及一套可以直接替换的约束模板都写成了 Python 脚本,参数都是独立变量,换成自己的序列和权重就能跑。希望帮到你。
本文还有配套的精品资源,点击获取