#Datawhale AI夏令营 之 AI for Science(AI+药物)#深度学习 #task 2

不如沉默踏实做 2024-08-20 14:01:02 阅读 73

task2 深入理解赛题,入门RNN和特征工程

前面我们了解了task1和和一些基础知识,那么task2就直接步入正题了

思路:我们应该关注哪些部分?

第一部分:关注模型从原始特征到输入模型之前应该经历哪些过程,第二部分:关注输入模型后到输出经历哪些过程,第三部分:关注输入输出后,输出和训练集的真实值计算损失。

第一部分 :

<code>### 5. siRNA Model

这是一个基于GRU的神经网络模型,用于处理siRNA序列。

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()

我们可以发现输入是通过forward函数实现的,那么x是什么呢, 跳转到第八部分中有一个对数据集的拆分然后进行迭代的循环

for epoch in range(num_epochs):

model.train() # 设置模型为训练模式

train_loss = 0 # 初始化训练损失

for inputs, targets in tqdm(train_loader, desc=f'Epoch {epoch+1}/{num_epochs}'):

inputs = [x.to(device) for x in inputs] # 将输入移动到设备

targets = targets.to(device) # 将目标值移动到设备

 这时候可以查看一下inputs的维度,通过在输出调用train_model之前,打印一下train_loder中的输入尺寸

for inputs, target in train_loader:

print(len(inputs))

print(inputs[0].shape)

print(inputs[0][0])

print(target.shape)

break

  

 

 打印出来后可以发现这个inputs这个列表里元素张量的维度为64*25,这里的inputs和上面的x是一个东西。我们首先发现inputs包含两个元素,它们分别对应的是前面提到的两个使用的特征,每个元素的尺寸都是64*25,64代表batch的大小,25代表序列的长度。这里我们可以从inputs[0][0]看到每一行数据的siRNA_antisense_seq被向量化后的情况,这个例子中我们发现前面的7位是非零数,表示其序列编码后每一位的唯一标识;而后面都是0,这是因为RNN模型的输入需要每个样本的长度一致,因此我们需要事先算出一个所有序列编码后的最大长度,然后补0。

那么我们怎么能得到这个唯一标识呢?我们首先需要把序列给进行分词,siRNA_antisense_seq的分词策略是3个一组(GenomicTokenizer的ngram和stride都取3)进行token拆分,比如AGCCGAGAU会被分为[AGC, CGA, GAU],而modified_siRNA_antisense_seq_list会进行按照空格分词(因为它本身已经根据空格分好了)。由此我们可以从整个数据集构建出一个词汇表,他负责token到唯一标识(索引)的映射:

<code># 创建词汇表

all_tokens = []

for col in columns:

for seq in train_data[col]:

if ' ' in seq: # 修饰过的序列

all_tokens.extend(seq.split())

else:

all_tokens.extend(tokenizer.tokenize(seq))

vocab = GenomicVocab.create(all_tokens, max_vocab=10000, min_freq=1)

有了这个词汇表,我们就可以来获得序列的最大长度

max_len = max(max(len(seq.split()) if ' ' in seq else len(tokenizer.tokenize(seq))

for seq in train_data[col]) for col in columns)

在loader获取样本的时候把token转为索引

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)

(补充一下补0操作,假如我现在有60长度的碱基序列,token编码后得出序列最大长度为25,此时,每一段为长度为20(20<25),就需要在后面补5个0 )

例如此时,对于某一行数据,其两个特征分别为AGCCUUAGCACA和u u g g u u Cf c,假设整个数据集对应token编码后序列的最大长度为10,那么得到的特征就可能是

[25, 38, 25, 24, 0, 0, 0, 0, 0, 0]

[65, 65, 63, 63, 65, 65, 74, 50, 0, 0]

那么假设batch的大小为16,此时forword函数的x就会是两个列表,每个列表的tensor尺寸为16 * 10

第二部分 :

我们在上一部分已经得到了数据的张量化表示,此时就要把它输入模型了。

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()

我们首先第一步将得到的索引进行了embedding,token的embedding是将离散的符号(如单词、字符、或基因序列片段)映射到连续的向量空间的过程。这个过程通过将高维的稀疏表示(如独热编码)转换为低维的密集向量表示,使得相似的符号在向量空间中距离更近。此时,embed的尺寸会从BatchSize * Length成为BatchSize * Length * EmbeddingSize,此处EmbeddingSize即embed_dim=200。 

然后了解一下RNN、LSTM与GRU的工作原理和流程:RNN、LSTM和GRU_lstm gru rnn-CSDN博客

下面是一些特点

RNN(Recurrent Neural Network)模型

定义: RNN是一种特殊的神经网络,适合处理序列数据。与传统的前馈神经网络不同,RNN具有内部状态(记忆),能够处理输入信息的序列,这使得它们非常适合处理语言处理、时间序列分析等任务。

结构特点:

循环结构: RNN的核心是循环单元,该单元能够将信息传递到下一个时间步,从而创建状态序列。参数共享: 在处理序列的不同时间步时,RNN使用相同的权重,这减少了模型的参数数量。

优点:

处理序列数据: 能够处理任意长度的序列数据。参数共享: 减少了模型的参数数量,降低了计算复杂度。

缺点:

梯度消失和梯度爆炸: 在长序列中,RNN很难捕捉到长距离依赖,因为梯度在反向传播过程中可能消失或爆炸。难以并行化: 由于序列依赖性,RNN的计算通常需要按顺序进行,这限制了并行处理的能力。

LSTM(Long Short-Term Memory)

定义: LSTM是RNN的一种变体,由Hochreiter和Schmidhuber在1997年提出,旨在解决标准RNN在长序列学习中遇到的梯度消失问题。

结构特点:

门结构: LSTM单元包含三个门(输入门、遗忘门、输出门)和一个细胞状态,这些结构允许LSTM单元有选择性地记住或忘记信息。细胞状态: LSTM单元的核心,它可以在序列中传递信息,使得LSTM能够捕捉长距离依赖。

优点:

解决梯度消失问题: LSTM通过门控机制和细胞状态有效地解决了梯度消失问题,能够学习长序列的依赖关系。更灵活的记忆: LSTM能够根据需要记住或忘记信息,这使得它在处理不同长度的序列时更为灵活。

GRU(Gated Recurrent Unit)

定义: GRU是由Cho等人在2014年提出的一种RNN的变体,它和LSTM一样,旨在解决标准RNN在处理长序列时遇到的梯度消失问题。GRU可以看作是LSTM的一个简化版本,它具有更少的门控结构。

结构特点:

重置门和更新门: GRU只有两个门,分别是重置门(reset gate)和更新门(update gate)。这两个门控制信息的流动。隐藏状态: GRU没有单独的长期记忆细胞状态,而是将隐藏状态和细胞状态合并为一个单一的隐藏状态。

优点:

更少的参数: 相比于LSTM,GRU的参数更少,这使得模型的计算效率更高,训练速度更快。简化结构: GRU的门控结构比LSTM简单,这使得模型更容易理解和实现。缓解梯度消失问题: 类似于LSTM,GRU通过门控机制能够缓解梯度消失问题,学习长序列的依赖关系。

GRU 的结构更简单,计算效率更高,同时在许多应用中表现出与 LSTM 类似的性能。

我们在pytorch的GRU文档中可以找到对应可选的参数信息,我们需要特别关注的参数如下,它们决定了模型的输入输出的张量维度

input_size(200)

hidden_size(256)

bidirectional(True)

假设输入的BatchSize为16,序列最大长度为10,即x每个元素尺寸为16 * 10 * 200,那么其输出的张量尺寸为 16 * 10 * (256 * 2)

在从GRU模型输出后,x = self.dropout(x[:, -1, :])使得输出变为了BatchSize * (hidden_dim * 2),此处取了序列最后一个位置的输出数据(注意RNN网络的记忆性),这里的2是因为bidirectional参数为True,随后x = torch.cat(outputs, dim=1)指定在第二个维度拼接后,通过全连接层再映射为标量,因此最后经过squeeze(去除维数为1的维度)后得到的张量尺寸为批大小,从而可以后续和target值进行loss计算,迭代模型

做完后我们发现效果并不是很好,,这一方面原因可能在于数据用的特征还较为简单,序列特征的构造较为粗糙,下面进行在表格数据上做特征工程(lightgbm模型)。

在特征构造前,一定要分析数据,我们先展示一下一共有多少列,然后判断这个变量是类别变量还是数值型变量,如果是数值型变量(例如上一期的电力预测里的变量)就需要考虑方差,均值的分布,如果是类别型变量就要考虑有多少类别数,分别占比等等.

可以用下面语句先展示一下一共有多少列

df.columns

我们就拿publication_id来举例,(pandas库中,.value_counts() 是一个非常有用的方法,它用于计算Series(一维数组)中各个值的频率,并返回一个按频率降序排列的Series。这对于快速查看数据集中不同值的分布情况非常有用。)

df.publication_id.value_counts()

如果相较于数据的总行数很少,那么其很可能就是类别变量了。此时,我们可以使用get_dummie函数来实现one-hot特征的构造(pandas库中,<code>get_dummies() 函数是用来创建一个one-hot编码(独热编码)的DataFrame。One-hot编码是一种将分类变量转换为二进制(0和1)向量表示的方法,其中每个向量只有一个元素为1,其余元素为0。),siRNA和mRNA序列本质上是分类数据,每个碱基(A、U、C、G)都是一个类别。通过One-hot编码,可以将这些碱基转换成数值特征向量,并且除了碱基序列,还可能考虑其他特征,如GC含量、序列的二级结构、靶标mRNA的局部结构等。这些特征可以通过One-hot编码转换成机器学习模型可以理解的格式

举个例子:

import pandas as pd

data = {'颜色': ['红色', '绿色', '蓝色', '红色']}

df = pd.DataFrame(data)

# 进行One-hot编码

encoded_df = pd.get_dummies(df['颜色'])

print(encoded_df)

结果就是:

红色 绿色 蓝色

0 1 0 0

1 0 1 0

2 0 0 1

3 1 0 0

结果我们发现有很多列都是分类变量,处理方法也都是一样的:

df_publication_id = pd.get_dummies(df.publication_id)

df_publication_id.columns = [

f"feat_publication_id_{c}" for c in df_publication_id.columns

]

df_gene_target_symbol_name = pd.get_dummies(df.gene_target_symbol_name)

df_gene_target_symbol_name.columns = [

f"feat_gene_target_symbol_name_{c}" for c in df_gene_target_symbol_name.columns

]

df_gene_target_ncbi_id = pd.get_dummies(df.gene_target_ncbi_id)

df_gene_target_ncbi_id.columns = [

f"feat_gene_target_ncbi_id_{c}" for c in df_gene_target_ncbi_id.columns

]

df_gene_target_species = pd.get_dummies(df.gene_target_species)

df_gene_target_species.columns = [

f"feat_gene_target_species_{c}" for c in df_gene_target_species.columns

]

siRNA_duplex_id_values = df.siRNA_duplex_id.str[3:-2].str.strip(".").astype("int")

siRNA_duplex_id_values = (siRNA_duplex_id_values - siRNA_duplex_id_values.min()) / (

siRNA_duplex_id_values.max() - siRNA_duplex_id_values.min()

)

df_siRNA_duplex_id = pd.DataFrame(siRNA_duplex_id_values)

df_cell_line_donor = pd.get_dummies(df.cell_line_donor)

df_cell_line_donor.columns = [

f"feat_cell_line_donor_{c}" for c in df_cell_line_donor.columns

]

df_cell_line_donor["feat_cell_line_donor_hepatocytes"] = (

(df.cell_line_donor.str.contains("Hepatocytes")).fillna(False).astype("int")

)

df_cell_line_donor["feat_cell_line_donor_cells"] = (

df.cell_line_donor.str.contains("Cells").fillna(False).astype("int")

)

df_siRNA_concentration = df.siRNA_concentration.to_frame()

df_Transfection_method = pd.get_dummies(df.Transfection_method)

df_Transfection_method.columns = [

f"feat_Transfection_method_{c}" for c in df_Transfection_method.columns

]

df_Duration_after_transfection_h = pd.get_dummies(df.Duration_after_transfection_h)

df_Duration_after_transfection_h.columns = [

f"feat_Duration_after_transfection_h_{c}"

在数据观察的时候发现,siRNA_duplex_id的编码方式很有意思,其格式为AD-1810676.1,我们猜测AD是某个类别,后面的.1是版本,当中的可能是按照一定顺序的序列号,因此可以构造如下可能的时间特征

siRNA_duplex_id_values = df.siRNA_duplex_id.str.split("-|\.").str[1].astype("int")

在观察 cell_line_donor的时候同样发现,他们一共有两种的后缀(Hepatocytes和Cells),我们猜测可能与二分类有关,因此可以构造如下特征

df_cell_line_donor = pd.get_dummies(df.cell_line_donor)

df_cell_line_donor.columns = [

f"feat_cell_line_donor_{c}" for c in df_cell_line_donor.columns

]

# 包含Hepatocytes

df_cell_line_donor["feat_cell_line_donor_hepatocytes"] = (

(df.cell_line_donor.str.contains("Hepatocytes")).fillna(False).astype("int")

)

# 包含Cells

df_cell_line_donor["feat_cell_line_donor_cells"] = (

df.cell_line_donor.str.contains("Cells").fillna(False).astype("int")

)

根据序列模式提取特征

假设siRNA的序列为ACGCA...,此时我们可以根据上一个task中提到的rna背景知识,对碱基的模式进行特征构造

<code>ef siRNA_feat_builder(s: pd.Series, anti: bool = False):

name = "anti" if anti else "sense"

df = s.to_frame()

# 序列长度

df[f"feat_siRNA_{name}_seq_len"] = s.str.len()

for pos in [0, -1]:

for c in list("AUGC"):

# 第一个和最后一个是否是A/U/G/C

df[f"feat_siRNA_{name}_seq_{c}_{'front' if pos == 0 else 'back'}"] = (

s.str[pos] == c

)

# 是否已某一对碱基开头和某一对碱基结尾

df[f"feat_siRNA_{name}_seq_pattern_1"] = s.str.startswith("AA") & s.str.endswith(

"UU"

)

df[f"feat_siRNA_{name}_seq_pattern_2"] = s.str.startswith("GA") & s.str.endswith(

"UU"

)

df[f"feat_siRNA_{name}_seq_pattern_3"] = s.str.startswith("CA") & s.str.endswith(

"UU"

)

df[f"feat_siRNA_{name}_seq_pattern_4"] = s.str.startswith("UA") & s.str.endswith(

"UU"

)

df[f"feat_siRNA_{name}_seq_pattern_5"] = s.str.startswith("UU") & s.str.endswith(

"AA"

)

df[f"feat_siRNA_{name}_seq_pattern_6"] = s.str.startswith("UU") & s.str.endswith(

"GA"

)

df[f"feat_siRNA_{name}_seq_pattern_7"] = s.str.startswith("UU") & s.str.endswith(

"CA"

)

df[f"feat_siRNA_{name}_seq_pattern_8"] = s.str.startswith("UU") & s.str.endswith(

"UA"

)

# 第二位和倒数第二位是否为A

df[f"feat_siRNA_{name}_seq_pattern_9"] = s.str[1] == "A"

df[f"feat_siRNA_{name}_seq_pattern_10"] = s.str[-2] == "A"

# GC占整体长度的比例

df[f"feat_siRNA_{name}_seq_pattern_GC_frac"] = (

s.str.contains("G") + s.str.contains("C")

) / s.str.len()

return df.iloc[:, 1:]

第三部分 :

在得到了表格数据之后,我们可以使用适用于表格数据的机器学习回归模型来进行预测,这里使用了lightgbm模型:

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],

)

这里有一些好的调参建议(各位可以参考) 

https://lightgbm.readthedocs.io/en/stable/Parameters.html

以上就是task2的学习过程辣~最后分数也来到了0.7590~hh

其实大家经过调参也可以进行一定的分数提升,修改一些num_boost_round(迭代次数)学习速率(learning_rate),树的深度(max_depth).....

也可以加一些新的特征(

df[f"feat_siRNA_{name}_seq_pattern_1"] = s.str.startswith("AAA") & s.str.endswith("UUU")

df[f"feat_siRNA_{name}_seq_pattern_5"] = s.str.startswith("UUU") & s.str.endswith("AAA")

我加上了连续“AAA”“UUU”这样的特征,分数都是有些许提高的,本人是一名小白,上文有借助检索解决疑惑和一些自己的理解,如有不对的地方还请各位大佬提出,会修改的hh,期待task3的学习qwq(有部分理解源自b站二次元的Datawhale巨佬耿远昊的讲解,大家可以点击链接观看

二次元的Datawhale)

完整baseline 代码

<code>import pandas as pd

df_original = pd.read_csv("data/train_data.csv")

n_original = df_original.shape[0]

df_submit = pd.read_csv("data/sample_submission.csv")

df = pd.concat([df_original, df_submit], axis=0).reset_index(drop=True)

def siRNA_feat_builder(s: pd.Series, anti: bool = False):

name = "anti" if anti else "sense"

df = s.to_frame()

# 序列长度

df[f"feat_siRNA_{name}_seq_len"] = s.str.len()

for pos in [0, -1]:

for c in list("AUGC"):

# 第一个和最后一个是否是A/U/G/C

df[f"feat_siRNA_{name}_seq_{c}_{'front' if pos == 0 else 'back'}"] = (

s.str[pos] == c

)

# 是否已某一对碱基开头和某一对碱基结尾

df[f"feat_siRNA_{name}_seq_pattern_1"] = s.str.startswith("AA") & s.str.endswith(

"UU"

)

df[f"feat_siRNA_{name}_seq_pattern_2"] = s.str.startswith("GA") & s.str.endswith(

"UU"

)

df[f"feat_siRNA_{name}_seq_pattern_3"] = s.str.startswith("CA") & s.str.endswith(

"UU"

)

df[f"feat_siRNA_{name}_seq_pattern_4"] = s.str.startswith("UA") & s.str.endswith(

"UU"

)

df[f"feat_siRNA_{name}_seq_pattern_5"] = s.str.startswith("UU") & s.str.endswith(

"AA"

)

df[f"feat_siRNA_{name}_seq_pattern_6"] = s.str.startswith("UU") & s.str.endswith(

"GA"

)

df[f"feat_siRNA_{name}_seq_pattern_7"] = s.str.startswith("UU") & s.str.endswith(

"CA"

)

df[f"feat_siRNA_{name}_seq_pattern_8"] = s.str.startswith("UU") & s.str.endswith(

"UA"

)

# 第二位和倒数第二位是否为A

df[f"feat_siRNA_{name}_seq_pattern_9"] = s.str[1] == "A"

df[f"feat_siRNA_{name}_seq_pattern_10"] = s.str[-2] == "A"

# GC占整体长度的比例

df[f"feat_siRNA_{name}_seq_pattern_GC_frac"] = (

s.str.contains("G") + s.str.contains("C")

) / s.str.len()

return df.iloc[:, 1:]

df_publication_id = pd.get_dummies(df.publication_id)

df_publication_id.columns = [

f"feat_publication_id_{c}" for c in df_publication_id.columns

]

df_gene_target_symbol_name = pd.get_dummies(df.gene_target_symbol_name)

df_gene_target_symbol_name.columns = [

f"feat_gene_target_symbol_name_{c}" for c in df_gene_target_symbol_name.columns

]

df_gene_target_ncbi_id = pd.get_dummies(df.gene_target_ncbi_id)

df_gene_target_ncbi_id.columns = [

f"feat_gene_target_ncbi_id_{c}" for c in df_gene_target_ncbi_id.columns

]

df_gene_target_species = pd.get_dummies(df.gene_target_species)

df_gene_target_species.columns = [

f"feat_gene_target_species_{c}" for c in df_gene_target_species.columns

]

siRNA_duplex_id_values = df.siRNA_duplex_id.str[3:-2].str.strip(".").astype("int")

siRNA_duplex_id_values = (siRNA_duplex_id_values - siRNA_duplex_id_values.min()) / (

siRNA_duplex_id_values.max() - siRNA_duplex_id_values.min()

)

df_siRNA_duplex_id = pd.DataFrame(siRNA_duplex_id_values)

df_cell_line_donor = pd.get_dummies(df.cell_line_donor)

df_cell_line_donor.columns = [

f"feat_cell_line_donor_{c}" for c in df_cell_line_donor.columns

]

df_cell_line_donor["feat_cell_line_donor_hepatocytes"] = (

(df.cell_line_donor.str.contains("Hepatocytes")).fillna(False).astype("int")

)

df_cell_line_donor["feat_cell_line_donor_cells"] = (

df.cell_line_donor.str.contains("Cells").fillna(False).astype("int")

)

df_siRNA_concentration = df.siRNA_concentration.to_frame()

df_Transfection_method = pd.get_dummies(df.Transfection_method)

df_Transfection_method.columns = [

f"feat_Transfection_method_{c}" for c in df_Transfection_method.columns

]

df_Duration_after_transfection_h = pd.get_dummies(df.Duration_after_transfection_h)

df_Duration_after_transfection_h.columns = [

f"feat_Duration_after_transfection_h_{c}"

for c in df_Duration_after_transfection_h.columns

]

feats = pd.concat(

[

df_publication_id,

df_gene_target_symbol_name,

df_gene_target_ncbi_id,

df_gene_target_species,

df_siRNA_duplex_id,

df_cell_line_donor,

df_siRNA_concentration,

df_Transfection_method,

df_Duration_after_transfection_h,

siRNA_feat_builder(df.siRNA_sense_seq, False),

siRNA_feat_builder(df.siRNA_antisense_seq, True),

df.iloc[:, -1].to_frame(),

],

axis=1,

)

!pip install lightgbm

import lightgbm as lgb

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(

feats.iloc[:n_original, :-1],

feats.iloc[:n_original, -1],

test_size=0.2,

random_state=42,

)

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],

)

y_pred = gbm.predict(feats.iloc[n_original:, :-1])

df_submit["mRNA_remaining_pct"] = y_pred

df_submit.to_csv("submission.csv", index=False)



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。