From af84ff6c498ab368f0253e829cfa83dfd542130f Mon Sep 17 00:00:00 2001 From: Celsa Diaz Date: Sat, 4 Aug 2018 18:54:06 +0200 Subject: [PATCH] add gitignore, add requirements, correct format, add main, add modes for show text with sentiment, pickle sentiment of a text, pickle sentiment of a list of texts --- .gitignore | 3 + README.md | 2 +- convert_to_cpu.py | 26 ++-- lm.py | 247 ++++++++++++++++---------------- load_from_numpy.py | 24 ++-- models.py | 71 +++++----- requirements.txt | 8 ++ visualize.py | 341 ++++++++++++++++++++++++++------------------- 8 files changed, 389 insertions(+), 333 deletions(-) create mode 100644 .gitignore create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8c75de4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea/ +__pycache__/ +*.pyc \ No newline at end of file diff --git a/README.md b/README.md index 58f036c..7c7ddd9 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Pytorch version of generating-reviews-discovering-sentiment : https://github.com Sample command : -python visualize.py -seq_length 1000 -cuda -load_model mlstm_ns.pt -temperature 0.4 -neuron 2388 -init "I couldn't figure out" +python visualize.py -seq_length 1000 -cuda -load_model mlstm_ns.pt -temperature 0.4 -neuron 2388 -mode "show" -init "I couldn't figure out" Click on release to get model file mlstm_ns.pt or numpy weights. diff --git a/convert_to_cpu.py b/convert_to_cpu.py index a7e14ec..c9fa17b 100644 --- a/convert_to_cpu.py +++ b/convert_to_cpu.py @@ -1,30 +1,24 @@ -import os -import torch -from torch.autograd import Variable -from torch import optim -import torch.nn.functional as F -import torch.nn as nn import argparse -import models +import torch parser = argparse.ArgumentParser(description='convert_to_cpu.py') parser.add_argument('-load_model', default='', - help="""Model filename to load and convert.""") - -opt = parser.parse_args() + help="""Model filename to load and convert.""") + +opt = parser.parse_args() checkpoint = torch.load(opt.load_model) embed = checkpoint['embed'] rnn = checkpoint['rnn'] checkpoint = { - 'rnn': rnn.cpu(), - 'embed': embed.cpu(), - 'opt': checkpoint['opt'], - 'epoch': checkpoint['epoch'] - } + 'rnn': rnn.cpu(), + 'embed': embed.cpu(), + 'opt': checkpoint['opt'], + 'epoch': checkpoint['epoch'] +} save_file = opt.load_model + '.cpu' -print('Saving to '+ save_file) +print('Saving to ' + save_file) torch.save(checkpoint, save_file) diff --git a/lm.py b/lm.py index fa27eae..6673a4b 100644 --- a/lm.py +++ b/lm.py @@ -1,14 +1,14 @@ +import argparse +import math import os +import time + import torch -from torch.autograd import Variable -from torch import optim -import torch.nn.functional as F import torch.nn as nn -import numpy as np +from torch import optim +from torch.autograd import Variable + import models -import argparse -import time -import math parser = argparse.ArgumentParser(description='lm.py') @@ -19,7 +19,7 @@ parser.add_argument('-train', default='data/input.txt', help="""Text filename for training""") parser.add_argument('-valid', default='data/valid.txt', - help="""Text filename for validation""") + help="""Text filename for validation""") parser.add_argument('-rnn_type', default='mlstm', help='mlstm, lstm or gru') parser.add_argument('-layers', type=int, default=1, @@ -42,73 +42,70 @@ parser.add_argument('-clip', type=float, default=5, help="""Clip gradients at this value.""") parser.add_argument('--seed', type=int, default=1234, - help='random seed') + help='random seed') # GPU parser.add_argument('-cuda', action='store_true', help="Use CUDA") - - -opt = parser.parse_args() +opt = parser.parse_args() learning_rate = opt.learning_rate path = opt.train torch.manual_seed(opt.seed) if opt.cuda: - torch.cuda.manual_seed(opt.seed) + torch.cuda.manual_seed(opt.seed) + def tokenize(path): - """Tokenizes a text file.""" - assert os.path.exists(path) - # Count bytes - with open(path, 'r') as f: - tokens = 0 - for line in f: - tokens += len(line.encode()) - - print(tokens) - # Tokenize file content - with open(path, 'r') as f: - ids = torch.ByteTensor(tokens) - token = 0 - for line in f: - - for char in line.encode(): - ids[token] = char - token += 1 - - return ids + """Tokenizes a text file.""" + assert os.path.exists(path) + # Count bytes + with open(path, 'r') as f: + tokens = 0 + for line in f: + tokens += len(line.encode()) + + print(tokens) + # Tokenize file content + with open(path, 'r') as f: + ids = torch.ByteTensor(tokens) + token = 0 + for line in f: + + for char in line.encode(): + ids[token] = char + token += 1 + + return ids + def batchify(data, bsz): nbatch = data.size(0) // bsz data = data.narrow(0, 0, nbatch * bsz) data = data.view(bsz, -1).t().contiguous() - return data - + return data batch_size = opt.batch_size -hidden_size =opt.rnn_size +hidden_size = opt.rnn_size input_size = opt.embed_size data_size = 256 TIMESTEPS = opt.seq_length -if len(opt.load_model)>0: +if len(opt.load_model) > 0: checkpoint = torch.load(opt.load_model) embed = checkpoint['embed'] rnn = checkpoint['rnn'] else: embed = nn.Embedding(256, input_size) if opt.rnn_type == 'gru': - rnn = models.StackedRNN(nn.GRUCell, opt.layers, input_size, hidden_size, data_size, opt.dropout) + rnn = models.StackedRNN(nn.GRUCell, opt.layers, input_size, hidden_size, data_size, opt.dropout) elif opt.rnn_type == 'mlstm': - rnn = models.StackedLSTM(models.mLSTM, opt.layers, input_size, hidden_size, data_size, opt.dropout) - else:#default to lstm - rnn = models.StackedLSTM(nn.LSTMCell, opt.layers, input_size, hidden_size, data_size, opt.dropout) - + rnn = models.StackedLSTM(models.mLSTM, opt.layers, input_size, hidden_size, data_size, opt.dropout) + else: # default to lstm + rnn = models.StackedLSTM(nn.LSTMCell, opt.layers, input_size, hidden_size, data_size, opt.dropout) - -loss_fn = nn.CrossEntropyLoss() +loss_fn = nn.CrossEntropyLoss() nParams = sum([p.nelement() for p in rnn.parameters()]) print('* number of parameters: %d' % nParams) @@ -117,21 +114,23 @@ def batchify(data, bsz): valid = tokenize(opt.valid) valid = batchify(valid, batch_size) -learning_rate =opt.learning_rate +learning_rate = opt.learning_rate -n_batch = text.size(0)//TIMESTEPS -nv_batch = valid.size(0)//TIMESTEPS +n_batch = text.size(0) // TIMESTEPS +nv_batch = valid.size(0) // TIMESTEPS print(text.size(0)) print(n_batch) embed_optimizer = optim.SGD(embed.parameters(), lr=learning_rate) rnn_optimizer = optim.SGD(rnn.parameters(), lr=learning_rate) - + + def update_lr(optimizer, lr): for group in optimizer.param_groups: group['lr'] = lr return - + + def clip_gradient_coeff(model, clip): """Computes a gradient clipping coefficient based on gradient norm.""" totalnorm = 0 @@ -141,6 +140,7 @@ def clip_gradient_coeff(model, clip): totalnorm = math.sqrt(totalnorm) return min(1, clip / (totalnorm + 1e-6)) + def calc_grad_norm(model): """Computes a gradient clipping coefficient based on gradient norm.""" totalnorm = 0 @@ -148,7 +148,8 @@ def calc_grad_norm(model): modulenorm = p.grad.data.norm() totalnorm += modulenorm ** 2 return math.sqrt(totalnorm) - + + def calc_grad_norms(model): """Computes a gradient clipping coefficient based on gradient norm.""" norms = [] @@ -156,107 +157,111 @@ def calc_grad_norms(model): modulenorm = p.grad.data.norm() norms += [modulenorm] return norms - + + def clip_gradient(model, clip): """Clip the gradient.""" totalnorm = 0 for p in model.parameters(): - p.grad.data = p.grad.data.clamp(-clip,clip) + p.grad.data = p.grad.data.clamp(-clip, clip) + - def make_cuda(state): if isinstance(state, tuple): - return (state[0].cuda(), state[1].cuda()) + return (state[0].cuda(), state[1].cuda()) else: - return state.cuda() - + return state.cuda() + + def copy_state(state): if isinstance(state, tuple): - return (Variable(state[0].data), Variable(state[1].data)) + return (Variable(state[0].data), Variable(state[1].data)) else: - return Variable(state.data) + return Variable(state.data) def evaluate(): - hidden_init = rnn.state0(opt.batch_size) + hidden_init = rnn.state0(opt.batch_size) if opt.cuda: - embed.cuda() - rnn.cuda() - hidden_init = make_cuda(hidden_init) + embed.cuda() + rnn.cuda() + hidden_init = make_cuda(hidden_init) loss_avg = 0 - for s in range(nv_batch-1): - batch = Variable(valid.narrow(0,s*TIMESTEPS,TIMESTEPS+1).long()) + for s in range(nv_batch - 1): + batch = Variable(valid.narrow(0, s * TIMESTEPS, TIMESTEPS + 1).long()) start = time.time() hidden = hidden_init if opt.cuda: batch = batch.cuda() loss = 0 - for t in range(TIMESTEPS): + for t in range(TIMESTEPS): emb = embed(batch[t]) hidden, output = rnn(emb, hidden) - loss += loss_fn(output, batch[t+1]) + loss += loss_fn(output, batch[t + 1]) hidden_init = copy_state(hidden) - loss_avg = loss_avg + loss.data[0]/TIMESTEPS + loss_avg = loss_avg + loss.data[0] / TIMESTEPS if s % 10 == 0: - print('v %s / %s loss %.4f loss avg %.4f time %.4f' % ( s, nv_batch, loss.data[0]/TIMESTEPS, loss_avg/(s+1), time.time()-start)) - return loss_avg/nv_batch + print('v %s / %s loss %.4f loss avg %.4f time %.4f' % ( + s, nv_batch, loss.data[0] / TIMESTEPS, loss_avg / (s + 1), time.time() - start)) + return loss_avg / nv_batch + def train_epoch(epoch): - hidden_init = rnn.state0(opt.batch_size) - if opt.cuda: - embed.cuda() - rnn.cuda() - hidden_init = make_cuda(hidden_init) - - loss_avg = 0 - - for s in range(n_batch-1): - - embed_optimizer.zero_grad() - rnn_optimizer.zero_grad() - batch = Variable(text.narrow(0,s*TIMESTEPS,TIMESTEPS+1).long()) - start = time.time() - hidden = hidden_init - if opt.cuda: - batch = batch.cuda() - loss = 0 - for t in range(TIMESTEPS): - emb = embed(batch[t]) - hidden, output = rnn(emb, hidden) - loss += loss_fn(output, batch[t+1]) - - - loss.backward() - - hidden_init = copy_state(hidden) - gn =calc_grad_norm(rnn) - clip_gradient(rnn, opt.clip) - clip_gradient(embed, opt.clip) - embed_optimizer.step() - rnn_optimizer.step() - loss_avg = .99*loss_avg + .01*loss.data[0]/TIMESTEPS - if s % 10 == 0: - print('e%s %s / %s loss %.4f loss avg %.4f time %.4f grad_norm %.4f' % (epoch, s, n_batch, loss.data[0]/TIMESTEPS, loss_avg, time.time()-start, gn)) + hidden_init = rnn.state0(opt.batch_size) + if opt.cuda: + embed.cuda() + rnn.cuda() + hidden_init = make_cuda(hidden_init) + + loss_avg = 0 + + for s in range(n_batch - 1): + + embed_optimizer.zero_grad() + rnn_optimizer.zero_grad() + batch = Variable(text.narrow(0, s * TIMESTEPS, TIMESTEPS + 1).long()) + start = time.time() + hidden = hidden_init + if opt.cuda: + batch = batch.cuda() + loss = 0 + for t in range(TIMESTEPS): + emb = embed(batch[t]) + hidden, output = rnn(emb, hidden) + loss += loss_fn(output, batch[t + 1]) + + loss.backward() + + hidden_init = copy_state(hidden) + gn = calc_grad_norm(rnn) + clip_gradient(rnn, opt.clip) + clip_gradient(embed, opt.clip) + embed_optimizer.step() + rnn_optimizer.step() + loss_avg = .99 * loss_avg + .01 * loss.data[0] / TIMESTEPS + if s % 10 == 0: + print('e%s %s / %s loss %.4f loss avg %.4f time %.4f grad_norm %.4f' % ( + epoch, s, n_batch, loss.data[0] / TIMESTEPS, loss_avg, time.time() - start, gn)) for e in range(10): - try: - train_epoch(e) - except KeyboardInterrupt: - print('Exiting from training early') - loss_avg = evaluate() - checkpoint = { - 'rnn': rnn, - 'embed': embed, - 'opt': opt, - 'epoch': e - } - save_file = ('%s_e%s_%.2f.pt' % (opt.save_model, e, loss_avg)) - print('Saving to '+ save_file) - torch.save(checkpoint, save_file) - learning_rate *= 0.7 - update_lr(rnn_optimizer, learning_rate) - update_lr(embed_optimizer, learning_rate) + try: + train_epoch(e) + except KeyboardInterrupt: + print('Exiting from training early') + loss_avg = evaluate() + checkpoint = { + 'rnn': rnn, + 'embed': embed, + 'opt': opt, + 'epoch': e + } + save_file = ('%s_e%s_%.2f.pt' % (opt.save_model, e, loss_avg)) + print('Saving to ' + save_file) + torch.save(checkpoint, save_file) + learning_rate *= 0.7 + update_lr(rnn_optimizer, learning_rate) + update_lr(embed_optimizer, learning_rate) diff --git a/load_from_numpy.py b/load_from_numpy.py index 81e6f8c..3f131f2 100644 --- a/load_from_numpy.py +++ b/load_from_numpy.py @@ -1,15 +1,10 @@ -import os +import argparse + +import numpy as np import torch -from torch.autograd import Variable -from torch import optim -import torch.nn.functional as F import torch.nn as nn -import numpy as np -import models -import argparse -import time -import math +import models parser = argparse.ArgumentParser(description='load_from_numpy.py') @@ -20,7 +15,7 @@ parser.add_argument('-train', default='data/input.txt', help="""Text filename for training""") parser.add_argument('-valid', default='data/valid.txt', - help="""Text filename for validation""") + help="""Text filename for validation""") parser.add_argument('-rnn_type', default='mlstm', help='mlstm, lstm or gru') parser.add_argument('-layers', type=int, default=1, @@ -43,13 +38,12 @@ parser.add_argument('-clip', type=float, default=5, help="""Clip gradients at this value.""") parser.add_argument('--seed', type=int, default=1234, - help='random seed') + help='random seed') # GPU parser.add_argument('-cuda', action='store_true', help="Use CUDA") - -opt = parser.parse_args() +opt = parser.parse_args() embed = nn.Embedding(256, opt.embed_size) rnn = models.StackedLSTM(models.mLSTM, opt.layers, opt.embed_size, opt.rnn_size, 256, opt.dropout) @@ -67,7 +61,7 @@ 'embed': embed, 'opt': opt, 'epoch': 0 - } +} save_file = opt.save_model -print('Saving to '+ save_file) +print('Saving to ' + save_file) torch.save(checkpoint, save_file) diff --git a/models.py b/models.py index 5f5675b..f377fa2 100644 --- a/models.py +++ b/models.py @@ -1,42 +1,39 @@ -import numpy as np import torch import torch.nn as nn -from torch.autograd import Variable -from torch import optim import torch.nn.functional as F +from torch.autograd import Variable + class mLSTM(nn.Module): + def __init__(self, data_size, hidden_size, n_layers=1): + super(mLSTM, self).__init__() + + self.hidden_size = hidden_size + self.data_size = data_size + self.n_layers = n_layers + input_size = data_size + hidden_size - def __init__(self, data_size, hidden_size, n_layers = 1): - super(mLSTM, self).__init__() - - self.hidden_size = hidden_size - self.data_size = data_size - self.n_layers = n_layers - input_size = data_size + hidden_size - - - self.wx = nn.Linear(data_size, 4*hidden_size, bias = False) - self.wh = nn.Linear(hidden_size, 4*hidden_size, bias = True) - self.wmx = nn.Linear(data_size, hidden_size, bias = False) - self.wmh = nn.Linear(hidden_size, hidden_size, bias = False) - - def forward(self, data, last_hidden): + self.wx = nn.Linear(data_size, 4 * hidden_size, bias=False) + self.wh = nn.Linear(hidden_size, 4 * hidden_size, bias=True) + self.wmx = nn.Linear(data_size, hidden_size, bias=False) + self.wmh = nn.Linear(hidden_size, hidden_size, bias=False) - hx, cx = last_hidden - m = self.wmx(data) * self.wmh(hx) - gates = self.wx(data) + self.wh(m) - i, f, o, u = gates.chunk(4, 1) + def forward(self, data, last_hidden): + hx, cx = last_hidden + m = self.wmx(data) * self.wmh(hx) + gates = self.wx(data) + self.wh(m) + i, f, o, u = gates.chunk(4, 1) - i = F.sigmoid(i) - f = F.sigmoid(f) - u = F.tanh(u) - o = F.sigmoid(o) + i = F.sigmoid(i) + f = F.sigmoid(f) + u = F.tanh(u) + o = F.sigmoid(o) - cy = f * cx + i * u - hy = o * F.tanh(cy) + cy = f * cx + i * u + hy = o * F.tanh(cy) + + return hy, cy - return hy, cy class StackedLSTM(nn.Module): def __init__(self, cell, num_layers, input_size, rnn_size, output_size, dropout): @@ -45,7 +42,7 @@ def __init__(self, cell, num_layers, input_size, rnn_size, output_size, dropout) self.num_layers = num_layers self.rnn_size = rnn_size self.h2o = nn.Linear(rnn_size, output_size) - + self.layers = [] for i in range(num_layers): layer = cell(input_size, rnn_size) @@ -59,9 +56,9 @@ def forward(self, input, hidden): for i, layer in enumerate(self.layers): h_1_i, c_1_i = layer(input, (h_0[i], c_0[i])) if i == 0: - input = h_1_i + input = h_1_i else: - input = input + h_1_i + input = input + h_1_i if i != len(self.layers): input = self.dropout(input) h_1 += [h_1_i] @@ -71,9 +68,9 @@ def forward(self, input, hidden): c_1 = torch.stack(c_1) output = self.h2o(input) - return (h_1, c_1),output - + return (h_1, c_1), output + def state0(self, batch_size): - h_0 = Variable(torch.zeros(self.num_layers, batch_size, self.rnn_size), requires_grad=False) - c_0 = Variable(torch.zeros(self.num_layers, batch_size, self.rnn_size), requires_grad=False) - return (h_0, c_0) + h_0 = Variable(torch.zeros(self.num_layers, batch_size, self.rnn_size), requires_grad=False) + c_0 = Variable(torch.zeros(self.num_layers, batch_size, self.rnn_size), requires_grad=False) + return (h_0, c_0) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c8f4d7a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +numpy==1.15.0 +pandas==0.23.3 +Pillow==5.2.0 +python-dateutil==2.7.3 +pytz==2018.5 +six==1.11.0 +torch==0.4.1 +torchvision==0.2.1 diff --git a/visualize.py b/visualize.py index 8f8ee2f..9022fd1 100644 --- a/visualize.py +++ b/visualize.py @@ -1,34 +1,12 @@ -import os -import torch -from torch.autograd import Variable -from torch import optim -import torch.nn.functional as F -import torch.nn as nn import argparse -import models +import ast import math - -parser = argparse.ArgumentParser(description='sample.py') - -parser.add_argument('-init', default='The meaning of life is ', - help="""Initial text """) -parser.add_argument('-load_model', default='', - help="""Model filename to load""") -parser.add_argument('-seq_length', type=int, default=50, - help="""Maximum sequence length""") -parser.add_argument('-temperature', type=float, default=0.4, - help="""Temperature for sampling.""") -parser.add_argument('-neuron', type=int, default=0, - help="""Neuron to read.""") -parser.add_argument('-overwrite', type=float, default=0, - help="""Value used to overwrite the neuron. 0 means don't overwrite.""") -parser.add_argument('-layer', type=int, default=-1, - help="""Layer to read. -1 = last layer""") -# GPU -parser.add_argument('-cuda', action='store_true', - help="""Use CUDA""") - -opt = parser.parse_args() +import pickle +import timeit +import pandas as pd +import torch +import torch.nn.functional as F +from torch.autograd import Variable def batchify(data, bsz): @@ -41,140 +19,217 @@ def batchify(data, bsz): nbatch = ids.size(0) // bsz ids = ids.narrow(0, 0, nbatch * bsz) ids = ids.view(bsz, -1).t().contiguous() - return ids + return ids, data def color(p): - p = math.tanh(3*p)*.5+.5 - q = 1.-p*1.3 - r = 1.-abs(0.5-p)*1.3+.3*q - p=1.3*p-.3 - i = int(p*255) - j = int(q*255) - k = int(r*255) - if j<0: - j=0 - if k<0: - k=0 - if k >255: - k=255 - if i<0: - i = 0 - return ('\033[38;2;%d;%d;%dm' % (j, k, i)).encode() - - - -batch_size = 1 + p = math.tanh(3 * p) * .5 + .5 + q = 1. - p * 1.3 + r = 1. - abs(0.5 - p) * 1.3 + .3 * q + p = 1.3 * p - .3 + i = int(p * 255) + j = int(q * 255) + k = int(r * 255) + if j < 0: + j = 0 + if k < 0: + k = 0 + if k > 255: + k = 255 + if i < 0: + i = 0 + return ('\033[38;2;%d;%d;%dm' % (j, k, i)).encode() -checkpoint = torch.load(opt.load_model) -embed = checkpoint['embed'] -rnn = checkpoint['rnn'] - -loss_fn = nn.CrossEntropyLoss() - - -text = batchify(opt.init, batch_size) def make_cuda(state): if isinstance(state, tuple): - return (state[0].cuda(), state[1].cuda()) + return (state[0].cuda(), state[1].cuda()) else: - return state.cuda() - -batch = Variable(text) -states = rnn.state0(batch_size) -if isinstance(states, tuple): - hidden, cell = states -else: - hidden = states -last = hidden.size(0)-1 -if opt.layer <= last and opt.layer >= 0: - last = opt.layer - -if opt.cuda: - batch =batch.cuda() - states = make_cuda(states) - embed.cuda() - rnn.cuda() - -loss_avg = 0 -loss = 0 -gen = bytearray() -for t in range(text.size(0)): - emb = embed(batch[t]) - ni = (batch[t]).data[0] - states, output = rnn(emb, states) + return state.cuda() + + +def rnn_infer(text, states, batch, embed, rnn): if isinstance(states, tuple): hidden, cell = states else: hidden = states - feat = hidden.data[last,0,opt.neuron] - if ni< 128: - col = color(feat) - gen+=(col) - gen.append(ni) + last = hidden.size(0) - 1 + if opt.layer <= last and opt.layer >= 0: + last = opt.layer -print(opt.init) - - -if opt.temperature == 0: - topv, topi = output.data.topk(1) - ni = topi[0][0] - gen.append(ni) - inp = Variable(topi[0], volatile=True) if opt.cuda: - inp = inp.cuda() + batch = batch.cuda() + states = make_cuda(states) + embed.cuda() + rnn.cuda() + + sentiment_values = [] + gen = bytearray() + for t in range(text.size(0)): + emb = embed(batch[t]) + ni = (batch[t]).data[0] + states, output = rnn(emb, states) + if isinstance(states, tuple): + hidden, cell = states + else: + hidden = states + feat = hidden.data[last, 0, opt.neuron] + sentiment_values.append(feat.data.tolist()) + if ni < 128: + col = color(feat) + gen += (col) + gen.append(ni) - for t in range(opt.seq_length): - - emb = embed(inp) - states, output = rnn(emb, states) + if opt.temperature == 0: topv, topi = output.data.topk(1) ni = topi[0][0] gen.append(ni) - inp = Variable(topi[0]) + inp = Variable(topi[0], volatile=True) if opt.cuda: - inp = inp.cuda() - -else: - probs = F.softmax(output[0].squeeze().div(opt.temperature)).data.cpu() - ni = torch.multinomial(probs,1)[0] - feat = hidden.data[last,0,opt.neuron] - - if ni < 128: - col = color(feat) - gen+=(col) - - gen.append(ni) - - - inp = Variable(torch.LongTensor([ni]), volatile=True) - if opt.cuda: - inp = inp.cuda() - for t in range(opt.seq_length): - - emb = embed(inp) - states, output = rnn(emb, states) - if isinstance(states, tuple): - hidden, cell = states - else: - hidden = states - feat = hidden.data[last,0,opt.neuron] - if isinstance(output, list): - output =output[0] - probs = F.softmax(output.squeeze().div(opt.temperature)).data.cpu() - ni = torch.multinomial(probs,1)[0] - - if ni< 128: - col = color(feat) - gen+=(col) + inp = inp.cuda() + + for t in range(opt.seq_length): + + emb = embed(inp) + states, output = rnn(emb, states) + topv, topi = output.data.topk(1) + ni = topi[0][0] + gen.append(ni) + inp = Variable(topi[0]) + if opt.cuda: + inp = inp.cuda() + + else: + probs = F.softmax(output[0].squeeze().div(opt.temperature)).data.cpu() + ni = torch.multinomial(probs, 1)[0] + feat = hidden.data[last, 0, opt.neuron] + + if ni < 128: + col = color(feat) + gen += (col) + gen.append(ni) - inp = Variable(torch.LongTensor([ni])) + + inp = Variable(torch.LongTensor([ni]), volatile=True) if opt.cuda: - inp = inp.cuda() - if opt.overwrite != 0: - hidden.data[last,0,opt.neuron] = opt.overwrite + inp = inp.cuda() + for t in range(opt.seq_length): + + emb = embed(inp) + states, output = rnn(emb, states) + if isinstance(states, tuple): + hidden, cell = states + else: + hidden = states + feat = hidden.data[last, 0, opt.neuron] + if isinstance(output, list): + output = output[0] + probs = F.softmax(output.squeeze().div(opt.temperature)).data.cpu() + ni = torch.multinomial(probs, 1)[0] + + if ni < 128: + col = color(feat) + gen += (col) + gen.append(ni) + inp = Variable(torch.LongTensor([ni])) + if opt.cuda: + inp = inp.cuda() + if opt.overwrite != 0: + hidden.data[last, 0, opt.neuron] = opt.overwrite + + return gen, sentiment_values + + +def main(opt): + batch_size = 1 + checkpoint = torch.load(opt.load_model) + embed = checkpoint['embed'] + rnn = checkpoint['rnn'] + + if opt.mode == 'save_set': + + # store clean used characters and its predicted sentiment as a list of dicts + analyzed_texts = [] + + # init input texts as list of texts + + if type(opt.init) == str: + if opt.init[-4:] == '.csv': + list_texts = pd.read_csv(opt.init) + list_texts = list_texts['text_en'].tolist() + else: + list_texts = ast.literal_eval(opt.init) + else: + list_texts = opt.init + + start = timeit.default_timer() + for t in list_texts: + try: + sent_text = {} + text, text_clean = batchify(t, batch_size) + batch = Variable(text) + states = rnn.state0(batch_size) + gen, sentiment_values = rnn_infer(text, states, batch, embed, rnn) -gen+=('\033[0m').encode() + # Save cleaned text and sentiment per character into its dict + sent_text['text'] = text_clean + sent_text['sentiment'] = sentiment_values + analyzed_texts.append(sent_text) -print(gen.decode("utf-8",errors = 'ignore' )) + except Exception as exp: + print(f"There was a failure in text {t}: {exp}") + pickle.dump(analyzed_texts, open(opt.pickle + '.checkpoint', "wb")) + + pickle.dump(analyzed_texts, open(opt.pickle, "wb")) + stop = timeit.default_timer() + time_cost = stop - start + print(f"It takes {time_cost}s to calculate the sentiment of {len(list_texts)} texts.") + + + else: + text, text_clean = batchify(opt.init, batch_size) + batch = Variable(text) + states = rnn.state0(batch_size) + + if opt.mode == 'show': + + gen, sentiment_values = rnn_infer(text, states, batch, embed, rnn) + gen += ('\033[0m').encode() + print(gen.decode("utf-8", errors='ignore')) + + elif opt.mode == 'save_text': + gen, sentiment_values = rnn_infer(text, states, batch, embed, rnn) + + sentiment = {} + sentiment['text'] = text_clean + sentiment['sentiment'] = sentiment_values + pickle.dump(sentiment, open(opt.pickle, "wb")) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='sample.py') + + parser.add_argument('-init', default='The meaning of life is ', + help="""Initial text or list of texts""") + parser.add_argument('-mode', choices=['show', 'save_text', 'save_set'], default='show') + parser.add_argument('-load_model', default='', + help="""Model filename to load""") + parser.add_argument('-seq_length', type=int, default=50, + help="""Maximum sequence length""") + parser.add_argument('-temperature', type=float, default=0.4, + help="""Temperature for sampling.""") + parser.add_argument('-neuron', type=int, default=0, + help="""Neuron to read.""") + parser.add_argument('-overwrite', type=float, default=0, + help="""Value used to overwrite the neuron. 0 means don't overwrite.""") + parser.add_argument('-layer', type=int, default=-1, + help="""Layer to read. -1 = last layer""") + parser.add_argument('-pickle', default="sentiment.pkl", + help="""Name of file to save sentiment results""") + # GPU + parser.add_argument('-cuda', action='store_true', + help="""Use CUDA""") + + opt = parser.parse_args() + + main(opt)