Datawhale AI夏令营 siRNA task2

#Datawhale AI夏令营

task2的任务是精读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

这一部分是在将基因组序列分割成固定长度的n-gram:

__init__方法接受两个参数ngram和stride,用于设置分词器的n-gram长度和步幅。当ngram设置为1时,它确实将输入序列转换为单个字符的列表;当ngram大于1时,它通过步幅来生成ngram分词,但当步幅小于ngram长度,这将导致在某些情况下无法正确生成ngram分词。此外,即使步幅足够大,也可能因为输入序列的长度不是步幅的整数倍而导致最后一个分词长度小于ngram。

class SiRNADataset(Dataset):
    def __init__(self, df, columns, vocab, tokenizer, max_len, is_test=False):
        # 初始化数据集
        self.df = df  # 数据框
        self.columns = columns  # 包含序列的列名
        self.vocab = vocab  # 词汇表
        self.tokenizer = tokenizer  # 分词器
        self.max_len = max_len  # 最大序列长度
        self.is_test = is_test  # 指示是否是测速集

    def __len__(self):
        # 返回数据集的长度
        return len(self.df)

    def __getitem__(self, idx):
        # 获取数据集中的第idx个样本
        row = self.df.iloc[idx]  # 获取第idx行数据
        
        # 对每一列进行分词和编码
        seqs = [self.tokenize_and_encode(row[col]) for col in self.columns]
        if self.is_test:
            # 仅返回编码后的序列(非测试集模式)
            return seqs
        else:
            # 获取目标值并转换为张量(仅在非测试集模式下)
            target = torch.tensor(row['mRNA_remaining_pct'], dtype=torch.float)
            # 返回编码后的序列和目标值
            return seqs, target

    def tokenize_and_encode(self, seq):
        if ' ' in seq:  # 修改过的序列
            tokens = seq.split()  # 按空格分词
        else:  # 常规序列
            tokens = self.tokenizer.tokenize(seq)  # 使用分词器分词
        
        # 将token转换为索引,未知token使用0(<pad>)
        encoded = [self.vocab.stoi.get(token, 0) for token in tokens]
        # 将序列填充到最大长度
        padded = encoded + [0] * (self.max_len - len(encoded))
        # 返回张量格式的序列
        return torch.tensor(padded[:self.max_len], dtype=torch.long)

这一部分用于加载siRNA数据,并将序列数据转换为模型可以处理的格式:

类定义和初始化部分已经清晰,包括了处理数据集所需的所有必要信息,但需要注意的是,is_test参数用于区分测试集和非测试集,所以确保这个参数在使用时保持一致是很重要的。tokenize_and_encode方法检查序列中是否包含空格,如果是,则按空格分词;否则,使用自定义分词器分词。这种方法非常灵活,能让我了解如何处理不同类型的输入序列。序列被填充到最大长度self.max_len,这是处理变长序列时的常见做法。但是,baseline在这里使用了[0]*(self.max_len-len(encoded))来生成填充,然后又使用 padded[:self.max_len],这实际上是多余的,因为padded的长度已经是self.max_len,可以简化为padded=encoded+[0]*(self.max_len-len(encoded))[:self.max_len].

train_data = lgb.Dataset(X_train, label=y_train)
test_data = lgb.Dataset(X_test, label=y_test, reference=train_data)

def print_validation_result(env):
    result = env.evaluation_result_list[-1]
    print(f"[{env.iteration}] {result[1]}'s {result[0]}: {result[2]}")

params = {
    "boosting_type": "gbdt",
    "objective": "regression",
    "metric": "root_mean_squared_error",
    "max_depth": 7,
    "learning_rate": 0.02,
    "verbose": 0,
}

gbm = lgb.train(
    params,
    train_data,
    num_boost_round=15000,
    valid_sets=[test_data],
    callbacks=[print_validation_result],
)

这是有大佬使用了lightgbm模型对官方baseline做出的修改,并且跑到了0.75的分数。注意在使用这个修改的模型前,需要在控制台上pip install lightgbm,否则会报错。至于如何读懂修改后的模型,我仍在不断学习中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值