Yeyito's picture
num_z = 50 for all
28487fe
raw
history blame
9.37 kB
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 unload_model(model,tokenizer):
print("[X] Cannot unload model! Functionality not implemented!")
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)
unload_model(model2,tokenizer2)
# 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
model1, tokenizer1 = load_model(target_model)
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)
unload_model(model1,tokenizer1)
### 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)