Datawhale Al夏令营——siRNA药物药效预测背景与Baseline

基本背景

目的

RNAi是生物体内天然存在的一种基因表达调控机制,通过抑制靶基因的表达来实现降低目标蛋白量的目的,这一机制一般可通过siRNA实现。本研究期望聚焦于通过机器学习技术,利用化学修饰后的siRNA序列来预测RNA干扰(RNAi)机制下对靶基因(target gene)的沉默效率,这一指标与药物实际疗效直接相关。

面临挑战

目前开源的数据库中,以RNA主干序列(裸序列)为主,缺少相应的化学修饰数据。而化学修饰对siRNA的毒性、体内稳定性、靶向效果、药效等具有重大影响,在实际药物设计中至关重要

原始资料

修饰后的siRNA数据非常稀缺,仅siRNAmod数据库包含4894条siRNA修饰序列。

基本数据集是通过对公开文献信息进行系统的整理、清洗、归一化后产生的,对多套化学修饰、细胞系、转染方式表达体系进行了统一整合,确保了数据的正确性、独特性和高应用价值,且数据量提升了1个数量级。

测试数据集由大睿生物提供部分尚未公开专利的siRNA修饰序列数据。

训练数据

train_data.csv

train_data.csv的每行为一条训练记录,包含数据记录的id、siRNA裸序列、相应的siRNA修饰序列、目标mRNA序列、siRNA浓度、细胞系、转染方法等实验室条件以及对应的实验室测量的mRNA Remaining值等总计19个字段。其中mRNA Remaining值为模型训练目标,其余18个字段的全部或部分可以作为模型的输入特征。

Remaining值代表了经过siRNA的沉默之后,mRNA的剩余百分比(相对于对照组)。Remaining值越低,siRNA的沉默效率越好,药效就越好。Remaining值一般位于0-100的区间内,100表示完全没有沉默效果,0表示该mRNA被彻底沉默,但是由于实验室测量的误差,可能存在少量训练记录的mRNA Remaining值在这个范围之外,这是正常的数据。

表头含义一览表:

表头字段 表头说明
id 数据唯一识别号
--- ---
publication_id 公开文献号,已经过脱敏处理
gene_target_symbol_name 靶基因符号名称,靶基因即为siRNA想要沉默的目标基因
gene_target_ncbi_id 靶基因的NCBI标识
gene_target_species 靶基因参考序列的物种,一般物种应为人类
siRNA_duplex_id siRNA双链编号
siRNA_sense_seq siRNA的sense序列
siRNA_antisense_seq siRNA的antisense序列
cell_line_donor 实验使用的细胞系,一般认为对沉默效率测定存在较大影响
siRNA_concentration 实验使用的siRNA浓度,一般认为对沉默效率测定存在较大影响
concentration_unit siRNA浓度单位,比如nM
Transfection_method 转染方法,即将siRNA植入细胞的方法,一般认为对沉默效率测定存在较大影响
Duration_after_transfection_h 转染后持续时间(小时)
modified_siRNA_sense_seq 带修饰的siRNA的sense序列
modified_siRNA_antisense_seq 带修饰的siRNA的antisense序列
modified_siRNA_sense_seq_list 带修饰的siRNA的sense序列分解列表,基于标准词表将sense序列分解,以空格分隔
modified_siRNA_antisense_seq_list 带修饰的siRNA的antisense序列分解列表,基于标准词表将antisense序列分解,以空格分隔
gene_target_seq 靶基因的参考序列,siRNA一般靶向序列中的一部分片段以达到沉默的效果
mRNA_remaining_pct 实验后mRNA的剩余百分比

sample_submission.csv

sample_submission.csv为初赛的leaderboard submission测试集,格式与初赛训练集train_data.csv相同。不同之处在于mRNA_remaining_pct列的数值为空,参赛者需要填充这些空白处的预测结果后提交。

"leaderboard submission测试集" 指的是一个特定的数据集,它用于评估参赛者在某个竞赛中的表现。

vocab.csv(经过归一化后的siRNA化学修饰缩写表)

第一列(Abbreviation):列出了各种修饰核苷酸的缩写。
第二列(Chemical Name):展示了与第一列中缩写对应的完整化学名称。这些化学名称详细描述了核苷酸的结构,包括对其进行的化学修饰。这些修饰可能涉及改变核苷酸的糖部分、磷酸基团或碱基,以增强其性能,如提高稳定性或特定的生物活性。

样例数据

Abbreviation Chemical Name
A adenosine-3'-phosphate
--- ---
C cytidine-3'-phosphate
G guanosine-3'-phosphate

baseline.py

本次比赛提供一个基础的基线方法,利用 RNN 来预测Remaining值。基线方法中我们仅使用了siRNA_sense_seq 字段作为特征,除此之外尚有其他特征对Remaining结果有重大影响。

评价指标

本次任务采用3个指标来进行评测

  1. 平均绝对误差(MAE):平均绝对误差是对每个样本的绝对误差取平均值,主要用于衡量模型在整体上的预测精度。𝑦𝑖yi​为实验室的真实测量值,𝑦𝑖y​i​为模型的预测值,计算公式 MAE=1𝑛∑𝑖=1𝑛∣𝑦𝑖-𝑦𝑖∣MAE=n1​∑i=1n​∣yi​-y​i​∣,其中𝑛n是样本总数,MAE∈[0,100]MAE∈[0,100]。
  2. 预测值在一定范围内的平均绝对误差(Range-MAE):在实际场景我们会尤其关注在低Remaining区间模型的预测准确率,此指标衡量在特定范围内的预测值的平均绝对误差。在本次比赛中,低Remaining范围为[0,30][0,30],计算公式 Range-MAE=1𝑚∑𝑖=1𝑚∣𝑦𝑖-𝑦𝑖∣Range-MAE=m1​∑i=1m​∣yi​-y​i​∣,其中𝑚m是预测值在[0,30][0,30]范围内的样本数量,Range-MAE∈[0,100]Range-MAE∈[0,100]。
  3. 预测值在一定范围内的F1指标(F1):此指标衡量在特定范围内的预测值的precision以及在相应区间预测的recall情况,综合得到F1值。在本次比赛中,低Remaining范围为[0,30][0,30]。

解读baseline

1、为什么要self.ngram = ngram,而不是直接赋值

定义实例属性使得类(class)的其他方法(其他def)可以直接访问和使用 ngram 的值。例如,tokenize 方法需要使用 ngram 的值来执行分词操作,如果不将其定义为实例属性,就无法在 tokenize 方法中直接访问。

class GenomicTokenizer:
    def __init__(self, ngram=5, stride=2):
        self.ngram = ngram
        self.stride = stride

  # 假设使用实例属性
    def tokenize(self, t):
        t = t.upper()
        if self.ngram == 1:
            toks = list(t)
        else:
            toks = [t[i:i+self.ngram] for i in range(0, len(t), self.stride) if len(t[i:i+self.ngram]) == self.ngram]
        return toks
        
  # 假设不使用实例属性,而是硬编码
        def tokenize(self, t):
        t = t.upper()
        ngram = 5
        stride = 2
        if ngram == 1:
            toks = list(t)
        else:
            toks = [t[i:i+ngram] for i in range(0, len(t), stride) if len(t[i:i+ngram]) == ngram]
        return toks

2、列表推导式

列表推导式(List Comprehension)是一种在Python中用来创建列表的简洁语法。它允许你从一个序列(如列表、元组、字符串等)或者另一个列表推导式,通过一个表达式来生成新的列表。列表推导式通常包含一个表达式,后面跟着一个for循环,以及可选的if条件语句。

基本语法如下:

[expression for item in iterable if condition]
  • expression 是对每个元素进行的操作。
  • item 是从 iterable 中取出来的元素。
  • iterable 是一个序列或者任何可迭代的对象。
  • condition 是一个可选的条件语句,用于筛选元素。

例如,如果你有一个数字列表,你想创建一个新的列表,其中只包含原列表中的偶数,你可以使用列表推导式如下:

original_list = [1, 2, 3, 4, 5, 6]
even_numbers = [num for num in original_list if num % 2 == 0]

在这个例子中,even_numbers 将会是 [2, 4, 6]

3、类方法和实例方法

"类方法"和"实例方法"是面向对象编程中的两个概念,它们都与类和对象的行为有关,但它们的使用场景和作用不同。

  • 实例方法:这是最常见的方法类型,它们与类的实例(对象)相关联。实例方法的第一个参数通常是 self,它代表当前对象的实例。当调用实例方法时,你通常是在对某个具体的对象进行操作。

  • 类方法:与实例方法不同,类方法是与类本身相关联的方法。这意味着它们不需要创建类的实例就可以被调用。类方法的第一个参数通常是 cls,它代表类本身。使用类方法可以访问类属性或执行与类相关的操作,而不需要创建类的实例。

在Python中,使用 @classmethod 装饰器来定义一个类方法。这个装饰器告诉Python解释器,接下来的函数是一个类方法,而不是一个实例方法。当你调用一个类方法时,你可以使用类名直接调用,也可以通过类的实例调用,但传递给方法的第一个参数将是类本身,而不是实例。

在Python中,类方法和实例方法的区别可以通过一个实际案例来更清晰地理解:

为了更好地理解类方法和实例方法的区别及其用途,下面是一个具体的例子。假设我们在开发一个员工管理系统,我们需要管理员工的信息并生成员工的工号。

实例方法

实例方法依赖于类的实例(对象),它们操作实例数据。实例方法的第一个参数通常是 self,表示实例本身。

class Employee:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.employee_id = None

    def set_employee_id(self, employee_id):
        self.employee_id = employee_id

    def get_info(self):
        return f"Name: {self.name}, Age: {self.age}, Employee ID: {self.employee_id}"

使用实例方法

# 创建员工实例
emp1 = Employee("Alice", 30)
emp2 = Employee("Bob", 35)

# 设置员工ID
emp1.set_employee_id("E001")
emp2.set_employee_id("E002")

# 获取员工信息
print(emp1.get_info())  # 输出: Name: Alice, Age: 30, Employee ID: E001
print(emp2.get_info())  # 输出: Name: Bob, Age: 35, Employee ID: E002

在这个例子中:

  • set_employee_idget_info 是实例方法,它们操作和访问实例的数据(nameageemployee_id)。
  • 每个实例(emp1emp2)都有独立的数据。

类方法

类方法不依赖于类的实例,它们操作类本身的数据或提供一些通用功能。类方法的第一个参数通常是 cls,表示类本身。

class Employee:
    employee_count = 0  # 类变量,所有实例共享

    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.employee_id = None
        Employee.employee_count += 1

    def set_employee_id(self, employee_id):
        self.employee_id = employee_id

    def get_info(self):
        return f"Name: {self.name}, Age: {self.age}, Employee ID: {self.employee_id}"

    @classmethod
    def generate_employee_id(cls):
        return f"E{cls.employee_count + 1:03d}"

使用类方法

# 创建员工实例
emp1 = Employee("Alice", 30)
emp2 = Employee("Bob", 35)

# 使用类方法生成员工ID
emp1.set_employee_id(Employee.generate_employee_id())
emp2.set_employee_id(Employee.generate_employee_id())

# 获取员工信息
print(emp1.get_info())  # 输出: Name: Alice, Age: 30, Employee ID: E003
print(emp2.get_info())  # 输出: Name: Bob, Age: 35, Employee ID: E004

# 查看总员工数
print(Employee.employee_count)  # 输出: 2

在这个例子中:

  • generate_employee_id 是一个类方法,它不依赖于具体的实例,而是依赖于类的数据(employee_count)。
  • employee_count 是一个类变量,所有实例共享,用于跟踪员工的总数。

区分类方法和实例方法

  1. 作用域不同

    • 实例方法作用于类的实例,操作实例数据。
    • 类方法作用于类本身,操作类的数据或提供一些通用功能。
  2. 使用场景不同

    • 当需要访问或修改实例的属性时,使用实例方法。
    • 当需要执行与类相关的操作且不依赖于实例数据时,使用类方法。例如,统计类的实例数量、生成唯一的实例标识符等。
  3. 设计上的清晰性和组织性

    • 将不同类型的方法分开,可以使代码更清晰、更易于维护。类方法适用于全局操作或类级别的操作,实例方法适用于具体实例的操作。

posted @ 2024-07-26 14:51  CASTWJ  阅读(110)  评论(0编辑  收藏  举报