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