Open tsutsen opened 3 years ago
Thank you for the quick reply, @golsun !
I've tried to adapt the code from GPT2Generator
and Integrated
to get it working with Transformers' model card but I get the error 'GPT2ForSequenceClassification' object has no attribute 'predict'
on the line scores_ranker = self.ranker.predict(cxt, hyps)
Which predict
method should I use for the ranker? The one in model.py or the one in score.py?
The code:
model = AutoModelForCausalLM.from_pretrained("microsoft/DialoGPT-small")
tokenizer = AutoTokenizer.from_pretrained("microsoft/DialoGPT-small")
modelRPT = AutoModelForSequenceClassification.from_pretrained('microsoft/DialogRPT-human-vs-machine')
tokenizerRPT = AutoTokenizer.from_pretrained('microsoft/DialogRPT-human-vs-machine')
class Generator:
def __init__(self):
self.tokenizer = AutoTokenizer.from_pretrained("microsoft/DialoGPT-small")
self.model = AutoModelForCausalLM.from_pretrained("microsoft/DialoGPT-small")
self.ix_EOS = tokenizer.eos_token_id
self.model.eval()
self.cuda = True
self.model.cuda()
def tokenize(self, cxt):
turns = cxt.split(tokenizer.eos_token)
ids = []
for turn in turns:
ids += self.tokenizer.encode(turn.strip()) + [self.ix_EOS]
ids = torch.tensor([ids]).view(1, -1)
if self.cuda:
ids = ids.cuda()
return ids
def predict_sampling(self, cxt, temperature=0.7, n_hyp=5, max_t=30):
""" sampling tokens based on predicted probability """
tokens = self.tokenize(cxt)
tokens = tokens.repeat(n_hyp, 1)
len_cxt = tokens.shape[1]
sum_logP = [0] * n_hyp
live = [True] * n_hyp
seqs = [[] for _ in range(n_hyp)]
np.random.seed(2020)
for _ in range(max_t):
outputs = self.model(tokens)
predictions = outputs[0]
prob = torch.softmax(predictions[:, -1, :] / temperature, dim=-1)
if self.cuda:
prob = prob.cpu()
prob = prob.detach().numpy()
vocab = prob.shape[-1]
next_tokens = []
for i in range(n_hyp):
next_token = np.random.choice(vocab, p=prob[i,:])
next_tokens.append(next_token)
if not live[i]:
continue
sum_logP[i] += np.log(prob[i, next_token])
seqs[i].append(next_token)
if next_token == self.ix_EOS:
live[i] = False
continue
next_tokens = torch.LongTensor(next_tokens).view(-1, 1)
if self.cuda:
next_tokens = next_tokens.cuda()
tokens = torch.cat([tokens, next_tokens], dim=-1)
ret = []
for i in range(n_hyp):
if live[i]: # only return hyp that ends with EOS
continue
prob = np.exp(sum_logP[i] / (len(seqs[i]) + 1))
hyp = self.tokenizer.decode(seqs[i][:-1]) # strip EOS
ret.append((prob, hyp))
return ret
def play(self, params):
while True:
cxt = input('\nContext:\t')
if not cxt:
break
ret = self.predict(cxt, **params)
for prob, hyp in sorted(ret, reverse=True):
print('%.3f\t%s'%(prob, hyp))
class Integrated:
def __init__(self, generator, ranker):
self.generator = generator
self.ranker = ranker
def predict(self, cxt, wt_ranker, params):
with torch.no_grad():
prob_hyp = self.generator.predict_sampling(cxt, **params)
probs = np.array([prob for prob, _ in prob_hyp])
hyps = [hyp for _, hyp in prob_hyp]
if wt_ranker > 0:
scores_ranker = self.ranker.predict(cxt, hyps)
if isinstance(scores_ranker, dict):
scores_ranker = scores_ranker['final']
scores = wt_ranker * scores_ranker + (1 - wt_ranker) * probs
else:
scores = probs
ret = []
for i in range(len(hyps)):
ret.append((scores[i], probs[i], scores_ranker[i], hyps[i]))
ret = sorted(ret, reverse=True)
return ret
generator = Generator()
params = {'temperature': 0.7, 'n_hyp': 5}
Integrated(generator, modelRPT).predict('How are you?', 1, params)
The error:
AttributeError Traceback (most recent call last)
<ipython-input-11-ef5210f29a1f> in <module>
103 params = {'temperature': 0.7, 'n_hyp': 5}
104
--> 105 Integrated(generator, modelRPT).predict('How are you?', 1, params)
<ipython-input-11-ef5210f29a1f> in predict(self, cxt, wt_ranker, params)
88 hyps = [hyp for _, hyp in prob_hyp]
89 if wt_ranker > 0:
---> 90 scores_ranker = self.ranker.predict(cxt, hyps)
91 if isinstance(scores_ranker, dict):
92 scores_ranker = scores_ranker['final']
/usr/lib/python3.9/site-packages/torch/nn/modules/module.py in __getattr__(self, name)
945 if name in modules:
946 return modules[name]
--> 947 raise AttributeError("'{}' object has no attribute '{}'".format(
948 type(self).__name__, name))
949
AttributeError: 'GPT2ForSequenceClassification' object has no attribute 'predict'
UPD. Nevermind, I understood how to implement it. Will put it into Colab and share a link for others in a few days.
@tsutsen, any updates?
this
Can you share the colab code? Thank you so much!
I am not satisfied with the responses that DialoGPT produces -- for the most part, they seem pretty random and AI-ish to me. I fine-tuned the model on my dataset using Transformers'
Trainer
but that did not help much – the responses are often just quotes from the dataset out of context. I want these quotes to be relevant at least, so I decided to try DialogRPT human-vs-rand and human-vs-machine.The problem is I do not understand how to rerank DialoGPT responses with DialogRPT using Transformers. Should I use DialogRPT during fine-tuning to compute loss? Or maybe it is possible to connect it as a LogitsProcessor? If yes, then how? As I understand, Transformers'
generate()
method outputs scores for every token but DialogRPT outputs a single number. How can I modify the scores of a response then?I am new to machine learning and this stuff is quite overwhelming for me; any help is very appreciated!