“第二届世界科学智能大赛 生命科学赛道:siRNA药物药效预测“第一次笔记#AI夏令营 #Datawhale #夏令营

1. 赛题解析与背景

背景:近年来,mRNA疫苗在新冠预防领域取得巨大成功,推动了核酸类药物的研发。本次比赛的任务是利用机器学习和深度学习技术,预测化学修饰后的siRNA序列在RNA干扰(RNAi)机制下对靶基因的沉默效率。

数据:数据集包括公开文献中的siRNA修饰序列及实验条件,分为85%的训练集和15%的验集。复赛增加未公开专利数据以评估模型在新靶基因上的预测能力。

2. 必知概念入门

RNA干扰(RNAi):一种基因表达调控机制,通过siRNA等分子沉默特定基因。其在基因治疗和疾病治疗中具有广泛应用。

化学修饰siRNA:通过化学修饰增强siRNA的稳定性、靶向性和有效性,常见修饰包括磷酸酯骨架修饰、核苷酸修饰等。

深度学习与RNN:深度学习擅长处理复杂数据,RNN特别适合处理序列数据,能捕捉时间依赖关系。

词汇表与序列编码:将核酸序列转换为数值表示,以便输入模型。使用3-gram词汇表捕捉局部模式。

数据处理与特征选择:包括数据清洗、去除缺失值和异常值,以及选择最能代表数据特征的字段。

模型训练与评估:通过优化算法调整模型参数,常用评估指标包括均方误差(MSE)、平均绝对误差(MAE)、精确率(Precision)和召回率(Recall)。

PyTorch框架:一个开源的深度学习框架,支持灵活的动态计算图,广泛用于研究和生产环境。

3. 我的关于赛题的思考:生物与AI的奇妙碰撞

生物背景知识:细胞的静音模式

在生物界,有一种非常有趣的现象叫做RNA干扰(RNAi),就像按下了基因的“静音键”,让特定基因不再发声。小干扰RNA(siRNA)就是这个“静音键”的操作员。siRNA能锁定目标基因,把它们“闭嘴”的能力用在基因治疗上简直是一绝。2018年,全球首个siRNA药物Patisiran成功上市,这不仅是科研界的一大步,也是患者们的福音。

AI与制药:打破“双十定律”的魔法

药物研发界流传着一个不太友好的“双十定律”:从药物研发到上市,得花上十年时间和十亿美元。AI的出现给了这个古老定律一记漂亮的反击。比如,AI能在海量的化合物中找到潜在的药物分子,就像在草堆里找针一样,但AI的效率高得多。此外,AI还能优化临床试验设计,简直就是制药界的魔法师!看看英矽智能的例子,他们用AI设计的药物INS018_055,从发现到进入人体临床试验仅用了18个月,这速度,简直像是开启了“快进键”。

AI在生命科学中的超级应用

AI在生命科学中的表现简直就是超级英雄级别的。以下是几个AI的经典技能:

  1. 药物发现:传统药物研发就像是大海捞针,而AI的加入让这个过程像装上了金属探测器,不仅快还准。AI可以预测化合物的药效和毒性,把不靠谱的选项直接筛掉,省时又省钱。

  2. 基因组学:AI在基因组学中就像一台超级计算机,能够分析海量的基因数据,找出基因与疾病之间的关系。通过这种方式,个性化医疗已经不再是科幻小说里的情节。

  3. 医学影像分析:医生们靠AI帮忙看X光、CT、MRI就像多了一双火眼金睛。AI能自动检测早期疾病的征兆,比如癌症,减少医生的工作量,还能让诊断更准确。

  4. 蛋白质结构预测:蛋白质的结构决定了它的功能,而预测蛋白质结构一直是生物学中的一大难题。DeepMind的AlphaFold用AI突破了这个瓶颈,提供了精确的蛋白质结构预测,这对药物设计和疾病研究都有重大意义。

  5. 免疫疗法:AI还能在免疫疗法中发挥作用,特别是癌症治疗。通过分析肿瘤细胞和免疫细胞的互动,AI帮助优化治疗方案,提高了治疗效果,减少了副作用

AI和生物科技的结合正在重新定义我们对健康和疾病的理解。未来,随着技术的不断进步,我们可能会看到更多意想不到的突破。就像这次比赛一样,AI帮助我们更好地理解和设计siRNA,让精准医疗不再只是梦想,而是触手可及的现实。

4. baseline重要代码解读

class GenomicTokenizer:
    def __init__(self, ngram=5, stride=2):
        # 初始化分词器,设置n-gram长度和步幅
        self.ngram = ngram
        self.stride = stride
        
    def tokenize(self, t):
        # 将输入序列转换为大写
        t = t.upper()
        
        if self.ngram == 1:
            # 如果n-gram长度为1,直接将序列转换为字符列表
            toks = list(t)
        else:
            # 否则,按照步幅对序列进行n-gram分词
            toks = [t[i:i+self.ngram] for i in range(0, len(t), self.stride) if len(t[i:i+self.ngram]) == self.ngram]
        
        # 如果最后一个分词长度小于n-gram,移除最后一个分词
        if len(toks[-1]) < self.ngram:
            toks = toks[:-1]
        
        # 返回分词结果
        return toks

代码解读

  1. 类初始化:__init__ 方法接受两个参数 ngram 和 stride,用于设置分词器的 n-gram 长度和步幅。
  2. 分词方法:tokenize 方法将输入的序列转换为大写,并根据 ngram 和 stride 对序列进行分词。
  3. n-gram 长度为 1 的处理:如果 ngram 为 1,直接将序列转换为字符列表。
  4. n-gram 长度大于 1 的处理:按步幅进行分词,并确保每个分词的长度等于 ngram
  5. 最后一个分词的处理:如果最后一个分词长度小于 ngram,将其移除。
  6. 返回分词结果:返回处理后的分词结果列表。
class GenomicVocab:
    def __init__(self, itos):
        # 初始化词汇表,itos是一个词汇表列表
        self.itos = itos
        # 创建从词汇到索引的映射
        self.stoi = {v: k for k, v in enumerate(self.itos)}
        
    @classmethod
    def create(cls, tokens, max_vocab, min_freq):
        # 创建词汇表类方法
        # 统计每个token出现的频率
        freq = Counter(tokens)
        # 选择出现频率大于等于min_freq的token,并且最多保留max_vocab个token
        itos = ['<pad>'] + [o for o, c in freq.most_common(max_vocab - 1) if c >= min_freq]
        # 返回包含词汇表的类实例
        return cls(itos)

代码解读

  1. 类初始化:__init__ 方法接受一个参数 itos,它是一个词汇表列表。

    • itos:从索引到词汇的映射。
    • stoi:从词汇到索引的映射,由 itos 列表生成。
  2. 类方法 create:创建词汇表的类方法,用于生成 GenomicVocab 类的实例。

    • 参数:
      • tokens:所有token的列表。
      • max_vocab:词汇表的最大容量。
      • min_freq:词汇在被包含到词汇表中的最低频率。
    • 步骤:
      • 统计 tokens 中每个token出现的频率。
      • 按照频率从高到低排序,并选择出现频率大于等于 min_freq 的token,最多保留 max_vocab 个。
      • 在词汇表中添加一个特殊的 <pad> token,用于填充序列。
      • 返回包含生成的 itos 列表的 GenomicVocab 实例。
class SiRNAModel(nn.Module):
    def __init__(self, vocab_size, embed_dim=200, hidden_dim=256, n_layers=3, dropout=0.5):
        super(SiRNAModel, self).__init__()
        
        # 初始化嵌入层
        self.embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=0)
        # 初始化GRU层
        self.gru = nn.GRU(embed_dim, hidden_dim, n_layers, bidirectional=True, batch_first=True, dropout=dropout)
        # 初始化全连接层
        self.fc = nn.Linear(hidden_dim * 4, 1)  # hidden_dim * 4 因为GRU是双向的,有n_layers层
        # 初始化Dropout层
        self.dropout = nn.Dropout(dropout)
    
    def forward(self, x):
        # 将输入序列传入嵌入层
        embedded = [self.embedding(seq) for seq in x]
        outputs = []
        
        # 对每个嵌入的序列进行处理
        for embed in embedded:
            x, _ = self.gru(embed)  # 传入GRU层
            x = self.dropout(x[:, -1, :])  # 取最后一个隐藏状态,并进行dropout处理
            outputs.append(x)
        
        # 将所有序列的输出拼接起来
        x = torch.cat(outputs, dim=1)
        # 传入全连接层
        x = self.fc(x)
        # 返回结果
        return x.squeeze()
    

代码解读

  1. 初始化方法 __init__

    • vocab_size:词汇表大小,用于嵌入层。
    • embed_dim:嵌入维度,嵌入层将词汇映射为 embed_dim 维向量。
    • hidden_dim:隐藏层维度,GRU的隐藏状态维度。
    • n_layers:GRU的层数。
    • dropoutDropout层的丢弃率,用于防止过拟合。

该方法初始化了模型的各层,包括嵌入层GRU层全连接层Dropout层

  1. 前向传播方法 forward

    • 将输入序列传入嵌入层进行词汇嵌入。
    • 对每个嵌入的序列进行GRU处理,提取最后一个隐藏状态并进行Dropout处理。
    • 将所有处理后的序列输出拼接起来,并传入全连接层。
    • 返回经过全连接层后的结果。
def calculate_metrics(y_true, y_pred, threshold=30):
    # 计算平均绝对误差
    mae = np.mean(np.abs(y_true - y_pred))

    # 将实际值和预测值转换为二进制分类(低于阈值为1,高于或等于阈值为0)
    y_true_binary = (y_true < threshold).astype(int)
    y_pred_binary = (y_pred < threshold).astype(int)

    # 创建掩码,用于筛选预测值在0和阈值之间的样本
    mask = (y_pred >= 0) & (y_pred <= threshold)
    range_mae = mean_absolute_error(y_true[mask], y_pred[mask]) if mask.sum() > 0 else 100

    # 计算精确度、召回率和F1得分
    precision = precision_score(y_true_binary, y_pred_binary, average='binary')
    recall = recall_score(y_true_binary, y_pred_binary, average='binary')
    f1 = 2 * precision * recall / (precision + recall)

    # 计算综合评分
    score = (1 - mae / 100) * 0.5 + (1 - range_mae / 100) * f1 * 0.5

    return score

代码解读

  1. 计算平均绝对误差 (MAE):

    mae = np.mean(np.abs(y_true - y_pred)):计算实际值和预测值之间的平均绝对误差
  2. 将实际值和预测值转换为二进制分类:

    • y_true_binary = (y_true < threshold).astype(int):如果实际值小于阈值,设为1,否则设为0
    • y_pred_binary = (y_pred < threshold).astype(int):如果预测值小于阈值,设为1,否则设为0
  3. 创建掩码:

    • mask = (y_pred >= 0) & (y_pred <= threshold):筛选预测值0阈值之间的样本。
    • range_mae = mean_absolute_error(y_true[mask], y_pred[mask]) if mask.sum() > 0 else 100:计算这些样本的平均绝对误差,如果没有符合条件的样本,设为100
  4. 计算精确度、召回率和F1得分:

    • precision = precision_score(y_true_binary, y_pred_binary, average='binary'):计算精确度。
    • recall = recall_score(y_true_binary, y_pred_binary, average='binary'):计算召回率。
    • f1 = 2 * precision * recall / (precision + recall):计算F1得分。
  5. 计算综合评分:

    score = (1 - mae / 100) * 0.5 + (1 - range_mae / 100) * f1 * 0.5:综合MAE、范围内的MAE和F1得分,计算最终评分。
  6. 返回评分:

    return score:返回综合评分。

5. 深度学习知识复习

见顶部资源。

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值