Pytorch实现基于CharRNN的文本分类与生成示例
2020-06-25 08:07:59 来源:易采站长站 作者:易采站长站整理
device = torch.device("cuda" if USE_CUDA else "cpu")
chars = string.ascii_lowercase + '-' + ' ' + "'"
'''
将名字编码为向量:每个字符为one-hot编码,将多个字符的向量进行堆叠
abc = [ [1, 0, ...,0] [0, 1, 0, ..] [0, 0, 1, ..] ]abc.shape = (len("abc"), len(chars))
'''
def name2vec(name):
ids = [chars.index(c) for c in name if c not in [""]]
a = np.zeros(shape=(len(ids), len(chars)))
for i, idx in enumerate(ids):
a[i][idx] = 1
return a
def load_data():
female_file, male_file = names.fileids()
f1_names = names.words(female_file)
f2_names = names.words(male_file)
data_set = [(name.lower(), 0) for name in f1_names] + [(name.lower(), 1) for name in f2_names] data_set = [(name2vec(name), sexy) for name, sexy in data_set] random.shuffle(data_set)
return data_set
class CharRNN(nn.Module):
def __init__(self, vocab_size, hidden_size, output_size):
super(CharRNN, self).__init__()
self.vocab_size = vocab_size
self.hidden_size = hidden_size
self.output_size = output_size
self.rnn = nn.RNN(vocab_size, hidden_size, batch_first=True)
self.liner = nn.Linear(hidden_size, output_size)
def forward(self, input):
h0 = torch.zeros(1, 1, self.hidden_size, device=device) # 初始hidden state
output, hidden = self.rnn(input, h0)
output = output[:, -1, :] # 只使用最终时刻的输出作为特征
output = self.liner(output)
output = F.softmax(output, dim=1)
return output
hidden_dim = 128
output_dim = 2
class Model:
def __init__(self, epoches=100):
self.model = CharRNN(len(chars), hidden_dim , output_dim)
self.model.to(device)
self.epoches = epoches
def train(self, train_set):
loss_func = nn.CrossEntropyLoss()
optimizer = torch.optim.RMSprop(self.model.parameters(), lr=0.0003)
for epoch in range(self.epoches):
total_loss = 0
for x in range(1000):# 每轮随机样本训练1000次
name, sexy = random.choice(train_set)
# RNN的input要求shape为[batch, seq_len, embed_dim],由于名字为变长,也不准备好将其填充为定长,因此batch_size取1,将取的名字放入单个元素的list中。
name_tensor = torch.tensor([name], dtype=torch.float, device=device)
# torch要求计算损失时,只提供类别的索引值,不需要one-hot表示
sexy_tensor = torch.tensor([sexy], dtype=torch.long, device=device)
optimizer.zero_grad()
pred = self.model(name_tensor) # [batch, out_dim] loss = loss_func(pred, sexy_tensor)
loss.backward()
total_loss += loss
optimizer.step()
print("Training: in epoch {} loss {}".format(epoch, total_loss/1000))
def evaluate(self, test_set):
with torch.no_grad(): # 评估时不进行梯度计算
correct = 0
for x in range(1000): # 从测试集中随机采样测试1000次













闽公网安备 35020302000061号