
现代 RNA 设计中一个长期绕不开的瓶颈是三维结构预测先推断结构再依据结构反推序列。近期一项登上《Science》封面的研究展示了一条完全不同的路径——让 AI 绕过 3D 结构预测直接从序列与功能的关系中学习 RNA 设计。这个思路对 AI4Science、药物研发和生物信息学的人来说都很有价值。本文以这一研究为背景拆解“绕过结构预测”的设计哲学并给出一个可以落地的 AI 驱动的 RNA 序列设计工作流从环境准备、数据组织、模型训练到候选序列搜索、实验前验证和失败排查。即使不从事结构生物学也能从中理解端到端学习方法在分子设计里的应用逻辑。1. RNA 设计为什么长期卡在 3D 结构预测这一环1.1 RNA 设计的本质是从功能推导序列RNA 设计任务通常可以这样描述给定一个目标功能例如“RNA 能特异性结合某个蛋白质”或“RNA 在特定环境下发生构象切换”设计者需要输出一段 RNA 序列使得它在体外或细胞内达到预期效果。这本质上是一个逆问题功能空间到序列空间是多对多的映射。同一个功能可能对应大量不同的序列而不同序列的折叠路径、热稳定性、细胞内的降解速率和翻译起始能力又完全不同。设计者真正需要找的不是任意一条可行序列而是在表达量、特异性、合成成本、实验可重复性等多个指标上都足够好的序列。传统计算设计流程通常把这个逆问题拆成两步。先预测 RNA 的三维结构也就是正向建模再根据预测出的空间结构设计出能折叠成该结构的序列也就是结构逆向设计。这个思路听起来很完整实际执行时会发现每一步都存在误差而误差会在串联流程中被不断放大。1.2 传统流程把 3D 结构当作不可跳过的中间变量传统 RNA 设计流程可以分为四个环节功能定义明确 RNA 需要满足的结合面、构象变化或能量特征。结构建模通过同源建模、分子动力学或深度学习预测 RNA 的三维结构。序列逆向折叠在给定结构骨架的前提下搜索能稳定折叠成该结构的碱基序列。实验验证通过 gel shift、荧光报告系统、体内成像等方法确认设计是否工作。3D 结构预测在这里被当作“不可跳过的中间变量”。结构准确度直接决定后续序列搜索的起点。如果结构模型里某个环区摆位错误后续所有序列都会建立在一个错误的几何关系上。RNA 结构预测比蛋白质结构预测更困难。RNA 骨架柔性高非经典碱基配对、假结、碱基堆积和金属离子配位都会显著影响三维构象。现有的实验解析结构数量远低于蛋白质深度学习模型能学习到的结构先验也相对稀缺。结果就是即便用当前最先进的结构预测工具对某些长链非编码 RNA 或动态复合物的预测置信度仍然有限。1.3 结构预测本身的不确定性会向下传递传统流程里最容易被低估的问题是误差传播。假设 3D 结构预测的准确率是 85%逆向折叠的准确率是 80%两步相乘后的整体成功率就只有 68%。这还只是理想估计。如果目标 RNA 存在多种瞬态构象预测给出一套结构实验里实际存在的是另一套结构后续优化就会完全失去方向。更重要的是结构预测并不是设计任务的最终指标。设计者真正关心的是“这条序列在细胞里能不能结合目标蛋白、能不能执行功能”而不是“它折叠成什么角度”。结构只是功能的一个代理指标。代理指标越间接模型引入的偏差就越大。正因为存在这些问题研究者和工程师开始思考一条更直接的路径能否训练一个模型输入目标蛋白特征和候选 RNA 序列直接输出功能效应分数从而完全绕开中间的结构建模步骤这正是《Science》封面研究所展示的核心思想。关键判断绕开 3D 结构预测不等于忽略了结构信息而是让模型自己从序列中学习与功能相关的结构约束。结构信息仍然存在只是不再需要被显式解出来。2. “绕过 3D 结构预测”的设计思路到底在做什么2.1 从“结构中间变量”转向“序列到功能端到端映射”如果训练数据足够多模型可以直接学习“RNA 序列 靶蛋白序列 - 结合强度”的映射关系。设计过程变成输入目标蛋白的序列或特征编码。输出候选 RNA 序列的功能评分。反向优化在序列空间中进行搜索找到评分足够高的候选序列。这种端到端思路在图像、语音和自然语言处理中已经被验证过。只要模型容量够大、数据分布覆盖足够广很多手工设计的中间特征其实是多余的。RNA 设计同样如此。模型在训练时看到大量“序列-功能”配对样本后会隐式地学习到哪些碱基组合能够形成稳定的局部结构、哪些 motif 有利于结合蛋白甚至能学到与修饰、降解相关的序列规律。这些知识并不以三维结构的形式呈现但最终效果比显式预测结构再反向设计更稳健。2.2 模型输入与输出的工程化组织方式具体到工程实现一次端到端的 RNA 设计通常需要组织三类数据。数据字段含义示例protein_seq目标蛋白氨基酸序列MTVKT...rna_seq候选 RNA 序列AUGCCGGU...target_value功能标签可以是结合强度、荧光强度、翻译抑制率等0.87condition实验条件或细胞类型可选HEK293Tsplit训练集/验证集/测试集标记train模型不是直接吃字符串而是先把蛋白序列和 RNA 序列编码成数值特征。蛋白质序列可以使用预训练蛋白语言模型的 embedding 作为输入特征RNA 序列可以同时使用 one-hot 编码和 k-mer 特征也可以让模型从字符级直接学习。输出层通常有两种设计。第一种是回归头输出一个连续分数例如 predicted KD 或 binding probability。第二种是分类头输出“有效/无效”两个类别适用于实验数据里只有通过/未通过标签的场景。2.3 为什么模型可以“看不见结构却利用结构”这里有一个关键问题需要解释模型从未显式查看 3D 坐标它怎么学得会结构规律原因在于RNA 的二级结构信息在很大程度上可以从序列中推断。GC 含量、配对倾向、茎环周围的序列上下文、GNRA 四环 motif、单链区域的长度分布这些因素都会影响 RNA 的实际空间构象。深度学习模型只要见过足够多的真实序列就能把这些序列特征与功能标签之间的隐式关联捕捉出来。在训练良好的情况下模型内部其实形成了与结构和结合能力相关的表征。它可能不是一份坐标文件而是一个高维向量空间中的方向。这个方向对应着“可折叠、可结合”的序列特征。设计者不需要看到这个方向只需要沿着这个方向搜索序列即可。这就是“绕过 3D 结构预测”的本质不是抛弃结构知识而是把结构知识内化到模型权重中直接为用户需要的功能结果服务。3. 搭建一套可落地的 AI RNA 序列设计工作流3.1 环境准备与依赖选择动手之前先明确一点端到端 RNA 设计是一个计算密集任务实际生产环境至少需要一块支持 CUDA 的 NVIDIA GPU。纯 CPU 环境可以跑通小规模 demo但无法完成整条序列搜索。推荐使用 conda 管理 Python 环境避免系统依赖污染。conda create -n rna-design python3.10 -y conda activate rna-design pip install torch --index-url https://download.pytorch.org/whl/cu121 pip install pandas numpy scikit-learn hydra-core pip install viennarna项目基础依赖如下依赖库作用PyTorch构建和训练深度学习模型pandas / numpy数据处理与特征转化scikit-learn数据划分、评估指标计算hydra-core管理多组超参数配置ViennaRNA二级结构预测用于设计后的快速过滤ViennaRNA 是一个传统但非常实用的小工具它并不是深度学习模型而是基于热力学最小自由能预测 RNA 二级结构。它可以作为设计候选序列的第一道过滤器。3.2 数据准备与预处理训练数据是端到端设计模型的核心资产。数据来源可能包括公开数据库、高通量实验数据、文献补充材料以及自有实验数据。一份最小数据集可以保存为 CSV 文件protein_seq,rna_seq,target_value,condition MTVKTGGGGG,AUGCCGGUAAAC,0.72,HEK293 MTPQKLLL,AUGGCUUAGCGA,0.45,HEK293 MTVRMKKGG,CCGGUUAAGGCC,0.91,Hela读入数据后需要完成三件事清洗异常字符。RNA 序列只保留 A、U、G、C其他字符直接过滤或按 N 处理。长度截断。RNA 长度可能从几十到几千不等为了模型训练稳定可以截断到固定长度例如 128 或 256。归一化标签。如果标签值范围差异很大先做 min-max 归一化或 z-score。预处理代码可以这样写import pandas as pd import numpy as np def clean_rna(seq: str) - str: seq seq.upper() seq .join([c for c in seq if c in AUCG]) return seq def clean_protein(seq: str) - str: seq seq.upper() seq .join([c for c in seq if c in ACDEFGHIKLMNPQRSTVWY]) return seq def load_dataset(path: str): df pd.read_csv(path) df[rna_seq] df[rna_seq].apply(clean_rna) df[protein_seq] df[protein_seq].apply(clean_protein) df df[(df[rna_seq].str.len() 20) (df[rna_seq].str.len() 256)] return df这里要注意RNA 序列和蛋白质序列的字符表不一样清洗逻辑必须分开。RNA 使用 U蛋白质使用 C这是一个很容易踩的坑。3.3 训练一个简化版序列评分模型为了说明整个工作流的输入输出结构下面给出一个简化模型。它不用于复现任何论文结果而是帮助理解端到端设计的数据流输入两条序列输出一个分数。import torch import torch.nn as nn RNA_ALPHABET {A: 0, U: 1, G: 2, C: 3, N: 4} def encode_rna(seq: str, max_len: int 128) - torch.Tensor: seq seq[:max_len].ljust(max_len, N) indices [RNA_ALPHABET.get(c, 4) for c in seq] return torch.tensor(indices, dtypetorch.long) class RnaScorer(nn.Module): def __init__(self, vocab_size5, hidden_dim64, num_layers2): super().__init__() self.embed nn.Embedding(vocab_size, hidden_dim) self.lstm nn.LSTM(hidden_dim, hidden_dim, num_layersnum_layers, batch_firstTrue) self.fc nn.Sequential( nn.Linear(hidden_dim, 32), nn.ReLU(), nn.Linear(32, 1) ) self.sigmoid nn.Sigmoid() def forward(self, x): x self.embed(x) out, _ self.lstm(x) out out[:, -1, :] score self.sigmoid(self.fc(out)) return score model RnaScorer() sample_seq AUGCCGGUAAACUUAG x encode_rna(sample_seq).unsqueeze(0) score model(x) print(score)LSTM 在这里只用于处理变长序列依赖。实际项目可以替换成 Transformer encoder并加入蛋白质序列的交叉注意力模块。但无论模型结构怎么变“序列进、分数出”的主干不会变。训练循环采用标准的二分类或回归损失criterion nn.BCELoss() optimizer torch.optim.AdamW(model.parameters(), lr1e-3) for epoch in range(epochs): model.train() for batch_x, batch_y in dataloader: pred model(batch_x) loss criterion(pred, batch_y) optimizer.zero_grad() loss.backward() optimizer.step()当训练完成后模型就可以用来对新的候选序列进行快速打分。3.4 候选序列搜索从随机突变到遗传算法有了评分模型还需要一个序列搜索器来探索序列空间。最直接的方法是随机突变从一个已知有效序列出发随机改变若干碱基模型重新打分保留得分高的序列。一个简单的遗传算法实现如下import random def random_mutate(seq: str, rate: float 0.15) - str: bases [A, U, G, C] changed [] for b in seq: if random.random() rate: b random.choice(bases) changed.append(b) return .join(changed) def design_rounds(model, start_seq, rounds200, keep_top8): candidates [(0.0, start_seq)] for _ in range(rounds): parent random.choice(candidates)[1] child random_mutate(parent) x encode_rna(child).unsqueeze(0) score model(x).item() candidates.append((score, child)) candidates.sort(reverseTrue) candidates candidates[:keep_top] return candidates[0][1]这个搜索过程虽然简单但在序列空间较小的短链 RNA 上有一定效果。更复杂的搜索可以引入约束要求保持某个茎区的配对、不允许出现连续 5 个相同碱基、限制 GC 含量范围。这些约束需要在随机突变和模型评分之间同时施加。4. 关键参数与工程化设计细节4.1 模型结构参数速查参数默认建议调大影响调小影响hidden_dim64表达能力强但易过拟合、显存增加训练更快但拟合不足num_layers2可学习长距离依赖但训练变难训练稳定但长距离建模弱max_len128支持更长序列但增加计算量丢失长序列尾部信息dropout0.1降低过拟合但可能欠拟合训练集精度高但泛化差learning_rate1e-3收敛快但不稳定稳定但收敛慢这些参数不是固定值不同数据集规模下需要重新调优。数据量较小时建议优先降低 hidden_dim 和 num_layers并使用单层 LSTM 或浅层 Transformer。4.2 数据增强与样本均衡RNA 实验数据常常存在严重的标签不平衡通过实验的序列远少于失败的序列。直接训练会让模型倾向输出低分数所有候选序列都会被拒绝。处理方式有三种负样本欠采样仅保留与正样本数量接近的负样本。正样本过采样复制或对正样本进行同义突变增强。使用加权损失给少数类更高的损失权重。同义突变增强要特别小心。RNA 不像蛋白质有明确的密码子简并性但可以改变非关键区域的碱基。例如保持二级结构茎区配对的同时把 G-C 换成 C-G 仍可能维持配对。这里需要用 ViennaRNA 检查突变前后的最小自由能变化。4.3 设计入口的完整管道示例把所有组件串起来一个最小可运行的设计入口可以写成def run_pipeline(model, target_rna_start, output_num10): best [] for i in range(100): seq design_rounds(model, start_seqtarget_rna_start) if vienna_rna_free_energy(seq) -15: best.append(seq) best list(set(best)) return best[:output_num]实际项目中还需要在这里加入日志记录、断点保存、实验结果回传和模型版本管理。推荐使用 MLflow 记录每次训练和序列搜索的中间结果方便后续复现。5. 如何在实验前提高设计成功率5.1 用二级结构预测做第一轮过滤AI 模型输出分数后不要直接送去合成。先用 ViennaRNA 的 RNAfold 检查候选序列的二级结构echo AUGCCGGUAAACUUAGG | RNAfold --noPS关注两个指标最小自由能和结构熵。自由能过高的序列通常折叠不稳定可能无法形成预期结构。结构熵高说明相同序列在热力学上存在多种几乎等概率的构象这会导致功能结果不稳定。指标参考范围说明最小自由能 dG-20 到 -60 kcal/mol绝对值越大越稳定结构熵越小越好熵大表示构象多样性高配对碱基占比40% 到 70%过低难成结构过高可能缺乏功能柔性区5.2 序列多样性与副反应控制AI 模型很容易掉进局部最优候选序列之间可能只差一两个碱基。这种情况下的实验并不是验证“设计是否成功”而是在验证“模型的局部邻域是否有效”。建议对最终候选序列做聚类保证每类结构 motif 对应的序列不超过一个。同时过滤掉两类风险序列连续相同碱基超过 6 个以及 poly-A 过长因为这类序列在化学合成和细胞内传递时容易出现异常。5.3 体外实验验证清单合成前需要准备一份验证清单是否设置了阳性对照和阴性对照而不仅仅是待测序列。是否在不同浓度下检测结合曲线而不只是单点荧光值。是否对同一序列合成了至少两个重复以排除合成批次差异。是否保存了原始测序结果以便后续排查合成错误。是否记录了实验条件包括温度、离子浓度、细胞传代数。注意不要把“模型分数高”当成实验成功的证据。模型分数是搜索排序依据真正的成功标准是实验表型数据。设计闭环必须包含“实验反馈 - 增量训练 - 下一轮设计”。6. 常见问题与排查路径6.1 问题总览表问题现象常见原因检查方式处理建议模型预测分数很高但实验无功能训练数据与该目标蛋白分布差异大检查目标蛋白序列相似度收集域内数据微调模型候选序列全部集中在同一区域遗传算法陷入局部最优计算候选序列平均编辑距离增大突变率增加多样性奖励模型训练损失不下降序列字符表混乱或标签归一化错误检查预处理数据样例清洗字符、重做标签归一化结构过滤后没有候选序列模型没学到二级结构约束对比模型分数与 dG 相关性在训练损失中加入二级结构约束项相同输入两次运行结果不同缺少随机种子检查代码 seed 设置固定 set_seedGPU OOM序列过长或 batch 过大查看错误日志降低 max_len 或 batch_size6.2 模型分数与实验趋势不一致的排查顺序这是实际项目里最常遇到的问题。如果模型在验证集上表现不错但实验成功率和模型分数完全不对应按以下顺序排查确认实验标签是否可靠。如果训练集里的正负标签来自不同实验批次或不同时间批次效应会污染模型。确认序列清洗是否保留关键 motif。某些稀有碱基对应区域被当成噪声过滤后模型可能丢失重要信号。确认目标蛋白和训练数据中的蛋白是否有同源性。零样本跨蛋白设计很难只靠一个小模型。确认对照组序列是否真的无效。如果阴性对照也有功能说明实验体系本身无法区分有效与无效。最后才怀疑模型结构。不要一开始就调大 hidden_dim这样只会加剧过拟合。6.3 结构约束与结合分数互相冲突的处理当模型认为某条序列结合分数很高但 ViennaRNA 显示它无法折叠成稳定结构时问题通常出在训练数据没有覆盖“稳定折叠”这一约束。解决方式有两种。第一种是在候选序列生成阶段直接加入结构打分项def combined_score(model_score, dg, alpha0.7): return alpha * model_score - (1 - alpha) * dg / 20第二种是重新组织训练数据把二级结构信息作为额外特征输入模型例如给每条 RNA 追加一个由 RNAfold 生成的剖面向量。让模型在训练时就知道结构的概率分布而不是事后才发现结构不合理。7. 最佳实践与扩展方向7.1 学习环境与生产环境的分层设计在本地学习环境中可以先用几百条公开数据跑通流程重点理解“序列进、分数出、搜索序列”的循环。此时不需要大规模 GPU也不需要完整的生物实验闭环。进入生产环境后还需要补上几层能力配置外置化模型参数、数据路径、实验条件全部通过配置文件管理而不是硬编码在脚本里。日志与监控记录每次训练的数据版本、模型版本、搜索轮次和候选序列方便追溯。自动回滚如果实验反馈显示模型性能下降要能快速回退到上一个经过实验验证的模型版本。安全与权限涉及人类样本或医学相关序列时数据访问和模型推理都要有审计记录。增量学习每完成一轮体外实验把新数据加入训练集定期微调模型形成“设计-验证-再设计”的持续优化闭环。7.2 可复用的设计原则清单把本文的工程经验压缩成一份可执行清单先清洗数据再处理标签最后才调模型结构。不要把 3D 结构预测和序列设计当成必须串联的步骤。用二级结构预测作为快速过滤器但不要用它替代功能标签。搜索阶段加入多样性指标避免候选序列集中在同一局部区域。每次实验后把反馈回灌给模型这是整个工作流中最容易忽略的环节。所有序列和分数都要加版本号否则一轮失败后很难定位是哪一步引入的问题。使用 GPU 时固定随机种子确保相同输入可以得到可复现输出。7.3 下一步扩展方向端到端 RNA 设计目前还处在快速发展阶段。对关注这一方向的开发者来说有四个方向值得深入第一把生成模型引入序列搜索。扩散模型和流匹配已经在蛋白质设计领域被验证RNA 设计同样可以使用生成模型直接在序列分布上采样替代遗传算法。第二让模型同时学习多种功能标签。一条 RNA 往往对应多个属性比如稳定性、结合特异性、翻译效率、细胞毒性等。多任务学习可以让模型学习这些属性之间的共享规律。第三引入蛋白语言模型表示。与其只使用蛋白质原始序列编码不如用预训练蛋白模型提取的 embedding 作为条件输入增强模型对外部蛋白的理解。第四建立更好的统一评测基准。当前 RNA 任务的数据来源分散公开数据集规模也小。未来谁能把数据、评估流程和基线模型标准化谁就能进一步推动这个方向落地。《Science》封面研究真正值得学习的地方不是某个具体模型结构而是一套方法学立场当中间变量不可靠时可以直接从数据中学习输入到输出的映射。这种绕过显式中间建模的思路在 RNA 设计里成立在更广泛的 AI4Science 领域同样成立。对开发者来说最值得做的就是先跑通一条最小闭环然后用真实数据不断迭代。最后提醒设计类 AI 模型的训练效果高度依赖数据质量。与其花大量时间优化模型结构不如先把数据清洗、标签校验和实验反馈这三件事做扎实它们对最终设计成功率的贡献通常比模型结构更大。