Skip to content

Commit 56d9d23

Browse files
Make changes to hallucination pipeline (#156)
* edit installation instructions in readme * bump up version * make small change in readme because of publish to pypi error * bump up version * refactor tabular analysis of benchmarks * make changes to hallucination pipeline
1 parent 21227b3 commit 56d9d23

File tree

4 files changed

+164
-37
lines changed

4 files changed

+164
-37
lines changed

benchmarks/hallucination/mmlu/run.py

+14-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import os
2-
import pickle
32

43
from datasets import (
54
get_dataset_config_names,
@@ -19,9 +18,11 @@
1918
CALIB_FRAC = 0.8
2019

2120
if __name__ == "__main__":
22-
device = "cuda"
23-
model_id = "gpt2"
24-
model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto")
21+
model_id = "tiiuae/falcon-7b"
22+
model = AutoModelForCausalLM.from_pretrained(
23+
model_id, device_map="auto", load_in_8bit=True
24+
)
25+
model.eval()
2526
tokenizer = AutoTokenizer.from_pretrained(model_id)
2627

2728
# download and prepare data
@@ -69,8 +70,10 @@
6970
calib_targets.append(sample["targets"])
7071
else:
7172
test_questions.append(sample["question"])
72-
test_choices.append(sample["choices"])
73-
test_targets.append(sample["targets"])
73+
# test the first answer for each question
74+
test_choices.append(sample["choices"][0])
75+
test_targets.append(sample["targets"] == 0)
76+
test_targets = np.array(test_targets)
7477

7578
# calibrate
7679
calibrator = HallucinationMulticalibrator(
@@ -83,8 +86,7 @@
8386
targets=calib_targets,
8487
)
8588

86-
with open("fitted_calibrator.pth", "wb") as filehandler:
87-
pickle.dump(calibrator, filehandler, -1)
89+
calibrator.save(f"fitted_calibrator_{model_id.replace('/', '_')}.pth")
8890

8991
# test
9092
test_probs = calibrator.predict_proba(
@@ -103,13 +105,13 @@
103105

104106
# measure
105107
mse_before = calibrator.multicalibrator.mean_squared_error(
106-
probs=test_probs, targets=np.array(test_targets)
108+
probs=test_probs, targets=test_targets
107109
)
108-
acc_before = accuracy(test_preds, np.array(test_targets))
110+
acc_before = accuracy(test_preds, test_targets)
109111
mse_after = calibrator.multicalibrator.mean_squared_error(
110-
probs=calib_test_probs, targets=np.array(test_targets)
112+
probs=calib_test_probs, targets=test_targets
111113
)
112-
acc_after = accuracy(calib_test_preds, np.array(test_targets))
114+
acc_after = accuracy(calib_test_preds, test_targets)
113115

114116
print(f"MSE before calibration: {round(float(mse_before), 4)}.")
115117
print(f"Accuracy before calibration: {round(float(acc_before), 4)}.")

fortuna/hallucination/base.py

+34-23
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import pickle
23
from typing import (
34
Callable,
45
Dict,
@@ -9,12 +10,12 @@
910
)
1011

1112
import numpy as np
12-
from sklearn.manifold import locally_linear_embedding
1313
from sklearn.mixture import GaussianMixture
1414
import torch
1515
from torch import nn
1616
from tqdm import tqdm
1717
from transformers import PreTrainedTokenizer
18+
import umap.umap_ as umap
1819

1920
from fortuna.conformal import BinaryClassificationMulticalibrator
2021
from fortuna.hallucination.grouping.clustering.base import GroupingModel
@@ -26,7 +27,7 @@ def __init__(
2627
self,
2728
generative_model: nn.Module,
2829
tokenizer: PreTrainedTokenizer,
29-
embedding_reduction_fn: Optional[Callable[[np.ndarray], np.ndarray]] = None,
30+
embedding_reduction_model: Optional = None,
3031
clustering_models: Optional[List] = None,
3132
scoring_fn: Optional[
3233
Callable[[torch.Tensor, torch.Tensor, int], torch.Tensor]
@@ -49,8 +50,8 @@ def __init__(
4950
A generative model.
5051
tokenizer: PreTrainedTokenizer
5152
A tokenizer.
52-
embedding_reduction_fn: Optional[Callable[[np.ndarray], np.ndarray]]
53-
A function aimed at reducing the embedding dimensionality.
53+
embedding_reduction_model: Optional
54+
An embedding reduction model.
5455
clustering_models: Optional[List]
5556
A list of clustering models.
5657
scoring_fn: Optional[Callable[[torch.Tensor, torch.Tensor, int], torch.Tensor]]
@@ -61,8 +62,8 @@ def __init__(
6162
if self.tokenizer.pad_token is None:
6263
self.tokenizer.pad_token = self.tokenizer.eos_token
6364
logging.info("`tokenizer.pad_token` is None. Set to `tokenizer.eos_token`.")
64-
self.embedding_reduction_fn = (
65-
embedding_reduction_fn or locally_linear_embedding_fn
65+
self.embedding_reduction_model = embedding_reduction_model or umap.UMAP(
66+
n_neighbors=20
6667
)
6768
self.scoring_fn = scoring_fn or inv_perplexity
6869
self.clustering_models = clustering_models or [
@@ -124,7 +125,7 @@ def fit(
124125
else:
125126
targets = np.array(targets)
126127

127-
embeddings = self.embedding_reduction_fn(embeddings)
128+
embeddings = self.embedding_reduction_model.fit_transform(embeddings)
128129
embeddings = np.concatenate((embeddings, scores[:, None]), axis=1)
129130

130131
self.grouping_model = GroupingModel()
@@ -147,7 +148,7 @@ def fit(
147148

148149
def predict_proba(
149150
self,
150-
texts: Union[List[str], List[List[str]]],
151+
texts: List[str],
151152
contexts: List[str],
152153
calibrate: bool = True,
153154
) -> np.ndarray:
@@ -156,7 +157,7 @@ def predict_proba(
156157
157158
Parameters
158159
----------
159-
texts: Union[List[str], List[List[str]]]
160+
texts: List[str]
160161
The texts to fit.
161162
This may either be a list of strings (e.g. a list of single answers),
162163
or a list of lists of strings (e.g. a list of multi-choice answers).
@@ -176,14 +177,14 @@ def predict_proba(
176177
(
177178
scores,
178179
embeddings,
179-
which_choices,
180+
_,
180181
) = self._compute_scores_embeddings_which_choices(
181182
texts=texts, contexts=contexts
182183
)
183184
if not calibrate:
184185
return scores
185186

186-
embeddings = self.embedding_reduction_fn(embeddings)
187+
embeddings = self.embedding_reduction_model.transform(embeddings)
187188
embeddings = np.concatenate((embeddings, scores[:, None]), axis=1)
188189

189190
group_scores = self.grouping_model.predict_proba(
@@ -195,7 +196,7 @@ def predict_proba(
195196

196197
def predict(
197198
self,
198-
texts: Union[List[str], List[List[str]]],
199+
texts: List[str],
199200
contexts: List[str],
200201
calibrate: bool = True,
201202
probs: Optional[np.ndarray] = None,
@@ -206,7 +207,7 @@ def predict(
206207
207208
Parameters
208209
----------
209-
texts: Union[List[str], List[List[str]]]
210+
texts: List[str],
210211
The texts to fit.
211212
This may either be a list of strings (e.g. a list of single answers),
212213
or a list of lists of strings (e.g. a list of multi-choice answers).
@@ -253,7 +254,7 @@ def _compute_scores_embeddings_which_choices(
253254
embeddings.append(_embeddings[which_choice, None])
254255
elif isinstance(text, str):
255256
embeddings.append(_embeddings)
256-
scores.append(_scores)
257+
scores.append(_scores[0])
257258

258259
return (
259260
np.array(scores),
@@ -278,16 +279,26 @@ def _get_logits_scores(
278279
with torch.no_grad():
279280
_logits = self.generative_model(**inputs).logits
280281

281-
_scores = self.scoring_fn(
282-
logits=_logits,
283-
labels=inputs["input_ids"],
284-
init_pos=len(context_inputs),
285-
)
282+
_scores = self.scoring_fn(
283+
logits=_logits,
284+
labels=inputs["input_ids"],
285+
init_pos=len(context_inputs),
286+
)
286287

287288
return _logits.cpu().numpy(), _scores.cpu().numpy()
288289

290+
def save(self, path):
291+
state = dict(
292+
embedding_reduction_model=self.embedding_reduction_model,
293+
grouping_model=self.grouping_model,
294+
multicalibrator=self.multicalibrator,
295+
_quantiles=self._quantiles,
296+
)
297+
298+
with open(path, "wb") as filehandler:
299+
pickle.dump(state, filehandler, -1)
289300

290-
def locally_linear_embedding_fn(x: np.ndarray) -> np.ndarray:
291-
return locally_linear_embedding(
292-
x, n_neighbors=300, n_components=200, method="modified"
293-
)[0]
301+
def load(self, path):
302+
state = pickle.load(open(path, "rb"))
303+
for k, v in state.items():
304+
setattr(self, k, v)

poetry.lock

+114-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ boto3 = {version = "^1.26.145", optional = true}
3333
hydra-core = {version = "^1.3.2", optional = true}
3434
torch = {version = "^2.1.0", optional = true}
3535
scikit-learn = {version = "^1.3.2", optional = true}
36+
umap-learn = {version = "^0.5.5", optional = true}
3637

3738
[tool.poetry.extras]
3839
docs = ["Sphinx", "sphinx-autodoc-typehints", "pydata-sphinx-theme", "nbsphinx", "nbsphinx-link",
3940
"sphinx-gallery", "ipython", "pandas", "tensorflow-datasets", "xlrd", "openpyxl", "yfinance", 'tabulate', 'pandoc']
4041
notebooks = ["jupyter"]
4142
transformers = ["transformers", "datasets"]
4243
sagemaker = ["boto3", "hydra-core", "sagemaker", "sagemaker-utils"]
43-
hallucination = ["torch", "transformers", "datasets", "scikit-learn"]
44+
hallucination = ["torch", "transformers", "datasets", "scikit-learn", "umap-learn"]
4445

4546
[tool.poetry.group.dev.dependencies]
4647
traitlets = "^5.5.0"

0 commit comments

Comments
 (0)