DFKI-NLP / thermostat

Collection of NLP model explanations and accompanying analysis tools

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Prediction Values in Dataset

tpatzelt opened this issue · comments

commented

Hello,
I am experimenting with the attribution values of Layer Integrated Gradients on the AlbertV2 model on the imdb dataset. Along the way, I noticed a mismatch between the predictions saved in each instance in a dataset and the output of the model if loaded and called separately. I hope the following code sample makes clear what I mean:

import thermostat
import torch
from transformers import AutoModelForSequenceClassification

data = thermostat.load("imdb-albert-lig")

albert = AutoModelForSequenceClassification.from_pretrained(data.model_name, return_dict=False)
albert.eval()

sliced_data = data[:10]
thermostat_preds = [instance.predictions for instance in sliced_data]

batch_input = torch.tensor([instance.input_ids for instance in sliced_data])
preds = albert(batch_input)[0]

print("thermostat  ---  new inference".center(89, " "))
for m, n in zip(thermostat_preds, preds.tolist()):
    print(m, " --- ", n)

outputs:

Loading Thermostat configuration: imdb-albert-lig
Reusing dataset thermostat (/home/tim/.cache/huggingface/datasets/thermostat/imdb-albert-lig/1.0.1/0cbe93e1fbe5b8ed0217559442d8b49a80fd4c2787185f2d7940817c67d8707b)
                              thermostat  ---  new inference                             
[-2.9755005836486816, 3.422632932662964]  ---  [0.5287008285522461, 0.11485755443572998]
[-2.1383304595947266, 2.6063592433929443]  ---  [0.5254676938056946, 0.11936521530151367]
[-2.891936779022217, 3.3106441497802734]  ---  [0.5285712480545044, 0.11505177617073059]
[-3.0642969608306885, 3.240943670272827]  ---  [0.5282390117645264, 0.11541029810905457]
[-3.1076266765594482, 3.050632953643799]  ---  [0.5288912057876587, 0.11466512084007263]
[-2.8576371669769287, 3.023214101791382]  ---  [0.5283359885215759, 0.12018033862113953]
[-1.8885599374771118, 2.4350857734680176]  ---  [0.5438214540481567, 0.12777245044708252]
[-1.5720579624176025, 2.051628589630127]  ---  [0.5284878611564636, 0.11513140797615051]
[-3.2173707485198975, 3.510160207748413]  ---  [0.5282713174819946, 0.11538228392601013]
[-2.5653769969940186, 3.0336244106292725]  ---  [-2.5653772354125977, 3.033625841140747]

I only checked for that particular dataset and model, but I am wondering what causes the mismatch here? My suspicion is that either the model changed or the input_ids from the dataset do not correspond to the exact input used to create the dataset. Maybe you can shed some light on this?
Thank you already for this useful library and if there are further questions please contact me, Tim

Hi Tim,
thanks a lot for your support and interest!

First of all, I tested your code and could reproduce this mismatch as shown above.

I can already rule out versioning: I tried the dependencies I originally used and since I haven't specific a version string for transformers, things could have been changed, but the result stayed the same.

The model has not changed either. The last edit was last year and I worked on Thermostat in May and June primarily: https://huggingface.co/textattack/albert-base-v2-imdb/tree/main

The dataset is in the right order as well. I tokenized the IMDb again and it resulted in the same IDs.

The predictions were not produced in the same way as this:

preds = albert(batch_input)[0]

...but rather uses the attention mask and token type IDs as well:

def bert_forward(input_ids, attention_mask, token_type_ids):
input_model = {
'input_ids': input_ids.long(), # TODO: Is the cast to long necessary?
'attention_mask': attention_mask.long(),
'token_type_ids': token_type_ids.long(),
}
output_model = model(**input_model)[0]
return output_model

I attend EMNLP this week to present Thermostat, so I won't be able to test it out properly, so unfortunately I have to leave it like that until I'm back in around two weeks from now.

commented

Thank you for responding that quick!
I had some time to look into it again and find the cause of the mismatch. The model has a required input length of 512. It outputs different scores depending on whether the input_ids are already padded with zero (as it is saved in the thermostat object) or they are not padded and passed to the model with a short length. Please consider the following code example:

import thermostat
import torch
from transformers import AutoModelForSequenceClassification

data = thermostat.load("imdb-albert-lig")

albert = AutoModelForSequenceClassification.from_pretrained(data.model_name, return_dict=False)
albert.eval()

instance = data[0]
thermostat_preds = instance.predictions  # [-2.9755005836486816, 3.422632932662964]
input = torch.tensor([instance.input_ids])
input_without_padding = input[:, :179]

new_preds = albert(input)[0]  # [0.5287, 0.1149]
new_preds_without_padding = albert(input_without_padding)[0]  # [-2.9755,  3.4226]

assert not torch.all(torch.isclose(new_preds, torch.tensor([thermostat_preds])))
assert torch.all(torch.isclose(new_preds_without_padding, torch.tensor([thermostat_preds])))

I looked at the text of that sample and it is clear that the logits in instance.predictions and new_preds_without_padding are correct since the sample is "positive". It is still unclear to me why the predictions are wrong if the input is padded, but that is not a issue with thermostat. I can continue working by passing the unpadded input_ids to the model, so i will close this issue.
Thanks again and enjoy EMNLP!

Thank you so much for your thorough documentation on this!
Yes, the padding is definitely the culprit here.
Glad you found it and that the Thermostat results are verified in this regard.