Spaces:
Runtime error
Runtime error
| import logging | |
| logging.basicConfig(level='ERROR') | |
| import numpy as np | |
| from pathlib import Path | |
| import openai | |
| import torch | |
| import zlib | |
| import statistics | |
| from torch.utils.data import DataLoader | |
| from transformers import AutoTokenizer, AutoModelForCausalLM | |
| from tqdm import tqdm | |
| import math | |
| import numpy as np | |
| from datasets import load_dataset | |
| from options import Options | |
| from ipdb import set_trace as bp | |
| from eval import * | |
| from utils import evaluate_model | |
| from analyze import analyze_data | |
| import argparse | |
| import os | |
| import sys | |
| import gc | |
| import pickle | |
| models = {} | |
| def save_data(filename, data): | |
| with open(filename, 'wb') as filehandle: | |
| # store the data as binary data stream | |
| pickle.dump(data, filehandle) | |
| def load_data(filename): | |
| with open(filename, 'rb') as filehandle: | |
| # read the data as binary data stream | |
| loaded_data = pickle.load(filehandle) | |
| return loaded_data | |
| def load_model(name1): | |
| if name1 not in models: | |
| model1 = AutoModelForCausalLM.from_pretrained(name1, return_dict=True, device_map='auto') | |
| model1.eval() | |
| tokenizer1 = AutoTokenizer.from_pretrained(name1) | |
| tokenizer1.pad_token = tokenizer1.eos_token | |
| models[name1] = model1 | |
| models[name1 + "_tokenizer"] = tokenizer1 | |
| return models[name1], models[name1 + "_tokenizer"] | |
| def calculatePerplexity(sentence, model, tokenizer, gpu): | |
| """ | |
| exp(loss) | |
| """ | |
| input_ids = torch.tensor(tokenizer.encode(sentence)).unsqueeze(0) | |
| input_ids = input_ids.to(gpu) | |
| with torch.no_grad(): | |
| outputs = model(input_ids, labels=input_ids) | |
| loss, logits = outputs[:2] | |
| ''' | |
| extract logits: | |
| ''' | |
| # Apply softmax to the logits to get probabilities | |
| probabilities = torch.nn.functional.log_softmax(logits, dim=-1) | |
| # probabilities = torch.nn.functional.softmax(logits, dim=-1) | |
| all_prob = [] | |
| input_ids_processed = input_ids[0][1:] | |
| for i, token_id in enumerate(input_ids_processed): | |
| probability = probabilities[0, i, token_id].item() | |
| all_prob.append(probability) | |
| return torch.exp(loss).item(), all_prob, loss.item() | |
| def sample_generation(sentence, model, tokenizer, args,data_name): | |
| half_sentence_index = math.ceil(len(sentence.split())*args['prefix_length']) | |
| if half_sentence_index > 0: | |
| prefix = " ".join(sentence.split()[:half_sentence_index]) | |
| else: | |
| prefix = '<|startoftext|> ' | |
| input_ids = torch.tensor(tokenizer.encode(prefix)).unsqueeze(0) | |
| input_ids = input_ids.to(model.device) | |
| output = model.generate(input_ids, max_new_tokens=(len(sentence.split())-half_sentence_index), min_new_tokens=1, num_return_sequences=int(args['num_z']), pad_token_id=tokenizer.eos_token_id, **args['generate_args']) | |
| # print(output) | |
| complete_generated_text = tokenizer.batch_decode(output, skip_special_tokens=True) | |
| return complete_generated_text | |
| def RMIA_1(text,target_loss,ref_loss,model1,tokenizer1,ratio_gen,neighbors_dl): | |
| target_losses_z = evaluate_model(model1,tokenizer1,neighbors_dl) | |
| result = torch.count_nonzero(target_losses_z < target_loss).item() / len(target_losses_z) | |
| return result | |
| def get_neighbors(text,ref_loss,model2,tokenizer2,ratio_gen,data_name): | |
| cur_args = {'prefix_length': ratio_gen, 'num_z': 50, 'generate_args': {'do_sample': True}} | |
| neighbors = sample_generation(text, model2, tokenizer2, cur_args,data_name) | |
| neighbors_dl = DataLoader(neighbors, batch_size=32, shuffle=False) | |
| return neighbors_dl | |
| def evaluate_data(test_data, col_name, target_model, ref_model, ratio_gen, data_name): | |
| global model1,model2,tokenizer1,tokenizer2 | |
| print(f"all data size: {len(test_data)}") | |
| random.seed(0) | |
| random.shuffle(test_data) | |
| test_data = test_data[:100] | |
| inference2_pass = None | |
| neighbors_dls = None | |
| ref_model_clean = ref_model.replace("/","-") | |
| data_name_clean = data_name.replace("/","-") | |
| os.makedirs(os.path.join(f"saves/{ref_model_clean}",f"{data_name_clean}"),exist_ok=True) | |
| try: | |
| inference2_pass = load_data(f'saves/{ref_model_clean}/{data_name_clean}/inference2_pass.txt') | |
| neighbors_dls = load_data(f'saves/{ref_model_clean}/{data_name_clean}/neighbors_dls.txt') | |
| except: | |
| ### MODEL 2 likelihoods | |
| model2, tokenizer2 = load_model(ref_model) | |
| inference2_pass = [] #0: p_ref, #1: all_prob_ref, #2: p_ref_likelihood | |
| for ex in tqdm(test_data): | |
| text = ex[col_name] | |
| new_ex = inference_model2(model2, tokenizer2, text) | |
| inference2_pass.append(new_ex) | |
| # Invariant. Doesn't take in model1 so I'm good | |
| ### Neighbors: | |
| neighbors_dls = [] | |
| counter = 0 | |
| for ex in tqdm(test_data): | |
| text = ex[col_name] | |
| new_ex = get_neighbors(text,inference2_pass[counter][2],model2,tokenizer2,ratio_gen,data_name) | |
| counter = counter + 1 | |
| neighbors_dls.append(new_ex) | |
| del models[ref_model] | |
| del models[ref_model + "_tokenizer"] | |
| model2.cpu() | |
| del model2 | |
| del tokenizer2 | |
| gc.collect() | |
| torch.cuda.empty_cache() | |
| # Because it uses temp it is not invariant, however taking a snapshot in time should be just fine. | |
| save_data(f'saves/{ref_model_clean}/{data_name_clean}/inference2_pass.txt',inference2_pass) | |
| save_data(f'saves/{ref_model_clean}/{data_name_clean}/neighbors_dls.txt',neighbors_dls) | |
| print("Saved ref data, exiting.") | |
| ### MODEL 1 likelihoods | |
| model1, tokenizer1 = load_model(target_model) | |
| inference1_pass = [] #0: p1, #1: all_prob, #2: p1_likelihood, #3: p_lower, #4: p_lower_likelihood | |
| for ex in tqdm(test_data): | |
| text = ex[col_name] | |
| new_ex = inference_model1(model1,tokenizer1,text) | |
| inference1_pass.append(new_ex) | |
| ### RIMA results | |
| counter = 0 | |
| results = [] | |
| for ex in tqdm(test_data): | |
| text = ex[col_name] | |
| new_ex = RMIA_1(text,inference1_pass[counter][2],inference2_pass[counter][2],model1,tokenizer1,ratio_gen,neighbors_dls[counter]) | |
| counter = counter + 1 | |
| results.append(new_ex) | |
| del models[target_model] | |
| del models[target_model + "_tokenizer"] | |
| model1.cpu() | |
| del model1 | |
| del tokenizer1 | |
| gc.collect() | |
| torch.cuda.empty_cache() | |
| ### Inference ex | |
| all_output = [] | |
| counter = 0 | |
| for ex in tqdm(test_data): | |
| text = ex[col_name] | |
| pred = {} | |
| pred["minkprob_w/_ref"] = results[counter] | |
| pred["ppl"] = inference1_pass[counter][0] | |
| pred["ppl/Ref_ppl (calibrate PPL to the reference model)"] = inference1_pass[counter][2]-inference2_pass[counter][2] | |
| pred["ppl/lowercase_ppl"] = -(np.log(inference1_pass[counter][3]) / np.log(inference1_pass[counter][0])).item() | |
| zlib_entropy = len(zlib.compress(bytes(text, 'utf-8'))) | |
| pred["ppl/zlib"] = np.log(inference1_pass[counter][0])/zlib_entropy | |
| ex["pred"] = pred | |
| counter = counter + 1 | |
| all_output.append(ex) | |
| return all_output | |
| def inference_model1 (model1, tokenizer1, text): | |
| p1, all_prob, p1_likelihood = calculatePerplexity(text, model1, tokenizer1, gpu=model1.device) | |
| p_lower, _, p_lower_likelihood = calculatePerplexity(text.lower(), model1, tokenizer1, gpu=model1.device) | |
| return [p1, all_prob, p1_likelihood, p_lower, p_lower_likelihood] | |
| def inference_model2 (model2, tokenizer2, text): | |
| p_ref, all_prob_ref, p_ref_likelihood = calculatePerplexity(text, model2, tokenizer2, gpu=model2.device) | |
| return [p_ref,all_prob_ref,p_ref_likelihood] | |
| def main(target_model,ref_model,output_dir,data,length,key_name,ratio_gen): | |
| output_dir = f"{output_dir}/{target_model}_{ref_model}/{key_name}" | |
| Path(output_dir).mkdir(parents=True, exist_ok=True) | |
| # load model and data | |
| data_name = data | |
| if "jsonl" in data: | |
| data = load_jsonl(f"{data}") | |
| elif data == "truthful_qa": | |
| # bp() | |
| dataset = load_dataset(data, "multiple_choice", split="validation") | |
| data = convert_huggingface_data_to_list_dic(dataset) | |
| data = process_truthful_qa(data) | |
| elif data == "cais/mmlu": | |
| dataset = load_dataset(data, "all", split="test") | |
| data = convert_huggingface_data_to_list_dic(dataset) | |
| data = process_mmlu(data) | |
| elif data == "ai2_arc": | |
| dataset = load_dataset(data, "ARC-Challenge", split="test") | |
| data = convert_huggingface_data_to_list_dic(dataset) | |
| data = process_arc(data) | |
| elif data == "gsm8k": | |
| dataset = load_dataset(data, "main", split="test") | |
| data = convert_huggingface_data_to_list_dic(dataset) | |
| data = process_gsm8k(data) | |
| elif data == "Rowan/hellaswag": | |
| dataset = load_dataset(data, "default", split="validation") | |
| # We use validation since labels for the test set are not available? | |
| data = convert_huggingface_data_to_list_dic(dataset) | |
| data = process_hellaswag(data) | |
| elif data == "winogrande": | |
| dataset = load_dataset(data,"winogrande_debiased", split="validation") | |
| data = convert_huggingface_data_to_list_dic(dataset) | |
| data = process_winogrande(data) | |
| #model1, model2, tokenizer1, tokenizer2 = load_model(target_model, ref_model) | |
| all_output = evaluate_data(data,key_name, target_model, ref_model,ratio_gen,data_name) | |
| dump_jsonl(all_output, f"{output_dir}/all_output.jsonl") | |
| return analyze_data(all_output) | |
| # fig_fpr_tpr(all_output, output_dir) | |