RNN处理不定长输入
RNN模型:
class RNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(RNN, self).__init__()
self.hidden_size = hidden_size
self.u = nn.Linear(input_size, hidden_size)
self.w = nn.Linear(hidden_size, hidden_size)
self.v = nn.Linear(hidden_size, output_size)
self.tanh = nn.Tanh()
self.softmax = nn.LogSoftmax(dim=1)
def forward(self, inputs, hidden):
u_x = self.u(inputs)
hidden = self.w(hidden)
hidden = self.tanh(hidden + u_x)
output = self.softmax(self.v(hidden))
return output, hidden
def initHidden(self):
return torch.zeros(1, self.hidden_size)
rnn = RNN(n_input, n_hidden, n_categories)
rnn = RNN(57, 128, 18)
RNN训练过程:
for i in range(line_tensor.size()[0]):
output, hidden = rnn(line_tensor[i], hidden)
计算loss后的反向传播:
loss = criterion(output, category_tensor)
loss.backward()
梯度下降:
for p in rnn.parameters():
p.data.add_(-learning_rate, p.grad.data)
ot:目标分类数,在这里应该是18和下面的labels对应上
这里的xt用的是独热向量,表示58种输入
hidden:
line_tensor:
写个案例:
从csv文件中进行数据生成:
import pandas as pd
import torch
import math
import random
# ============================ step 1/5 数据 ================================
data = pd.read_csv("./data/traffic_28_classifier1.csv")
# data.dropna(axis=0,how='any') #drop all rows that have any NaN values
serises_num=3
serises_len=15
label_tag=13
def arrsToTensor(randomSample):
tensor = torch.zeros(serises_num, 1, serises_len) # serises_num是一个样本的序列长度 serises_len是每一个序列的长度 1是pytorch的格式需要
for i in range(len(randomSample)):
tensor[i][0] = torch.tensor(randomSample.iloc[i].values)
return tensor
def randomTrainingExample():
# 1. 样本数sampleCounts
# 2. 随机取[1,sampleCounts]中的值randomSample
# 3. 获取样本数据,data.iloc[randomSampleNum:randomSampleNum+3]
sampleCounts = data.shape[0]-2
randomSampleNum = random.randint(1,sampleCounts-2) # 最后一个样本不取,因为没有标签
#print(randomSampleNum)
#length_data=data.shape[0]
#test=data.iloc[0]
randomSample=data.iloc[randomSampleNum:randomSampleNum+3]
arrs_tensor = arrsToTensor(randomSample) # arrs_data
label_data=data.iloc[randomSampleNum + 3]
randomSampleLabel=data.iloc[randomSampleNum+3][label_tag] # label
#print(randomSampleLabel)
category_tensor = torch.tensor([randomSampleLabel], dtype=torch.long)
return category_tensor, arrs_tensor
输入为1*15的3个连续向量
输出为0,1的二分类任务
main.py
from model import RNN
from data_loader import randomTrainingExample
import torch.nn as nn
import torch
# ============================ step 0/5 参数设置 ============================
device = torch.device("cpu")
learning_rate = 0.005
n_iters = 200000
n_hidden = 128
n_input = 15
n_categories = 2
# ============================ step 1/5 数据 ================================
# from data_loader import randomTrainingExample
# ============================ step 2/5 模型 ================================
# rnn = RNN(n_input, n_hidden, n_categories)
rnn = RNN(n_input, n_hidden, n_categories)
rnn.to(device)
# ============================ step 3/5 损失函数 ============================
criterion = nn.NLLLoss()
# ============================ step 4/5 优化器 ==============================
# for p in rnn.parameters(): # 优化器
# p.data.add_(-learning_rate, p.grad.data)
# ============================ step 5/5 训练 ================================
def train(category_tensor, arrs_tensor):
hidden = rnn.initHidden()
rnn.zero_grad()
arrs_tensor = arrs_tensor.to(device)
hidden = hidden.to(device)
category_tensor = category_tensor.to(device)
for i in range(arrs_tensor.size()[0]):
output, hidden = rnn(arrs_tensor[i], hidden)
loss = criterion(output, category_tensor)
loss.backward()
# Add parameters' gradients to their values, multiplied by learning rate
for p in rnn.parameters(): # 优化器
p.data.add_(-learning_rate, p.grad.data)
return output, loss.item()
for iter in range(1, n_iters + 1):
category_tensor, arrs_tensor = randomTrainingExample()
# training
output, loss = train(category_tensor, arrs_tensor)
print(loss)
# =========================== inference ====================================
model.py
import torch.nn as nn
import torch
class RNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(RNN, self).__init__()
self.hidden_size = hidden_size
self.u = nn.Linear(input_size, hidden_size)
self.w = nn.Linear(hidden_size, hidden_size)
self.v = nn.Linear(hidden_size, output_size)
self.tanh = nn.Tanh()
self.softmax = nn.LogSoftmax(dim=1)
def forward(self, inputs, hidden):
u_x = self.u(inputs)
hidden = self.w(hidden)
hidden = self.tanh(hidden + u_x)
output = self.softmax(self.v(hidden))
return output, hidden
def initHidden(self):
return torch.zeros(1, self.hidden_size)
data_loader.py
import pandas as pd
import torch
import math
import random
# ============================ step 1/5 数据 ================================
data = pd.read_csv("./data/traffic_28_classifier1.csv")
# data.dropna(axis=0,how='any') #drop all rows that have any NaN values
serises_num=3
serises_len=15
label_tag=13
def arrsToTensor(randomSample):
tensor = torch.zeros(serises_num, 1, serises_len) # serises_num是一个样本的序列长度 serises_len是每一个序列的长度 1是pytorch的格式需要
for i in range(len(randomSample)):
tensor[i][0] = torch.tensor(randomSample.iloc[i].values)
return tensor
def randomTrainingExample():
# 1. 对所有的行数除以3,向下取整得出样本数sampleCounts
# 2. 随机取[1,sampleCounts]中的值randomSample
# 3. 获取样本数据,randomSample*3, data[randomSample*3-3,randomSample*3]
sampleCounts = data.shape[0]-2
randomSampleNum = random.randint(1,sampleCounts-2) # 最后一个样本不取,因为没有标签
#print(randomSampleNum)
#length_data=data.shape[0]
#test=data.iloc[0]
randomSample=data.iloc[randomSampleNum:randomSampleNum+3]
arrs_tensor = arrsToTensor(randomSample) # arrs_data
label_data=data.iloc[randomSampleNum + 3]
randomSampleLabel=data.iloc[randomSampleNum+3][label_tag] # label
#print(randomSampleLabel)
category_tensor = torch.tensor([randomSampleLabel], dtype=torch.long)
return category_tensor, arrs_tensor
# def traffic_data_loader():
# # 每取三行,对第四行的traffic进行判断,如果第四行的traffic是1,就是正样例,如果traffic=0,就是负样例
#
# positive = pd.DataFrame()
# negective = pd.DataFrame()
#
# for i in range(3,data.shape[0]):
# if data.iloc[i][13]== 1:
# positive=positive.append(data.iloc[i-3:i])
# #print(data.iloc[i-3:i])
# elif data.iloc[i][13]== 0:
# negective=negective.append(data.iloc[i-3:i])
# #print(data.iloc[i-3:i])
#
# negective.to_csv("negective.csv")
# positive.to_csv("positive.csv")
#
# data_single=data.iloc[1]
# data_single=data_single.values
# data_single
# t=torch.tensor(data_single)
#
#
# tensor = torch.zeros(3, 1, 15) # 3是一个样本的序列长度 15是每一个序列的长度 1是pytorch的格式需要
# tensor[0][1]= t;
# return tensor
if __name__ == "__main__":
category_tensor, arrs_tensor=randomTrainingExample()
print(category_tensor, arrs_tensor)