返回列表

29th Place Solution

593. LLM - Detect AI Generated Text | llm-detect-ai-generated-text

开始: 2023-10-31 结束: 2024-01-22 AI安全与对抗 数据算法赛

第29名解决方案

作者: YoungPaik | 团队成员: Patrick Chan, jerife | 排名: 第29名

非常感谢主办方举办这次比赛。这是一次非常棒的学习经历。
我要衷心感谢我的团队成员 @drpatrickchan@jerifate,感谢他们宝贵的贡献和协作。同时,我也真诚地感谢整个社区分享他们的见解。

以下是解决方案的简要总结。

TF-IDF模型(来自公开notebook):

Distil RoBERTa模型(来自公开notebook):

LSTM&Transformer CNN方法:

  • 灵感来源: Ensemble_TransformerCNN&Roberta
  • 改进: 增加了额外的类别特征,如Flesch阅读难易度、Fog指数、分数转年级水平、理解水平和极性。
  • 分数: 私有 - 0.766, 公开 - 0.926

Deberta模型:

  • 数据集: 90万行,包括llm-mistral-7b-instruct-texts、daigt-external-dataset等多种来源。
  • 亮点: 带magic的daigt-v4-train-dataset对我特别有帮助。感谢@thedrcat讨论
  • 训练方法: 使用Deberta-v3-large,最大长度为1024。此外,还使用了自定义截断(见下文)和0.1的标签平滑。
def custom_truncate(text, tokenizer_in, max_length=MAX_LEN):
    # 将文本分词为句子
    sentences = sent_tokenize(text)
    tokenized_sentences = [
        tokenizer_in.encode(sentence, add_special_tokens=False)
        for sentence in sentences
    ]

    # 计算总token数
    total_tokens = sum(len(sentence) for sentence in tokenized_sentences)

    # 如果总token数已在max_length范围内,返回原文本
    if total_tokens <= max_length:
        return text

    # 确定起始索引的上限
    tokens_so_far = 0
    for i, sentence_tokens in enumerate(tokenized_sentences):
        tokens_so_far += len(sentence_tokens)
        if tokens_so_far > max_length:
            max_start_index = i
            break

    # 选择一个不接近末尾的起始点
    start_index = random.randint(0, max(max_start_index - 1, 0))
    truncated_tokens = []

    # 连接句子token直到达到max_length
    for sentence_tokens in tokenized_sentences[start_index:]:
        if len(truncated_tokens) + len(sentence_tokens) <= max_length:
            truncated_tokens.extend(sentence_tokens)
        else:
            break

    # 将token转换回文本
    truncated_text = tokenizer_in.decode(
        truncated_tokens, skip_special_tokens=True, clean_up_tokenization_spaces=True
    )
    return truncated_text

def tokenize_with_custom_truncation(examples, max_length=MAX_LEN):
    text_li = examples["text"]
    # 应用自定义截断
    truncated_text_li = []
    for text in text_li:
        truncated_text = custom_truncate(text, tokenizer, max_length)
        truncated_text_li.append(truncated_text)

    # 对截断后的文本进行分词
    return tokenizer(
        truncated_text_li,
        padding=True,
        truncation=True,
        max_length=max_length,
    )
  • 我相信这种随机性有助于获得更稳健的模型
  • 分数: 私有 - 0.901, 公开 - 0.931

集成方法:

  • 权重分配: TF-IDF (0.5), Distil RoBERTa (0.1), Three Tower (0.15), Deberta (0.25)
  • 策略: 在TF-IDF和其他模型之间取得平衡,以实现有效性能。
  • 最终分数: 私有 - 0.921, 公开 - 0.970

更新: 解决方案代码已发布。

同比赛其他方案