标记数据 Labeling data :
转换数据 Transforming data :
资料切片 Slicing data :
我们将完成五个基本步骤,透过官方范例 YouTube comments 资料集示范,具体程序执行笔者将官网范例调整为可以在 Colab 执行的范例,您可以透过 Colab 实作 。
ABSTAIN = -1
NOT_SPAM = 0
SPAM = 1
将用 LFs 以编程方式标记我们未标记的数据集,而不是手动标记任何训练数据。 以下为官方导览介绍的3种LF函数写法:
关键字判别、正规表达式判别与用外部模组判别。
from snorkel.labeling import labeling_function
# 关键字'my'筛选
@labeling_function()
def lf_keyword_my(x):
"""Many spam comments talk about 'my channel', 'my video', etc."""
return SPAM if "my" in x.text.lower() else ABSTAIN
#正规表达式筛选
import re
@labeling_function()
def lf_regex_check_out(x):
"""Spam comments say 'check out my video', 'check it out', etc."""
return SPAM if re.search(r"check.*out", x.text, flags=re.I) else ABSTAIN
#结合模组筛选
from textblob import TextBlob
@labeling_function()
def lf_textblob_polarity(x):
"""
We use a third-party sentiment classification model, TextBlob.
We combine this with the heuristic that non-spam comments are often positive.
"""
return NOT_SPAM if TextBlob(x.text).sentiment.polarity > 0.3 else ABSTAIN
LabelModel
LF 组合为 list,将 LFs 应用於伪标注的训练数据。snorkel.labeling.model.LabelModel
可以自动估计它们的准确性和相关性,重新加权和组合它们的标签,并生成我们最终的乾净、集成的训练标签集:
from snorkel.labeling.model import LabelModel
from snorkel.labeling import PandasLFApplier
# set LFs
lfs = [ lf_keyword_my,
lf_regex_check_out,
lf_short_comment,
lf_textblob_polarity
]
# Apply the LFs to the unlabeled training data
applier = PandasLFApplier(lfs)
L_train = applier.apply(df_train)
# Train the label model and compute the training labels
label_model = LabelModel(cardinality=2, verbose=True)
label_model.fit(L_train, n_epochs=500, log_freq=50, seed=123)
df_train["label"] = label_model.predict(L=L_train, tie_break_policy="abstain")
LabelModel
可能很多数据为标注结果为放弃标示状态的ABSTAIN = -1
,为清理训练资料集,将明显标注SPAM
、NOT_SPAM
的训练资料集保留进行後去处理。
df_train = df_train[df_train.label != ABSTAIN]
接着透过建立一个TF函数来增强这个标记的训练集。
以下get_synonyms()
用nltk.wordnet
获取单词的同义词。
import random
import nltk
from nltk.corpus import wordnet as wn
nltk.download("wordnet", quiet=True)
def get_synonyms(word):
"""Get the synonyms of word from Wordnet."""
lemmas = set().union(
*[s.lemmas() for s in wn.synsets(word)]
)
return list(
set(l.name().lower().replace("_", " ") for l in lemmas) - {word}
)
使用 TF snorkel.augmentation.transformation_function
做为装饰子,自订 tf_replace_word_with_synonym()
函数将生成的同义词加入训练资料集。
from snorkel.augmentation import transformation_function
@transformation_function()
def tf_replace_word_with_synonym(x):
"""Try to replace a random word with a synonym."""
words = x.text.lower().split()
idx = random.choice(range(len(words)))
synonyms = get_synonyms(words[idx])
if len(synonyms) > 0:
x.text = " ".join(words[:idx] +
[synonyms[0]] +
words[idx + 1 :]
)
return x
将自订 TF 函数加入训练数据集。
from snorkel.augmentation import ApplyOnePolicy, PandasTFApplier
tf_policy = ApplyOnePolicy(n_per_original=2, keep_original=True)
tf_applier = PandasTFApplier([tf_replace_word_with_synonym], tf_policy)
df_train_augmented = tf_applier.apply(df_train)
更多数据增强的调整可参阅 Spam TFs tutorial。
Snorkel 的 Slicing Function 可用以监控特定切片,以及透过针对不同切片增加特徵以提高模型性能。
延续 Youtube 评论之中可能有恶意连结的想法,为此撰写一个查找可疑缩网址的程序,这对找出恶意垃圾评论可能很关键。设定好 SF 可监控此切片的性能:
from snorkel.slicing import slicing_function
@slicing_function()
def short_link(x):
"""
Return whether text matches common pattern
for shortened ".ly" links.
"""
return int(bool(re.search(r"\w+\.ly", x.text)))
df_train_augmented
,以 Scikit-Learn 的 n-gram 逻辑回归模型进行推论,完成整个运用Snorkel 弱监督分类模型。
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression
train_text = df_train_augmented.text.tolist()
X_train = CountVectorizer(ngram_range=(1, 2)).fit_transform(train_text)
clf = LogisticRegression(solver="lbfgs")
clf.fit(X=X_train, y=df_train_augmented.label.values)
Page & Post 傻傻分不清楚 由於前两天在研究 Menu,发现设定 Menu 的时候...
今天来做搜寻看板的部分,首先Layout我先简单的放一个EditText以及Button,点击But...
前言 Hi, 我是鱼板伯爵今天铁人赛的最後一天了感谢大家的支持,不知道大家对这个架构是不是有一点感觉...
前言 延续着上篇内容,这篇要继续来介绍jstack有些什麽options可以使用 options 介...
昨晚群组热烈的讨论鱼排,从土魠鱼排、澎湖白金土魠鱼排、白鲳、鮸鱼、嘉鱲等等,让人好想来块煎的恰恰的鱼...