In-Context Probing Approximates Influence Function for Data Valuation 代码 3 —— utils/icp_scores.py

目录

获得 icp 分数指令

utils/icp_scores.py

1. 命令行参数解析

2. 核心函数

2.1 get_task_count(data):通过提取所有唯一的doc_id,确定任务包含的样本总数

2.2 load_data(path):加载 JSON 格式的模型输出文件

2.3 get_likelihoods(data):分离基线似然分数(无上下文)和上下文似然分数

2.4 get_icp_scores(likelihoods, baseline_likelihoods):对每个上下文样本,计算其提升任务样本似然分数的比例(ICP分数)

 2.5 save_icp_scores(scores, path):将 ICP 分数存入 JSON 文件

3. 主程序流程


获得 icp 分数指令

python utils/icp_scores.py --infile path_to_model_outputs --outfile path_to_save_file

计算 ICP 分数:​获取模型输出后,使用 Python 脚本计算 ICP 分数:​

--infile path_to_model_outputs:
指定了通过之前的模型运行(bash scripts/run_icp.sh)生成的模型输出文件路线(model_probs.json

--outfile path_to_save_file:
指定了计算结果的输出文件路径(ICP分数保存路径)(icp_scores.csv


utils/icp_scores.py

该脚本用于计算 In-Context Probing (ICP) 分数,通过对比模型 使用上下文示例 和 无上下文(基线) 的预测似然差异,评估上下文学习的效果。

1. 命令行参数解析

parser = argparse.ArgumentParser()
parser.add_argument("--infile",  type=str, help="path to model likelihoods file")
parser.add_argument("--outfile", type=str, help="path to save file")
args = parser.parse_args()

输入文件格式:每行一个 JSON 对象,包含 doc_idincontext_doc_id 和 filtered_resps 等字段:

  •  doc_id 是输入数据(data)中每个条目(entry)的一个字段,通常是一个整数(如 0,1 等),是 任务样本的唯一标识符.
  • filtered_resps 表示经过过滤后的响应结果,通常是模型对某个任务样本的预测结果。它包含了模型针对样本计算得到的似然分数,这个分数可以用来衡量模型对该样本预测的置信度或者合理性。
  • incontext_doc_id 代表上下文文档的标识符。在上下文学习的场景里,模型在预测某个任务样本时,会利用一个或多个上下文样本的信息来辅助决策。incontext_doc_id 就是用来标识这些被用作上下文的样本:
    基线情况:当 incontext_doc_id 的值为 0 时,表示模型在预测当前样本时没有使用任何上下文信息,这通常作为一个基准情况,用于后续与使用上下文信息的情况进行对比。
    使用上下文情况:当 incontext_doc_id 的值不为 0 时,它标识了被用作上下文的具体样本的 doc_id,模型会参考该上下文样本的信息来对当前样本进行预测。

输出文件格式:JSON 字典,键为上下文示例ID,值为对应的 ICP 分数。

2. 核心函数

2.1 get_task_count(data):通过提取所有唯一的doc_id,确定任务包含的样本总数

def get_task_count(data):
    """
    Count the number of samples in the task.
    Args:
        data: model outputs.
    Returns:
        int: number of samples.
    """
    n_task_samples = set()
    for entry in tqdm(data):
        doc_id = entry['doc_id']
        n_task_samples.add(doc_id)    #集合n_task_samples存储唯一的doc_id(自动去重)
    return len(n_task_samples)    #返回集合长度即为样本数

doc_id 是输入数据(data)中每个条目(entry)的一个字段,通常是一个整数(如 012 等),是 任务样本的唯一标识符,用于:
1. 统计任务中的唯一样本数(通过集合去重)。
2. 作为索引 存储和关联样本的似然分数(基线和上下文场景)。
3. 区分不同样本,确保在多上下文或多次预测场景中,每个样本仅被处理一次。
 

2.2 load_data(path):加载 JSON 格式的模型输出文件

def load_data(path):
    """
    Data model outputs
    Args:
        path: model outputs.
    Returns:
        int: number of samples.
    """
    with open(path) as f:
        #逐行读取文件,用json.loads()解析为 Python 对象
        data = [json.loads(l.strip()) for l in f.readlines()] 
    return data    #返回包含所有条目的列表

 输入格式:每行一个 JSON 对象,例如:

{"doc_id": 0, "incontext_doc_id": 0, "filtered_resps": [[0.87]]}
{"doc_id": 1, "incontext_doc_id": 2, "filtered_resps": [[0.92]]}

2.3 get_likelihoods(data):分离基线似然分数(无上下文)和上下文似然分数

def get_likelihoods(data):
    """
    Get output likelihoods from model outputs
    Args:
        data: model outputs
    Returns:
        likelihoods: model output likelihoods for each incontext sample
        baseline_likelihoods: baseline model output likelihoods (without incontext samples)
    """
    likelihoods = {}
    n_task_samples = get_task_count(data)
    baseline_likelihoods = np.zeros(n_task_samples)

    for entry in tqdm(data):
        incontext_doc_id = entry['incontext_doc_id']
        doc_id = entry['doc_id']
        ll = entry['filtered_resps'][0][0]

        # baseline case
        if incontext_doc_id == 0:    ## 基线情况
            baseline_likelihoods[doc_id] = ll
            continue
        #上下文示例情况
            #其他 incontext_doc_id 转换为字符串键(减1处理),确保与后续索引对齐。
        incontext_doc_id = str(incontext_doc_id - 1)
        if incontext_doc_id not in likelihoods:
            likelihoods[incontext_doc_id] = np.zeros(n_task_samples)
        likelihoods[incontext_doc_id][doc_id] = ll

    return likelihoods, baseline_likelihoods

Python NumPy数组利器之np.zeros函数详解与应用实例例子解析-CSDN博客baseline_likelihoods:长度为n_task_samples的数组,索引为doc_id,值为基线似然分数likelihoods:键为上下文样本标识(字符串),值为对应似然分数数组
 

2.4 get_icp_scores(likelihoods, baseline_likelihoods):对每个上下文样本,计算其提升任务样本似然分数的比例(ICP分数)

def get_icp_scores(likelihoods, baseline_likelihoods):
    """
    Calculate ICP scores.
    Args:
        likelihoods: model output likelihoods for each incontext sample
        baseline_likelihoods: baseline model output likelihoods (without incontext samples)
    Returns:
        icp scores
    """
    icp_scores = {}
    for incontext_doc_id in likelihoods:
        task_likelihoods = likelihoods[incontext_doc_id]
        #计算 “上下文分数高于基线” 的样本比例,作为该上下文的 ICP 分数
        icp_score = np.mean([1 if task_likelihoods[i] > baseline_likelihoods[i] else 0 for i in range(len(task_likelihoods))])
        icp_scores[incontext_doc_id] = [icp_score]
    return icp_scores
  • range(len(task_likelihoods)):生成一个从 0 到 len(task_likelihoods) - 1 的整数序列。
  • 1 if task_likelihoods[i] > baseline_likelihoods[i] else 0:如果 task_likelihoods[i] 大于 baseline_likelihoods[i],则表达式的值为 1,表示使用该上下文样本时模型对第 i 个任务样本的预测效果比基线情况更好。
  • [ ... for i in range(len(task_likelihoods))]:列表推导式,会遍历生成的整数序列,将每个索引 i 对应的条件表达式的值添加到一个列表中。
  • np.mean(...):计算数组或列表的平均值。这里计算上述列表中所有元素的平均值,得到的结果就是 ICP 分数。
     

 2.5 save_icp_scores(scores, path):将 ICP 分数存入 JSON 文件

def save_icp_scores(icp_scores, path):
    with open(path, 'w+') as f:
        f.write(json.dumps(icp_scores))

输出格式:

{"0": [0.7], "1": [0.6]}        # 键为上下文样本标识,值为ICP分数列表

3. 主程序流程

if __name__ == "__main__":
    data = load_data(args.infile)    # 加载数据
    likelihoods, baseline_likelihoods = get_likelihoods(data)    # 提取似然
    icp_scores = get_icp_scores(likelihoods, baseline_likelihoods)    # 计算分数
    save_icp_scores(icp_scores, args.outfile)     # 保存结果

你可能感兴趣的:(ICL筛选高质量时序数据,算法,ICP,ICL,数据估值,python)