内容审查到零样本分类 | 技术创作特训营第一期

2023-08-25 22:09:46 浏览数 (2)

前言

如果我们想分析一小段没有额外信息或上下文的文本,并能够获取我们希望为自己的数据定义的最合理的标签,那该怎么办呢?

这可以为更确定性的策略引擎和规则引擎提供数据,甚至可以作为所需的更大上下文驱动分析的一部分。OpenAI 确实提供了一种“内容审核”的方法,其中预设的分类可以确定您的文本是否属于一个或多个不良类别。然而,本文更多关注的是我们如何更加定制地为给定的句子或短语定义我们自己的标签。

我们将会涵盖 4 个类别:即政治、PHI/PII、法律问题和公司绩效。鉴于在这个时间点上我们无法从 OpenAI 获取关于这些自定义标签的概率分数,我们将在选项 1 中尝试更用户导向的提示工程方法,而选项 2 将评估 Hugging Face 的其他预训练模型来进行相同的操作。

我们还将使用一些经常扭曲以与多个类别相匹配的示例句子。例如,我们的 CSV 输入文件中有以下行作为“负载”:

  1. 部长们之间的问题在他们开始把它个人化时就开始了变化。
  2. 我试图与我的猫谈判数据隐私,但他只是忽略了我,然后为了小睡而入侵了我的键盘。
  3. 参议院的听证会是关于试验中的一种药物是否只能用于这个患者。他的血液有一种目前没有药物的特定状况。
  4. 最初作为政治辩论开始,结果在谈论公司2023年及以后的优先事项时变成了与超大规模厂商有更好故事的人。
  5. 法院关于言论自由的重大决定,在在线平台上的表达和有害内容之间的微妙界限引发了关于法律考虑与在线治理争论的讨论。
  6. 我在PHI体检时对医生讲了一个政治笑话,现在我的医疗记录上写着:患者的幽默感:危险的两党制。
  7. 用户管理的访问赋予您所谓的控制身份的好处;但是,有多少人会仔细审查您的电话中的应用权限,这些权限利用了您的名字、电子邮件和电话号码?

选项 1:使用 OpenAI 进行提示工程

代码语言:python代码运行次数:0复制
from langchain.chat_models import ChatOpenAI
import pandas as pd 
from langchain.prompts import PromptTemplate
from langchain.chains.llm import LLMChain
from IPython.display import HTML
model_name = 'gpt-4'
llm = ChatOpenAI(model_name = model_name, temperature=0)
payload_chain = LLMChain(llm=llm, prompt=moderationPrompt)

moderationPrompt = PromptTemplate(
    template = """
        请根据每个类别的存在和适用性,将下面的文章在0.00-100.00的连续范围内评分:
    [ 政治 | PHI | 法律 | 公司相关 | 无以上类别 ]
    定义:
    PHI:受保护的健康信息或个人可识别信息
    政治:政治决策、治理、政党、选举、政策
    法律:协议或合同语言、判决
    公司相关:公司战略、收益、报告、预测
    文章:{payload}
    输出:以方括号列表形式的 Python 浮点数
    """, input_variables=["payload"]
)

def read_csv_file(file_path):
    df = pd.read_csv(file_path)
    lines = df["payload"].dropna().tolist()  
    return lines
def perform_OpenAIclassification(lines, model_name):
    classifications = []
    for idx, sentence in enumerate(lines, start=1):  # 从1开始递增的行号
        if pd.notna(sentence):  
            result = payload_chain.run(payload = sentence)
            result = result.strip('][').split(', ')
            result.insert(0,idx) 
            result.insert(1, model_name)
            classifications.append(result)
    return classifications 

if __name__ == "__main__":
    input_csv_file = "./input.csv"  # 用您的 CSV 文件路径替换
    lines = read_csv_file(input_csv_file)
    result = perform_OpenAIclassification(lines, model_name)
    dfr = pd.DataFrame(result, columns = ['行号', '模型', '政治','PHI/PII','法律','About Company','None of these'])
    output_csv_file = "gptOutput.csv"  
    dfr.to_csv(output_csv_file, index=False)

GPT-4 在处理这些扭曲的句子时似乎比 3.5 turbo 更好。输出的数据框将如下所示。它在大多数情况下都能够正确地获取较大的概率,除了像 #3 这样的句子,在这种情况下我们预期 PHI/PII 带有一些百分比。这也为我们提出了一个要求,即请 OpenAI 提供

一些自定义便利功能,以标记我们的标签,并利用这些模型更快、更“博学”的能力。

行号

模型

政治

PHI/PII

法律

公司相关

无以上类别

1

gpt-4

100.00

0.00

0.00

0.00

0.00

2

gpt-4

0.00

0.00

0.00

0.00

100.00

3

gpt-4

100.00

0.00

0.00

0.00

0.00

4

gpt-4

70.00

0.00

0.00

30.00

0.00

5

gpt-4

70.00

0.00

85.00

0.00

0.00

6

gpt-4

10.00

20.00

0.00

0.00

70.00

7

gpt-4

0.00

50.00

0.00

0.00

50.0

选项 2:使用 Hugging Face 模型进行零样本分类

接下来,我们将尝试使用 Hugging Face 的预训练模型来执行相同的操作,这些模型在某种程度上是针对此特定任务进行目的驱动的。

代码语言:python代码运行次数:0复制
import pandas as pd
from transformers import pipeline
from IPython.display import HTML

# 零样本分类函数
def classify_with_model(text_to_classify, candidate_labels, model_name_or_path, multi_label=True):
    classifier = pipeline("zero-shot-classification", model=model_name_or_path)
    output = classifier(text_to_classify, candidate_labels, multi_label=multi_label)
    return output

def read_csv_file(file_path):
    df = pd.read_csv(file_path)
    lines = df["payload"].dropna().tolist()  
    return lines

# 逐个句子迭代,并使用多个模型进行分类
def perform_classification(lines, candidate_labels, model_options):
    classifications = []
    for model_name_or_path in model_options:
        model_classifications = []
        for idx, sentence in enumerate(lines, start=1):  
            if pd.notna(sentence):  
                result = classify_with_model(sentence, candidate_labels, model_name_or_path)
                model_used = model_name_or_path.split("/")[-1]
                result['scores'] = [round(i*100,2) for i in result['scores']]
                model_classifications.append(result['scores'])
                tempList = [idx, model_used, result['scores'][0], result['scores'][1], result['scores'][2], result['scores'][3], result['scores'][4]]
                classifications.append(tempList)
    return classifications

if __name__ == "__main__":
    input_csv_file = "./input.csv"  
    candidate_labels = ["政治", "PHI/PII", "法律", "公司绩效", "无以上类别"]
    model_options = ["facebook/bart-large-mnli", "valhalla/distilbart-mnli-12-3", "MoritzLaurer/DeBERTa-v3-large-mnli-fever-anli-ling-wanli"]
    lines = read_csv_file(input_csv_file)

    model_results = perform_classification(lines, candidate_labels, model_options)
    dfr = pd.DataFrame(model_results, columns = ['行号', '模型', '政治','PHI/PII','法律','About Company','None of these'])

    output_csv_file = "output_classifications.csv"  
    dfr.to_csv(output_csv_file, index=False)
    display(dfr) 

注意:multi_label 的值被设置为 True。您也可以尝试将其设置为 False

我们还可以使用我们自己的人类专业知识来审查这个输出(最后一列)。我们可以使用这样的简单索引:

  • 合理 - 表示引擎准确选择了多个标签
  • 部分准确 - 两个标签中有一个是准确的
  • 不准确 - 显然不够好

行号

模型

政治

PHI/PII

法律

公司相关

无以上类别

审查

1

bart-large-mnli

69.47

34.74

0.85

0.21

0.03

合理

2

bart-large-mnli

81.92

1.23

0.22

0.14

0.06

不准确

3

bart-large-mnli

72.47

40.36

30.79

5.25

0.04

合理

4

bart-large-mnli

86.27

28.26

14.43

0.39

0.03

部分准确

5

bart-large-mnli

68.21

35.23

18.78

13.24

0.02

部分准确

6

bart-large-mnli

98.53

90.45

6.31

0.73

0.02

合理

7

bart-large-mnli

81.23

6.79

2.17

1.55

0.04

不准确

1

distilbart-mnli-12-3

88.65

9.08

5.91

4.1

1.7

部分准确

2

distilbart-mnli-12-3

64.87

7.77

2.72

2.38

0.26

不准确

3

distilbart-mnli-12-3

76.79

42.79

36.2

20.3

1.98

合理

4

distilbart-mnli-12-3

60.8

49.22

9.91

6.68

0.45

部分准确

5

distilbart-mnli-12-3

82.97

55.31

41.59

15

0.99

合理

6

distilbart-mnli-12-3

87.11

85.6

11.07

7.74

0.12

合理

7

distilbart-mnli-12-3

79.02

6.58

3.31

1.18

0.95

不准确

1

DeBERTa-v3-large-mnli-fever-anli-ling-wanli

36.51

1.27

0.15

0.14

0.02

部分准确

2

DeBERTa-v3-large-mnli-fever-anli-ling-wanli

17.58

0.72

0.4

0.05

0.03

不准确

3

DeBERTa-v3-large-mnli-fever-anli-ling-wanli

95.69

59.7

26.89

0.45

0.07

合理

4

DeBERTa-v3-large-mnli-fever-anli-ling-wanli

95.07

79.32

17.91

0.07

0.05

部分准确

5

DeBERTa-v3-large-mnli-fever-anli-ling-wanli

61.88

28.35

8.16

0.06

0.03

部分准确

6

DeBERTa-v3-large-mnli-fever-anli-ling-wanli

99.64

93.95

0.83

0.07

0.03

合理

7

DeBERTa-v3-large-mnli-fever-anli-ling-wanli

2.48

1.41

0.08

0.06

0.04

不准确

数据集太小,无法得出明确的结果,但它们在这个任务上似乎都在相对可比的空间内。

总结

大型语言模型在许多情况下都适用。对于需要零样本分类中自定义标签的情况,当我们几乎没有上下文可依赖时,我们仍然可以选择训练在更专用的 NLI(自然语言推理)模型上的替代方法,如上述模型。对于特定需求的最终选择可以基于性能(在实时交易中的使用)、可以使这个任务更确定性的额外上下文的程度,以及在给定生态系统中的整合的便利性。

选题思路:

选择这个选题的原因是因为在当今信息爆炸的时代,如何高效地对文本进行分类和标注变得愈发重要。特别是在没有足够上下文信息的情况下,如何将一段文本准确地分类到预定义的标签中,是一个具有挑战性的任务。这篇文章旨在介绍两种不同的方法来实现这一目标:一种是通过 OpenAI 的 GPT-4 进行 Prompt Engineering,另一种是使用 Hugging Face 的预训练模型进行 Zero Shot 分类。通过比较这两种方法的优缺点,读者可以更好地理解在不同情境下如何进行文本分类,从而为自己的数据处理和分析工作选择合适的方法。

写作提纲:

1. 引言

  • 引入文本分类的重要性和挑战,特别是在缺乏上下文信息的情况下。

2. 选题背景

  • 介绍当前信息爆炸的时代,大量文本数据的处理需求。
  • 解释为什么选择探讨文本分类中的零样本分类问题。

2.1 方法一:Prompt Engineering With OpenAI

  • 介绍 Prompt Engineering 的概念,即通过设计合适的提示语来引导模型产生期望的输出。
  • 解释如何使用 GPT-4 进行 Prompt Engineering 进行文本分类。
  • 展示实际代码示例,以及结果的解释和分析。
  • 讨论方法一的优势和局限性。

2.2 方法二:Zero Shot Classification With Models From Hugging Face

  • 介绍零样本分类的概念,即在没有样本标签的情况下对文本进行分类。
  • 说明如何使用 Hugging Face 的预训练模型进行零样本分类。
  • 展示实际代码示例,以及结果的解释和分析。
  • 讨论方法二的优势和局限性。

3. 结果对比与讨论

  • 对比两种方法在同样数据集上的结果,分析其性能表现。
  • 探讨在不同情境下,哪种方法更适用以及为什么。

4. 选题意义与应用

  • 探讨文本分类在现实应用中的价值,如社交媒体分析、内容过滤等领域。
  • 强调读者可以根据任务需求选择适当的分类方法。

5. 结论

  • 总结两种方法的特点和应用场景。
  • 强调在选择方法时需考虑任务特点和数据情境。

通过这篇文章,读者可以深入了解文本分类中的零样本分类问题以及两种不同方法的实现。无论是从事自然语言处理研究的专业人士,还是对文本数据处理感兴趣的初学者,都可以从中获得有关如何更好地进行文本分类的知识和见解。

参考出处

https://platform.openai.com/docs/api-reference/moderations/object

0 人点赞