epsilon-compositionality

Code for our paper Measuring Idiomaticity in Text Embedding Models with 𝜀-compositionality
git clone https://esimon.eu/repos/epsilon-compositionality.git
Log | Files | Refs | Submodules | README

commit 57a8735d2128141ede3e7b5ccb176e37aa8ec864
parent ba126b546e384dedfaa083c1b48f227bae104fa3
Author: Sondre Wold <sondrewold1@gmail.com>
Date:   Wed, 27 Aug 2025 14:32:11 +0200

scripts for debugging

Diffstat:
Adebug/analyze_embeddings.py | 114+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adebug/plot_sims.py | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 201 insertions(+), 0 deletions(-)

diff --git a/debug/analyze_embeddings.py b/debug/analyze_embeddings.py @@ -0,0 +1,114 @@ +import argparse +import pathlib +import pickle + +from numpy import mean +from experiment import Point + +import pandas as pd + +from typing import Any + +import torch +from get_epsilon import get_dataset_and_model_name + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Gather epsilon values") + parser.add_argument("-points_path", type=pathlib.Path) + parser.add_argument("-result_path", type=pathlib.Path) + return parser.parse_args() + + +def main() -> None: + args = parse_args() + points_folder: str = args.points_path + raw_files = list(pathlib.Path(points_folder).glob("*.pkl")) + + final_result: dict[str, list[Any]] = { + "dataset": [], + "model": [], + "a_norm": [], + "b_norm": [], + "ac_norm": [], + "bc_norm": [], + "a_mean": [], + "b_mean": [], + "ac_mean": [], + "bc_mean": [], + "distance": [], + } + + for raw_file in raw_files: + with open(raw_file, "rb") as file: + points: list[Point] = pickle.load(file) + dataset_name, model_name = get_dataset_and_model_name(raw_file.name) + a_norms: list[float] = [] + b_norms: list[float] = [] + ac_norms: list[float] = [] + bc_norms: list[float] = [] + a_means: list[torch.Tensor] = [] + b_means: list[torch.Tensor] = [] + ac_means: list[torch.Tensor] = [] + bc_means: list[torch.Tensor] = [] + for point in points: + a_norms.append( + torch.linalg.norm(torch.Tensor(point.phrase_a_embedded)).item() + ) + b_norms.append( + torch.linalg.norm(torch.Tensor(point.phrase_b_embedded)).item() + ) + ac_norms.append( + torch.linalg.norm(torch.Tensor(point.context_ac_embedded)).item() + ) + bc_norms.append( + torch.linalg.norm(torch.Tensor(point.context_bc_embedded)).item() + ) + a_means.append(torch.Tensor(point.phrase_a_embedded)) + b_means.append(torch.Tensor(point.phrase_b_embedded)) + ac_means.append(torch.Tensor(point.context_ac_embedded)) + bc_means.append(torch.Tensor(point.context_bc_embedded)) + + final_result["dataset"].append(dataset_name) + final_result["model"].append(model_name) + final_result["a_norm"].append(mean(a_norms)) + final_result["b_norm"].append(mean(b_norms)) + final_result["ac_norm"].append(mean(ac_norms)) + final_result["bc_norm"].append(mean(bc_norms)) + + final_result["a_mean"].append( + torch.mean(torch.stack(a_means), dim=-1).norm().item() + ) + final_result["b_mean"].append( + torch.mean(torch.stack(b_means), dim=-1).norm().item() + ) + final_result["ac_mean"].append( + torch.mean(torch.stack(ac_means), dim=-1).norm().item() + ) + final_result["bc_mean"].append( + torch.mean(torch.stack(bc_means), dim=-1).norm().item() + ) + + final_result["distance"].append( + ( + ( + torch.mean(torch.stack(ac_means), dim=-1) + + torch.mean(torch.stack(bc_means), dim=-1) + ) + / 2 + - ( + torch.mean(torch.stack(a_means), dim=-1) + + torch.mean(torch.stack(b_means), dim=-1) + ) + / 2 + ) + .norm() + .item() + ) + + df = pd.DataFrame.from_dict(final_result) + print(df) + + +if __name__ == "__main__": + main() diff --git a/debug/plot_sims.py b/debug/plot_sims.py @@ -0,0 +1,87 @@ +import argparse +import pathlib +import pickle + +import numpy + +from numpy import mean +from experiment import Point + +import matplotlib.pyplot as plt + +import pandas as pd + +from typing import Any + +import torch +from get_epsilon import get_dataset_and_model_name + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Gather epsilon values") + parser.add_argument("-points_path", type=pathlib.Path) + parser.add_argument("-result_path", type=pathlib.Path) + return parser.parse_args() + + +def main() -> None: + args = parse_args() + points_folder: str = args.points_path + raw_files = list(pathlib.Path(points_folder).glob("*.pkl")) + + final_result: dict[str, list[Any]] = { + "dataset": [], + "model": [], + "phrase_sim": [], + "context_sim": [], + } + + for raw_file in raw_files: + with open(raw_file, "rb") as file: + points: list[Point] = pickle.load(file) + dataset_name, model_name = get_dataset_and_model_name(raw_file.name) + + word_sims = [ + ( + point.phrase_similarity + if isinstance(point.phrase_similarity, float) + else point.phrase_similarity.item() + ) + for point in points + ] + context_sims = [ + ( + point.contextualized_similarity + if isinstance(point.contextualized_similarity, float) + else point.contextualized_similarity.item() + ) + for point in points + ] + + final_result["dataset"].append(dataset_name) + final_result["model"].append(model_name) + final_result["phrase_sim"].append(word_sims) + final_result["context_sim"].append(context_sims) + + fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(10, 4)) + axs[0, 0].violinplot( + final_result["phrase_sim"], + [y + 1 for y in range(len(final_result["phrase_sim"]))], + ) + axs[0, 0].set_xticks( + [y + 1 for y in range(len(final_result["phrase_sim"]))], + labels=final_result["model"], + ) + axs[1, 0].violinplot( + final_result["context_sim"], + [y + 1 for y in range(len(final_result["context_sim"]))], + ) + axs[1, 0].set_xticks( + [y + 1 for y in range(len(final_result["context_sim"]))], + labels=final_result["model"], + ) + plt.show() + + +if __name__ == "__main__": + main()