如何用Python对数据集进行程序化标记的Snorkel Python

494 阅读9分钟

以编程方式为数据集贴标签的Snorkel Python

Snorkel是一个用于数据标记的Python库。它以编程方式管理和构建训练数据集,而不需要手动贴标签。在机器学习中,标签是数据集中的目标或输出变量。这就是模型试图预测的东西。

Snorkel不需要人类手动给大型数据集贴标签,而是自动给大量训练数据分配标签。这是用一套用户规则、标签函数和其他内置技术完成的。

Snorkel要求用户想出包含明确规则的函数。我们将使用这些规则来标记未标记的数据。

在本教程中,我们将有一个未标记的数据集,其中包含一个句子列表。句子列表是由问题组成的,而其他的是一般的陈述。

本教程的目的是将一个句子标记为问题或不是问题。如果一个句子是问题,它被标记为1 ,而非问题句子(一般陈述)被标记为-1 。所有这些都将使用Snorkel以编程方式完成。

前提条件

要想轻松跟上,读者应该。

  • 熟悉[Python编程。]
  • 了解[机器学习建模。]
  • 知道如何使用[谷歌Colab笔记本。]
  • 对[Pandas]有一定了解。
  • 熟悉[Scikit-learn。]

如何安装Snorkel Python

我们使用以下命令安装Snorkel Python。

!pip install snorkel

安装完Snorkel后,让我们开始处理我们的未标记的数据集。

无标签数据集

我们的无标签数据集是文本文件格式。

下面是我们的数据集的一个片段。Unlabeled dataset

要下载这个文本文件,请点击这里。

加载数据集

我们使用Pandas加载这个数据集。Pandas是一个Python软件包,用于数据处理和分析。

它还允许我们从不同的文件格式导入数据,如CSV文件、文本文件、JSON文件和SQL文件。

让我们导入Pandas。

import pandas as pd

让我们加载我们的数据集。

data = pd.read_table('unlabeled-dataset.txt')

让我们看看我们的数据集是否被加载。

要看数据集是否在我们的机器中被加载,使用这个命令。

data

输出显示如下。

Loaded dataset

让我们来洗刷我们的数据集。洗涤我们的数据集可以确保我们的数据集被正确地重新组织和格式化。这可以减少偏差。

为了洗刷我们的数据集,我们使用一个叫做random 的Python包。

让我们导入random 包。

import random

现在让我们使用random.shuffle() 方法来洗刷我们的数据集。

random.shuffle(data)

要看到数据集洗牌后的输出,请运行这个命令。

data

下面的输出显示了一个经过充分组织和格式化的数据集。

Loaded dataset

转换为数据框

数据框架是用行和列来表示数据。当数据以这种形式表示时,它很容易被模型理解和使用。

我们的数据集将有一列。它将有一个sentences 列,其中包含所有未标记的句子。

让我们来创建这一列。

df = pd.DataFrame({'sentences':data})

现在让我们看看我们的数据集与sentences 列。

df.head()

输出结果如下图所示。

Dataset structure

现在让我们来分割我们的数据集。

数据集的拆分

我们把我们的数据集分成两组,训练集和测试集。训练集在训练阶段使用,以便模型可以从中学习。

测试集是用来评估模型的总体性能。它也检查模型是否能做出准确的预测。

让我们导入必要的方法来分割我们的数据集。

from sklearn.model_selection import train_test_split

train_test_split 将被用来分割我们的数据集。

df_train,df_test = train_test_split(df,train_size=0.5)

在上面的代码中,我们指定了train_size=0.5 。这意味着数据集的50% 将被用于训练,而剩余的50% 将被用于测试。

让我们检查一下测试集中的句子总数。

print(df_train.shape)

输出结果如下所示。

(44, 1)

这表明我们的测试集中总共有44 句子和1 列。

定义我们的标签函数

贴标函数定义了贴标模型所使用的规则。这些规则被用来预测未标记数据的标签。

让我们导入可以让我们想出标签函数的方法。

from snorkel.labeling import labeling_function

为了使我们能够提出一个准确的标签模型,我们需要提出至少三个标签函数。

导入的labeling_function 方法允许我们创建三个贴标函数。

为了得出最佳的标签函数,我们需要知道如何对数据集进行标签。

在这种情况下,我们想给我们的数据集贴上两个标签,如下所示。一个句子可以被标记为一个问题或一个一般陈述。如果该句子是一个问题,它被标记为1 ,而一个一般的陈述被标记为-1

以下是一个声明是否有资格成为一个问题的规则。

规则

  • 一个句子应该以下列短语开始。why,what,when,who,where, 和how
  • 一个句子应该以问号结束,?

然后,我们需要为我们的标签指定常数。

标签的常量

我们将用它来给句子贴标签。例如,QUESTION ,用于标记符合问题条件的句子。ABSTAIN ,用于标记其他句子。

QUESTION = 1
ABSTAIN = -1

使用上面的规则,我们现在可以得出标签函数了。

关键字查找功能

这个函数是用来检查句子开头的短语的。这些短语如下。why,what,when,who,where, 和how

如果符合这一规则,该句子就被标记为QUESTION = 1 。如果不符合,该句子就被标记为ABSTAIN = -1

@labeling_function()
def lf_keyword_lookup(x):
  keywords = ["why","what","when","who","where","how"]
  return QUESTION if any(word in x.sentences.lower() for word in keywords) else ABSTAIN

我们在@labeling_function() 装饰器的帮助下将我们的函数定义为lf_keyword_lookup(x)

然后我们传递我们的规则。最后,我们在数据集中循环浏览我们的sentences ,看是否满足条件。

让我们去看第二个标签函数。

模式查找函数

这个函数检查句子是否包含开头的短语what

它还检查该句子是否以问号结束,?

为了在一个句子中找到? ,我们使用Python正则表达式

它在句子模式中搜索,直到找到一个?

import re
@labeling_function()
def lf_regex_contains_what(x):
  return QUESTION if re.search(r"what.*?",x.sentences,flags=re.I) else ABSTAIN

首先,我们有导入re ,它代表正则表达式。然后,我们使用re.search() 方法在句子中搜索,找到短语what? 的实例。

如果满足条件,该句子被标记为QUESTION = 1 ,如果不满足,则被标记为ABSTAIN = -1

让我们来看看最后一个标签,它也将使用一个模式查找函数。

第二个模式查找函数

这个函数也将使用Python正则表达式。然而,它只搜索句子中的问号,?

import re
@labeling_function()
def lf_regex_contains_question_mark(x):
  return QUESTION if re.search(r".*?",x.sentences,flags=re.I) else ABSTAIN

我们现在需要将所有这些标记函数应用于我们的训练集数据集。

合并标签函数

首先,我们需要结合所有这些标签函数,并将它们保存在一个单一的变量中,lfs 。当它们结合在一起时,它们会建立一个最佳的贴标模型。

lfs = [lf_keyword_lookup,lf_regex_contains_what,lf_regex_contains_question_mark]

然后我们导入PandasLFApplier 方法。这是一个Pandas 方法,用于对数据集应用一个以上的贴标函数。

from snorkel.labeling import PandasLFApplier

让我们把我们的组合贴标函数,lfs ,传入PandasLFApplier 方法。

applier = PandasLFApplier(lfs=lfs)

然后我们将所有的组合标记函数应用到训练数据集上。最后,训练数据集被保存在一个叫做df_train 的变量中。

标签函数在数据集中学习模式。这个过程被称为模式识别。

L_train = applier.apply(df=df_train)

现在我们已经在我们的df_train 中应用了所有三个标签函数,现在是时候建立我们的数据集了。

构建标签模型

我们需要导入我们将用于建立模型的方法。

from snorkel.labeling.model import LabelModel

LabelModel 方法将被用来建立我们的模型。

现在让我们来建立这个模型。

label_model = LabelModel(cardinality=2,verbose=True)
label_model.fit(L_train=L_train,n_epochs=500,log_freq=100,seed=123)

LabelModel 使用fit() 方法将模型装入L_trainL_train 包含标签函数和训练数据集。

在这个阶段,模型通过训练获得知识。它最终使用获得的知识来进行预测。

我们还使用以下参数。

  • n_epochs=500 - 模型通过 ,迭代的次数。L_train

  • cardinality=2 - 这显示了可能的标签输出。在我们的案例中,我们有 和 。1 -1

  • verbose=True - 这允许我们在搜索 时使用正则表达式。?

  • log_freq=100 - 它检查特定短语在数据集中的分布频率。

  • seed=123 - 我们的模型在模型训练期间将使用的随机数。

在500个epochs之后,我们将成功地训练我们的模型。

现在让我们用这个模型来标记数据集。

给未标记的数据集添加标签

我们用这个模型来给我们的数据集添加标签。我们的两个标签是:QUESTION = 1ABSTAIN = -1

我们使用predict 的方法来进行预测。这个方法是用来将句子分类为问题或非问题。

df_train['Labels'] = label_model.predict(L=L_train,tie_break_policy="abstain")

运行上面的代码后,模型应该能够对各种句子进行分类。

让我们看看预测的结果。

Prediction results

上面的图片显示,What's your favorite ice cream topping? 这个句子被标记为1 。因此,这代表QUESTION

另一个句子是,There is no Ctrl-Z in life. 这被标记为-1 ,这是个一般的陈述。

使用上面的两个例子,我们可以看到我们的模型可以做出正确的预测。此外,这表明我们的模型可以成功地给未标记的数据集分配标签。

总结

在本教程中,我们已经学会了如何使用Snorkel以编程方式给数据集打标签。首先,我们开始进行数据预处理。这涉及到清理数据集和为我们的数据集添加列。

从那里,我们将数据集分成两组,这样一组可以用于训练,另一组用于测试。然后,我们创建了一个标签函数,其中包含模型要使用的基本规则。

在成功地将所有的标记函数应用于我们的数据集后,我们开始建立我们的模型。最后,我们有了一个模型,可以将各种句子分类为问题或一般陈述。

通过本教程,读者应该能够使用Snorkel以编程方式对数据集进行标注。