绕过结构预测:AI端到端生成RNA序列的技术原理与实践
RNA 设计这件事过去十几年一直被一条默认流程统治着先想办法预测目标 RNA 的三维结构再根据结构反推序列。这条流程听着很严谨实际做起来却处处是坑。RNA 的三维结构数据极少、构象又高度动态预测精度根本撑不起下游设计——你辛辛苦苦预测出一个结构拿去做逆折叠生成一堆序列结果实验里一个都不工作。最近这项登上《Science》封面的 RNA 设计工作走的是一条完全不同的路线。它把3D 结构预测这一步直接从主流程里删掉了让 AI 从功能目标出发直接生成 RNA 序列。换句话说AI 不再纠结最终折成什么三维形状它只负责学会什么样的序列能干活。这个转变对开发者的意义其实远超 RNA 本身。它代表着一类更普遍的 AI 方法学变化——当模块化管线里的中间环节不可靠时端到端学习可以直接绕过它。本文会从 RNA 设计的真实痛点讲起拆解绕过结构预测的技术原理然后给出一套可以在本地跑起来的 RNA 序列 AI 最小示例最后聊一聊验证、排错和工程落地。1. 为什么 RNA 设计这么难结构优先路线的困境RNA 设计与蛋白质设计不同。蛋白质有天然的结构决定功能逻辑你画出一个目标三维结构用 AlphaFold 验证序列是否能折成这个结构再用 Rosetta 这类工具做固定骨架设计。这套流程在蛋白质领域已经相对成熟因为蛋白质结构数据足够多、折叠相对稳定。RNA 则完全不同。第一可用数据量差了一个量级。蛋白质数据库里实验解出的三维结构超过 20 万个而 RNA 独立折叠结构只有几千到一万量级大量 RNA 结构信息还是嵌在核糖体这类大复合物里的片段。数据不够监督学习就无从谈起。第二RNA 构象高度动态。一条 RNA 分子在溶液中可能同时存在多种构象不像蛋白质那样有一个清晰的能量最低态。你今天预测出的那个结构可能只是它众多状态中的一张快照下一毫秒它就换了形态。把这样一个瞬息万变的分子当作固定蓝图去做设计逻辑上就是脆的。第三预测误差会在管线中逐级放大。传统流程是预测结构 → 逆折叠 → 实验验证。如果第一步预测就有误差第二步的序列搜索会把这个误差扩大成大量无效序列等这些序列进入湿实验成本和时间已经烧掉了。很多团队在实验中发现最终能验证通过的序列比例低得可怜而且失败原因很难归因到具体哪一步。这正是这篇 Science 封面工作想解决的痛点与其在一条误差不断放大的模块化管线上修修补补不如让模型直接从数据中学习序列与功能之间的映射把结构预测这层中间表示整个去掉。这里需要强调一个判断这并不代表 RNA 三维结构不重要而是说对于设计出有功能的 RNA 序列这个任务显式的结构预测不一定是必经之路。AI 完全可以在隐空间中自己学到一个比人工设定更好的结构隐变量。2. 范式转变从结构优先到序列直通要理解这种转变可以看一个软件开发里的类比。早期的机器翻译系统是模块化的分词、词性标注、句法分析、语义表示、目标语言生成每一步都有明确的中间产物。问题在于句法分析这个中间模块的错误会被下游放大而且人工设计的语言规则永远覆盖不了真实语料的多样性。后来神经机器翻译出现直接把源语言句子映射到目标语言句子中间没有显式的句法树。端到端模型在隐空间里自己学会了句法结构而且学得比人工标注更全面——因为它是从亿万级语料里学出来的不是从几条语法规则里推出来的。RNA 设计的范式转变本质上也是同一件事。过去的结构优先路线相当于在做RNA 翻译系统时非要先构建一棵完整的三维结构树再做逆折叠。而新的序列直通路线是让模型直接学序列 → 功能的端到端映射。模型可能在隐空间里确实学到了某种结构表示但那是它自己从数据中发现的表示而不是人工指定的、需要精确坐标的物理结构。这种范式的优势很明显绕开了数据瓶颈。不再需要标注好的三维结构数据做训练只需要大量的 RNA 序列数据和对应的功能标签。绕开了误差放大。中间环节消失了模型直接优化最终目标训练目标与真实任务一致。更容易规模化。序列数据比结构数据多几个数量级自监督预训练可以充分利用这些数据。当然也有代价。代价是可解释性下降你不知道模型为什么觉得这条序列能工作它也不给你一个可检查的结构中间产物。这会让实验科学家感到不安但从工程角度看准确率比可解释性重要。3. 核心概念RNA 结构层次、逆折叠与端到端设计要把这个领域聊透几个基础概念必须先对齐。RNA 结构分为四个层次结构层次含义举例一级结构核苷酸序列A、C、G、U 的排列二级结构碱基配对形成的局部图案茎环stem-loop、发夹hairpin三级结构整条分子的三维空间折叠假结pseudoknot、A 型螺旋堆叠四级结构RNA 与其他分子形成复合物核糖体 RNA 与蛋白质的组装传统的 RNA 设计目标通常是设计一个能折叠成特定二级结构甚至三级结构的序列这就是逆折叠inverse folding给定一个目标结构找一条能折成该结构的序列。逆折叠问题之所以难是因为序列与结构之间是多对一映射同一个结构可以由无数条不同序列折叠而成但要从中找出既稳定、又有功能、还能被 RNA 聚合酶正常转录出来的那一条搜索空间极大。端到端设计则换了个玩法。它不再要求你先定义结构而是直接给出功能目标比如说我要一条能特异性结合某个蛋白质的 RNA 适体我要一条能调控某个基因表达的核开关riboswitch我要一条在细胞里稳定表达且不触发免疫反应的 mRNA 序列。这些目标都可以直接转成模型的监督信号或优化目标。模型学习的是序列 → 功能的直接映射结构只是中间结果的副产品不需要显式建模。这里有个容易混淆的点端到端设计并不等于不做结构验证。恰恰相反设计完成后实验上仍然需要确认这条 RNA 在真实环境里确实折叠成了有功能的状态。区别在于结构验证不再作为设计流程的输入约束而是作为设计结果的输出检查。4. AI 如何绕过 3D 结构预测技术路线拆解那么AI 具体是怎么做到绕过 3D 结构预测的从当前技术趋势看核心是三类方法在发挥作用。第一类大规模自监督预训练 下游微调。这是最主流的技术路线。研究者用海量天然 RNA 序列来自 Rfam、NCBI 等数据库训练一个大模型训练目标和 NLP 里的掩码语言模型MLM几乎一样随机遮住一些核苷酸让模型预测被遮住的位置。模型在学习过程中会隐式捕获 RNA 的进化保守性、二级结构偏好、密码子使用规律等语言规则。预训练完成后用少量带功能标签的数据微调模型就能学会从序列预测功能或生成有功能的序列。这就是绕过的核心机制模型不需要显式的三维坐标做输入它在自监督训练阶段已经通过海量序列数据把 RNA 的语法学到了隐空间里。第二类生成式模型直接产出候选序列。当前生物序列生成领域扩散模型、变分自编码器VAE和自回归语言模型都有实践。以自回归模型为例它的逻辑和 GPT 生成文本一样逐位置生成核苷酸每个位置的概率分布由前面已生成的序列决定。通过条件控制比如给定目标蛋白序列作为提示模型可以生成针对特定靶标的 RNA 候选序列。这类生成器训练时根本不接触三维结构数据目标函数只关心生成序列在功能评测中的表现。第三类强化学习与实验反馈闭环。纯粹的生成模型一次生成完就结束了但真实场景中我们需要模型从湿实验反馈中持续改进。做法是生成候选序列 → 交付实验验证 → 把实验结果作为奖励信号 → 用强化学习微调生成器。这个闭环最接近真实的科研流程也是端到端精神最彻底的体现——整个系统中没有任何一步需要显式结构预测。三类方法不是互斥的实际研究和论文中往往是叠加使用预训练一个 RNA 语言模型做底座用条件生成产出候选再用实验反馈做强化学习微调。从工程视角看这个技术栈与 NLP 高度重合这也解释了为什么 CSDN 读者能很快上手这个方向你不需要重新学一套完全陌生的工具链它本质上就是大模型 序列数据 领域微调三件套。5. 环境准备与工具链选择如果你也想在这个方向做实验或者只是想跑通一个最小流程验证想法环境准备和工具链并不复杂。下面以 Ubuntu 22.04 Python 3.10 为例版本可以根据实际情况调整核心思路不变。需要准备的内容如下类别工具/库用途Python 环境Python 3.10基础运行环境深度学习框架PyTorch 2.x模型训练与推理序列处理Biopython读取 FASTA、序列格式转换数据结构pandas、numpy数据处理模型加载HuggingFace Transformers使用预训练 RNA 模型可视化matplotlib训练曲线与结果可视化创建虚拟环境并安装依赖# 创建并激活虚拟环境 python -m venv rna_ai_env source rna_ai_env/bin/activate # 安装核心依赖 pip install torch pandas numpy biopython matplotlib pip install transformers # 验证安装 python -c import torch; print(PyTorch:, torch.__version__)安装完成后建议先下载一份公开的 RNA 序列数据作为测试集。Rfam 数据库是 RNA 家族序列的权威来源也可以先从 NCBI 下载小规模的 FASTA 文件做本地实验。不需要在一开始就追求大数据量先跑通流程最重要。这里要提醒一件事不要在未获得授权的情况下下载或使用受版权保护的私有数据库。公开数据库Rfam、NCBI RefSeq通常都没有问题但使用前仍然建议阅读各自的数据库使用条款。6. 最小可运行示例RNA 语言模型与序列生成下面给出一个可以在本地跑通的最小示例。这个示例不是复现 Science 封面论文而是演示序列直通思路的核心机制用自监督方式学习 RNA 序列的分布规律并生成新的候选序列。你可以把它当作一个实验脚手架。6.1 RNA 序列分词器RNA 只有 4 种碱基A、C、G、U所以分词比自然语言简单得多。不过为了兼容预训练模型常见的特殊 token如cls、pad我们仍然要设计一个简单的词表。# 文件路径rna_tokenizer.py class RnaTokenizer: def __init__(self): self.vocab { pad: 0, A: 1, C: 2, G: 3, U: 4, cls: 5, sep: 6, unk: 7 } self.id2token {v: k for k, v in self.vocab.items()} def encode(self, sequence: str) - list[int]: 将 RNA 序列转为 token ID 列表兼容 DNA 输入T 转 U。 seq sequence.strip().upper().replace(T, U) return [self.vocab.get(base, self.vocab[unk]) for base in seq] def decode(self, token_ids: list[int]) - str: 将 token ID 列表转回 RNA 序列去掉特殊 token。 return .join( self.id2token[t] for t in token_ids if t not in (0, 5, 6) # 去掉 pad、cls、sep )这个分词器把所有序列统一为大写并把 DNA 中的 T 转成 RNA 中的 U确保处理 FASTA 数据时不会因为字母差异出错。6.2 一个极简 RNA 语言模型接下来定义一个简单的 Transformer 语言模型。核心思路是输入一段 RNA 序列输出每个位置下一个核苷酸的概率分布。训练目标就是标准的交叉熵损失。# 文件路径rna_lm.py import torch import torch.nn as nn class RnaLanguageModel(nn.Module): def __init__(self, vocab_size8, d_model128, nhead4, num_layers2): super().__init__() self.embedding nn.Embedding(vocab_size, d_model) encoder_layer nn.TransformerEncoderLayer( d_modeld_model, nheadnhead, batch_firstTrue ) self.encoder nn.TransformerEncoder(encoder_layer, num_layersnum_layers) self.output nn.Linear(d_model, vocab_size) def forward(self, x): h self.embedding(x) # [batch, seq_len, d_model] h self.encoder(h) # [batch, seq_len, d_model] logits self.output(h) # [batch, seq_len, vocab_size] return logits这是一个标准的 Transformer encoder-only 语言模型没有用 decoder因为这里我们演示的是序列填空或者下一位置预测都可以直接套用。实际项目中你大概率会直接加载 HuggingFace 上开源的 RNA 预训练模型而不是自己从头训。6.3 训练脚本训练脚本的逻辑很简单从 FASTA 文件里读取序列切成定长片段随机遮住 15% 的 token 让模型预测被遮住的位置。这种训练方式叫掩码语言建模masked language modeling是 RNA 自监督预训练中最常见的目标函数之一。# 文件路径train_rna_lm.py import torch import torch.nn as nn from torch.utils.data import DataLoader, Dataset from rna_tokenizer import RnaTokenizer from rna_lm import RnaLanguageModel class RnaDataset(Dataset): def __init__(self, seqs, tokenizer, max_len64, mask_prob0.15): self.data [tokenizer.encode(s)[:max_len] for s in seqs] self.tokenizer tokenizer self.max_len max_len self.mask_prob mask_prob self.pad_id tokenizer.vocab[pad] def __len__(self): return len(self.data) def __getitem__(self, idx): seq self.data[idx] # 填充到定长 x seq [self.pad_id] * (self.max_len - len(seq)) x torch.tensor(x, dtypetorch.long) labels x.clone() # 随机掩码 mask torch.rand(x.shape) self.mask_prob x[mask] self.tokenizer.vocab[unk] # 用 unk 替代被遮住的碱基 # 只对真实碱基位置计算损失padding 位置不计 labels[~mask] -100 return x, labels # 构造假数据示例实际使用时替换为真实 FASTA 序列 demo_seqs [ AUGCAUGCAUGCAUGCAUGCAUGCAUGCAUGCAUGCAUGCAUGCA, GGCCGGCCGGCCGGCCGGCCGGCCGGCCGGCCGGCCGGCCGGCC, UAAUAAUAAUAAUAAUAAUAAUAAUAAUAAUAAUAAUAAUAAU, CGCGCGCGCGCGCGCGCGCGCGCGCGCGCGCGCGCGCGCGCG ] tokenizer RnaTokenizer() dataset RnaDataset(demo_seqs, tokenizer) loader DataLoader(dataset, batch_size2, shuffleTrue) model RnaLanguageModel() optimizer torch.optim.AdamW(model.parameters(), lr1e-3) loss_fn nn.CrossEntropyLoss(ignore_index-100) model.train() for epoch in range(20): total_loss 0 for x, labels in loader: optimizer.zero_grad() logits model(x) # [batch, seq_len, vocab_size] loss loss_fn(logits.permute(0, 2, 1), labels) loss.backward() optimizer.step() total_loss loss.item() if (epoch 1) % 5 0: print(fepoch {epoch 1}, loss {total_loss / len(loader):.4f})训练完成后可以用模型的输出概率分布做贪婪采样或 temperature 采样生成新的候选 RNA 序列。真实项目中这些候选序列还要经过后续过滤和实验验证。6.4 生成候选序列并做基础检查生成逻辑也很直观给定一个起始 token逐位根据模型输出概率采样下一个碱基直到达到目标长度。# 文件路径generate_candidates.py import torch from rna_tokenizer import RnaTokenizer from rna_lm import RnaLanguageModel def generate_sequence(model, tokenizer, seed_seq, target_len50, temperature0.8): model.eval() ids tokenizer.encode(seed_seq) with torch.no_grad(): for _ in range(target_len - len(ids)): x torch.tensor([ids], dtypetorch.long) logits model(x)[0, -1, :] / temperature probs torch.softmax(logits, dim-1) next_id torch.multinomial(probs, 1).item() ids.append(next_id) return tokenizer.decode(ids) # 加载训练好的模型后调用 # model RnaLanguageModel() # model.load_state_dict(torch.load(rna_lm.pt)) # seq generate_sequence(model, tokenizer, seed_seqAUG)生成的序列要做一个非常基础的可信度检查——至少保证长度、GC 含量在合理范围# 文件路径evaluate_design.py def basic_sequence_check(sequence: str): seq sequence.upper().replace(T, U) length len(seq) gc (seq.count(G) seq.count(C)) / length if length else 0 print(f序列长度: {length}) print(fGC 含量: {gc:.2%}) if length 20: print(警告: 序列过短, 可能难以形成稳定功能结构) if gc 0.3 or gc 0.7: print(提示: GC 含量偏低或偏高, 可能影响结构稳定性) return {length: length, gc_content: round(gc, 3)}以上代码不是直接复现 Science 封面的模型而是把序列直通思想拆解成可运行的最小实现。想要复现更接近论文效果的实验需要用真实的大规模 RNA 序列数据集从头预训练或者加载现成的 RNA foundation model。7. 设计之后的验证为什么绕过不是省略绕过 3D 结构预测容易给人一个错觉RNA 三维结构不重要了。事实并非如此。结构依然重要只是不再作为设计流程的前置输入而是作为设计结果的验证维度。从工程角度看验证环节才是整个 RNA 设计流程里最容易拖垮项目的地方。AI 生成序列的成本几乎为零但实验验证一条 RNA 候选序列是否真的具有预期功能成本可能是百倍千倍地增长。因此设计完之后怎么办成了真正决定项目成败的问题。一条合理的验证路径如下计算层面快速过滤。设计完的候选序列先做基础统计检查长度、GC 含量、重复序列、终止密码子再用轻量级的二级结构预测工具做一致性检查。虽然结构预测不是设计的主驱动但完全和已知结构常识冲突的序列可以直接过滤掉省下实验经费。同源性与保守性分析。把候选序列和已知数据库做比对看它是否与已知功能的 RNA 家族有相似性。相似性高说明设计方向未偏离自然演化规律相似性极低也不一定错但需要更强的解释。体外实验验证。合成少量候选 RNA先做体外实验结合实验测与靶标的结合亲和力、活性实验测核酶活性或基因沉默效率。这一步是决定去留的关键关卡。细胞内有功能验证。通过细胞实验确认 RNA 在真实生物环境中仍然有效。这一步数据最容易失败因为体内环境远比体外复杂存在大量 RNA 结合蛋白、核酸酶等干扰因素。动物模型与临床前验证。针对药物类应用才需要走到这一层。从流程可以看到绕过 3D 结构预测只改变了设计环节本身实验验证一条都不能少。这也是这篇 Science 工作最务实的地方它把 AI 的创造力集中在前端序列生成上后端的验证标准仍然由分子生物学实验说了算。8. 常见误区与排查思路把方向和技术路线都说清楚之后最后聊一聊这个领域最常见的坑。如果你打算在这个方向上做开发下面这些情况大概率会遇到。问题现象可能原因排查方式解决方案生成序列 GC 含量极端偏离训练数据偏好或采样温度过低统计训练集 GC 分布检查采样参数调整采样温度在生成后增加过滤规则模型 loss 下降但生成序列全相似训练数据多样性不足或自回归退化检查训练集序列家族分布统计生成序列多样性扩充数据源引入重复惩罚或蒸馏采样序列能折叠成目标结构但实验无功能二级结构正确但热力学稳定性不够用热力学计算软件检查自由能增加稳定茎区长度优化末端修饰候选序列在细胞内被降解核酸酶敏感位点未被过滤检查常见降解基序引入化学修饰或选择更稳定的结构基序实验验证结果和模型预测差异大训练数据与目标分布不一致检查训练集来源与目标功能的覆盖度收集更接近目标场景的训练数据训练时显存不足序列太长或 batch size 太大查看 GPU 显存占用缩短最大序列长度降低 batch size使用梯度累积这里面最值得展开的是最后一个问题。RNA 序列可以到数千甚至上万碱基Transformer 的注意力机制在长序列上显存开销是平方级的。实际工程中通常的做法是先用短序列50-200 nt做预训练和功能验证跑通流程需要长序列时采用分片训练sequence chunking或使用线性注意力变体生成时采用滑动窗口维持上下文长度可控。另外一个常见的认知误区是觉得AI 生成 结构预测验证就是完整闭环。实际上纯计算验证永远替代不了湿实验。AI 设计的高通量优势只有与自动化实验平台结合才能真正发挥出来。团队里没有湿实验能力时设计结果至少要交到可靠的合作方手里完成一轮体外验证。9. 最佳实践与工程建议结合 RNA 设计方向的特点这里总结几条对软件工程师和算法工程师都适用的实践建议。第一不要从零训练大模型。RNA 领域已有多个开源的大规模预训练模型可用直接基于这些模型做微调效果通常远好于从零训练而且成本低得多。HuggingFace Hub 上搜索 RNA 相关的模型权重大概率能找到可用的基础模型重点看训练数据和下游任务是否覆盖你的场景。第二把评估指标设计成实验友好的。模型训练时用的损失函数是交叉熵但交叉熵低不代表实验通过率高。更好的做法是设计一个复合评分序列合理性分数 与已知功能基序的匹配度 二级结构预测稳定性。这个复合评分要尽量贴近实验验证结果可以用已完成的实验数据不断校准。第三数据管理要严格。RNA 序列数据来源繁杂不同数据库的注释标准不一致序列版本也可能更新。进入训练集之前需要做去重、物种过滤、序列清洗。生产级项目建议为每一条训练数据保留来源追踪信息否则实验失败时你根本没法回溯是哪一批训练数据导致的。第四注意训练集与测试集的泄漏问题。RNA 家族同源性很高如果只是简单随机划分训练集和测试集高度相似的序列会同时出现在两边模型评估结果会虚高。更严谨的做法是按序列家族划分同一 RNA 家族的序列只允许出现在同一侧。第五建立AI 生成 → 计算过滤 → 湿实验验证 → 反馈微调的完整闭环。单次设计成功只是偶然持续迭代才是工程化。每一步的验证结果都要结构化记录作为下一轮模型微调的数据。第六安全和合规边界要提前想清楚。RNA 设计技术具有典型的双用途特性既有巨大的医疗和生物技术价值也存在被滥用的潜在风险。做这个方向的人应当严格遵守所在机构的生物安全规范不向不受控的渠道扩散高风险的合成序列。合成 RNA 序列之前也应该确认合成服务商是否有合规审查流程。10. 总结AI 与 RNA 设计的下一步这篇文章想传递的核心信息可以浓缩为三句话。第一RNA 设计长期被结构预测卡住本质原因是 RNA 三维结构数据稀缺、构象动态显式结构预测这个中间环节成了整条管线的瓶颈。第二Science 封面这篇工作的价值不在于某个具体指标刷新了纪录而在于它验证了一种更普适的方法学思路当中间表示不可靠时端到端学习可以绕过它让模型直接从数据中学习序列与功能之间的映射。第三对开发者来说RNA 设计的 AI 技术栈和 NLP 高度重叠——Transformer、掩码语言建模、生成式采样、强化学习闭环这些都是我们熟悉的工具。真正的门槛不在 AI 算法而在对 RNA 生物学的理解深度以及你是否愿意搭建计算 实验的迭代闭环。如果你对 AI for Science 方向感兴趣RNA 设计是一个绝佳的切入点任务定义清晰、数据体量适中、与产业应用药物研发、疫苗设计、基因编辑直接关联。建议下一步从跑通一两段公开数据的微调流程开始再逐步向自己的靶点场景迁移。这个领域的独特之处在于它允许你同时体会两套体系的美感AI 的端到端简洁与分子生物学的复杂真实。两者之间那个永远充满误差、永不完美的交界地带正是未来几年最值得投入的位置。