返回列表

13th(14th) place solution

573. Kaggle - LLM Science Exam | kaggle-llm-science-exam

开始: 2023-07-11 结束: 2023-10-10 自然语言处理 数据算法赛
```html

作者:kurupical (GRANDMASTER)

创建时间:2023-10-11 00:04:44

最后更新:2023-10-17 13:41:24

比赛排名:第13-14名

第13(14)名解决方案

首先,感谢比赛主办方举办本次竞赛。同时,我也想感谢 @radek1@leonidkulyk@mozattt@nlztrk@mgoksu 分享的有用数据集,感谢 @jjinho 分享的检索方法,感谢 @cdeotte此讨论帖 中汇总这些数据集和方法。没有你们的工作,我们无法取得这些成果。从你们身上我学到了很多!

我的方案基于 @cdeotte此 notebook。我对该 notebook 做了四个方面的改进:数据集、检索、模型和集成

1. 数据集

由于部分数据(主要是数字)存在缺失问题(如 此处讨论),我将维基百科数据集从 https://www.kaggle.com/datasets/jjinho/wikipedia-20230701 更换为 cirrussearch 维基百科数据集。

2. 检索

我尝试提升搜索精度。

2-1. 评估数据集

我使用 ChatGPT 创建了 250 个问题用于评估检索效果。为进行大量实验,仅使用了以 "a" 开头的维基百科数据进行评估(而非完整数据集)。最终在该数据集上达到 0.94@recall11.0@recall30 的召回率(使用完整维基百科数据集的问题时约为 0.85@recall1)。

2-2. 文本处理

为提升检索精度,我对维基百科文本进行了分段处理。具体方法是从文本开头读取,当字数达到 90 词或以上时保存分段,并保留最后三个句子用于继续读取后续内容。

伪代码如下:

def count_words(text_processed):
    return len(text_processed.split(" "))

def leave_last_sentence(text, n=3):
    ret = text.split(".")[-n:]
    return ".".join(ret)

texts = load_wiki()
texts_processed = []
text_processed = ""
length = 90
window = 3
for text in texts:
    text_split_period = text.split(".")
    for sentence in text_split_period:
        text_processed += sentence
        if count_words(text_processed) > length:
            texts_processed.append(text_processed)
            text_processed = leave_last_sentence(text_processed, window)

我尝试了以下参数组合 (length, window) = (60, 2), (75, 2), (90, 2), (90, 3), (90, 4), (120, 4), (150, 6),最终选择 LB 分数最高的配置。

2-3. FAISS

使用参数:{"nlists": 1, "M": 64, "nbits": 8}

2-4. 检索模型

使用 gte-basee5-base 模型。我尝试了 {gte, bge, e5}_{small, base, large} 多种组合并选择最优结果。(最初我仅通过 "a" 开头数据的检索精度选择模型,但发现检索精度与 LB 分数无相关性,最终改为依据 LB 分数选择😭)

3. 模型

基本与基线 notebook 相同。训练时设置 max_length 为 256,推理时为 768。虽然希望使用 768 长度训练,但内存资源不足。在 256、384 和 512 长度训练后使用 768 长度推理的对比中,256 长度训练效果最佳。

训练参数如下:

training_args = TrainingArguments(
    warmup_ratio=0.01, 
    learning_rate=1e-6,
    per_device_train_batch_size=2,
    per_device_eval_batch_size=2,
    num_train_epochs=config.epochs,
    report_to='wandb',
    optim="adamw_hf",
    overwrite_output_dir=True,
    fp16=True,
    gradient_accumulation_steps=8,
    load_best_model_at_end=True,
    metric_for_best_model="eval_map@3",
    lr_scheduler_type="cosine",
    weight_decay=0.01,
    save_total_limit=1,
)

我集成了 4 个模型,组合了以下元素:

  • 模型
    • OpenAssistant/reward-model-deberta-v3-large-v2
    • deepset/deberta-v3-large-squad2
    • microsoft/deberta-v3-large
  • 检索模型
    • gte-base
    • e5-base
  • 数据集
    • 全部数据
    • 排除 3,7,8,9 号数据源:相比其他数据集效果更差
    • 排除 10 号数据源:相比其他数据集效果更好

    编号参考 此数据集 的来源标识。

4. 集成

4-1. TTA(测试时增强)

我在推理时使用了低排名检索结果。设置 4 种 TTA 策略:

  • [ 0, 1, 2, 3, 4, 5]
  • [ 0, 6, 7, 8, 9, 10]
  • [ 0, 11, 12, 13, 14, 15]
  • [ 0, 16, 17, 18, 19, 20]

数组中的数字代表问题的检索排名。

4-2. 集成策略

TTA 后未使用简单平均分数,而是采用最大值与平均值相加的方式:

df = pd.read_csv("test.csv")  # len(df) == 测试数据量
df["id"] = np.arange(len(df))
df = ensemble(df)  # len(df) = 测试数据量 × TTA数量 × 模型数量
df = df.groupby("id").mean() + df.groupby("id").max()

5. 未生效/未实现的效果

  • 使用 ChatGPT 生成问题
    • 尝试多种提示词但分数下降
  • 创建与 LB 相关的 CV
    • 尝试了 @cdeotte 数据集的 300 行,最终使用 @wuwenmin 的 300 行 + 测试集 200 行,但 CV 与 LB 无相关性
  • 更复杂的 TTA 策略
  • 提升模型精度
    • 与 @cdeotte 的 notebook 精度几乎相同
    • 我认为提升模型精度非本竞赛关键,因此重点优化检索环节
```
同比赛其他方案