代码内容分析-笔记
(嗯?刚开始还有个0点几分,然后改了一下直接变负分了嘛?但是还是该写写该改改)
经过我的观察和分析,发现其代码内容包括以下三个方面
1.数据处理与特征提取
2.RNN模型的定义与训练
3.模型的评估与预测
下面尝试进行这三个方面的分析:
一、数据处理与特征提取
主要代码:
class Smiles_tokenizer():
def __init__(self, pad_token, regex, vocab_file, max_length):
self.pad_token = pad_token
self.regex = regex
self.vocab_file = vocab_file
self.max_length = max_length
with open(self.vocab_file, "r") as f:
lines = f.readlines()
lines = [line.strip("\n") for line in lines]
vocab_dic = {}
for index, token in enumerate(lines):
vocab_dic[token] = index
self.vocab_dic = vocab_dic
def _regex_match(self, smiles):
regex_string = r"(" + self.regex + r"|"
...
其中主要包括两点:
1.Tokenization
使用正则表达式将SMILES字符串分割成单独的字符或子字符串,并将这些字符映射到词汇表中的索引。
2.Padding
使用特殊的填充符号(pad_token
)将所有序列填充到相同长度(max_length
),以便于批处理训练。
二、RNN模型的定义与训练
主要代码:
class RNNModel(nn.Module):
def __init__(self, num_embed, input_size, hidden_size, output_size, num_layers, dropout, device):
super(RNNModel, self).__init__()
self.embed = nn.Embedding(num_embed, input_size)
self.rnn = nn.RNN(input_size, hidden_size, num_layers=num_layers,
batch_first=True, dropout=dropout, bidirectional=True)
self.fc = nn.Sequential(nn.Linear(2 * num_layers * hidden_size, output_size),
nn.Sigmoid(),
nn.Linear(output_size, 1),
nn.Sigmoid())
def forward(self, x):
x = self.embed(x)
_, hn = self.rnn(x)
hn = hn.transpose(0,1)
z = hn.reshape(hn.shape[0], -1)
output = self.fc(z).squeeze(-1)
return output
这段代码是RNN,这里介绍一下RNN的基本原理
RNN(循环神经网络)的原理
RNN是一种用于处理序列数据的神经网络,其主要特征是具有循环连接,能够保留并利用之前时刻的信息对当前时刻的输出进行影响。以下是RNN模型的原理及其关键组件:
1. 序列数据的处理
RNN特别适合处理时间序列数据或序列数据(如文本、语音信号、视频帧等)。在这种数据中,每个数据点不仅与前后数据点有关系,而且这种关系是顺序性的。
2. 隐藏状态
RNN通过一个隐藏状态向量来保留序列中前面部分的信息。每个时间步的隐藏状态不仅依赖于当前输入,还依赖于之前时间步的隐藏状态,这样就实现了信息的传播。
3. RNN的结构
一个简单的RNN的每个时间步可以表示为:
其中:
是时间步的隐藏状态
是时间步的输入
是输入到隐藏状态的权重矩阵
是前一隐藏状态到当前隐藏状态的权重矩阵
是隐藏状态到输出的权重矩阵
和分别是隐藏状态和输出的偏置项
是是激活函数
4. 前向传播
在RNN中,前向传播是通过时间展开的,每个时间步的输出和隐藏状态都会传递给下一个时间步。这使得RNN能够记住和利用之前的输入信息。
5. 反向传播
训练RNN使用的是反向传播算法,通过时间的反向传播来计算梯度并更新权重。BPTT会展开整个序列,将每个时间步的误差反向传播,从而更新每个时间步的参数。
6. 双向RNN
双向RNN通过同时考虑前向和后向的序列信息来增强模型的能力。它由两个独立的RNN组成,一个处理正向序列,另一个处理反向序列,然后将它们的输出结合起来进行预测。
7. RNN的局限性
1.梯度消失和梯度爆炸
由于反向传播过程中多次乘法操作,RNN容易出现梯度消失或梯度爆炸问题,特别是在处理长序列时。
2.长期依赖问题
由于梯度消失问题,RNN在处理长时间依赖时效果不佳。
三、模型的评估与预测
主要代码:
def predicit_and_make_submit_file(model_file, output_file):
NUM_EMBED = 294
INPUT_SIZE = 300
HIDDEN_SIZE = 512
OUTPUT_SIZE = 512
NUM_LAYERS = 10
DROPOUT = 0.2
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
test_data = read_data("../dataset/round1_test_data.csv", train=False)
test_dataset = ReactionDataset(test_data)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False, collate_fn=collate_fn)
model = RNNModel(NUM_EMBED, INPUT_SIZE, HIDDEN_SIZE, OUTPUT_SIZE, NUM_LAYERS, DROPOUT, device).to(device)
model.load_state_dict(torch.load(model_file))
model.eval()
output_list = []
for i, (src, y) in enumerate(test_loader):
src, y = src.to(device), y.to(device)
with torch.no_grad():
output = model(src)
output_list += output.detach().tolist()
ans_str_lst = ['rxnid,Yield']
for idx,y in enumerate(output_list):
ans_str_lst.append(f'test{idx+1},{y:.4f}')
with open(output_file,'w') as fw:
fw.writelines('\n'.join(ans_str_lst))
print("done!!!")
其中包含以下三个步骤:
1.数据加载与预处理
使用ReactionDataset
类和DataLoader
来加载测试数据,并对其进行批处理。
2.模型加载与评估
加载训练好的模型参数,并在测试数据上进行预测。
3.结果输出
将预测结果保存到指定的文件中。