目录
什么是'Flair'图书馆?
什么赋予了边缘?
用于序列标记的上下文字符串嵌入简介
使用Flair在Python中执行NLP任务
建立环境
关于数据集
1.使用Flair嵌入的文本分类
2.使用Flair标记语音(POS)
结束笔记
最近几年,自然语言处理(NLP) 作为一个领域令人难以置信!我们已经看到了多项突破 - ULMFiT,ELMo,Facebook的PyText,谷歌的BERT等等。这些已经迅速加速了NLP(尤其是语言建模)的最新研究。
我们现在可以预测下一句话,给出一系列前面的单词。
更重要的是,机器现在开始理解长期以来一直未能实现的关键因素。
背景! 理解背景已经打破了阻碍NLP技术取得进展的障碍。今天,我们将讨论一个这样的图书馆 - 弗莱尔。
到目前为止,这些单词要么表示为稀疏矩阵,要么表示为嵌入式单词,如GLoVe,Bert和ELMo,结果令人印象深刻。但是,总有改进的 余地,而且Flair愿意接受它。
在本文中,我们将首先了解Flair是什么以及它背后的概念。然后我们将深入探讨使用Flair实现NLP任务。准备好对它的准确性印象深刻!
请注意,本文假设您熟悉NLP概念。如果您需要快速复习,可以查看以下文章:
Flair是一个简单的自然语言处理(NLP)库,由Zalando Research开发和开源。Flair的框架直接构建在PyTorch上,PyTorch是最好的深度学习框架之一。Zalando Research团队还为以下NLP任务发布了几个预先训练的模型:
所有这些看起来很有希望。但真正引起我注意的是当我看到Flair在NLP中超越了几项最先进的成绩时。看看这张桌子:
注意:F1分数是主要用于分类任务的评估指标。在评估模型时,它通常用于机器学习项目中的精度度量。F1分数考虑了现有课程的分布。
Flair库中包含了许多令人敬畏的功能。这是我最挑选的一些:
在处理NLP任务时,上下文非常重要。学习基于先前字符预测下一个字符构成了序列建模的基础。
上下文字符串嵌入利用训练有素的字符语言模型的内部状态来产生一种新颖的字嵌入类型。 简单来说,它使用受过训练的角色模型的某些内部原则,使得单词在不同的句子中可以具有不同的含义。
注意: 语言和字符模型是单词/字符的概率分布,这样每个新单词或字符都取决于前面的单词或字符。看看 这里 了解更多。
有两个主要因素支持上下文字符串嵌入:
让我们看一个例子来理解这个:
说明:
语言是如此美妙而复杂的东西。您可以在本研究论文中阅读有关Contextual String Embeddings的更多信息 。
是时候让Flair进行测试了!我们已经看到了这个令人敬畏的图书馆的全部内容。现在让我们亲眼看看它在我们的机器上是如何工作的。
我们将使用Flair在Python中执行以下所有NLP任务:
我们将使用Google Colaboratory运行我们的代码。Colab最棒的一点是它免费提供GPU支持!这对于培训深度学习模型非常方便。
为何使用Colab?
您只需要一个稳定的互联网连接。
我们将研究Twitter Sentiment Analysis实践问题。继续从那里下载数据集(您需要先注册/登录)。
这一挑战带来的问题是:
这项任务的目的是检测推文中的仇恨言论。为了简单起见,我们说一条推文包含仇恨言论,如果它具有与之相关的种族主义或性别歧视情绪。因此,任务是从其他推文中对种族主义或性别歧视的推文进行分类。
步骤概述:
第1步:将数据导入Colab的本地环境:
第2步:安装Flair
第3步:准备文本以使用Flair
第4步:使用Flair嵌入Word
第5步:向量化文本
步骤6:为训练集和测试集分区数据
第7步:预测的时间!
第1步:将数据导入Colab的本地环境:
# Install the PyDrive wrapper & import libraries.
# This only needs to be done once per notebook.
!pip install -U -q PyDrive
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from google.colab import auth
from oauth2client.client import GoogleCredentials
# Authenticate and create the PyDrive client.
# This only needs to be done once per notebook.
auth.authenticate_user()
gauth = GoogleAuth()
gauth.credentials = GoogleCredentials.get_application_default()
drive = GoogleDrive(gauth)
# Download a file based on its file ID.
# A file ID looks like: laggVyWshwcyP6kEI-y_W3P8D26sz
file_id = '1GhyH4k9C4uPRnMAMKhJYOqa-V9Tqt4q8' ### File ID ###
data = drive.CreateFile({'id': file_id})
#print('Downloaded content "{}"'.format(downloaded.GetContentString()))
您可以在驱动器中数据集文件的可共享链接中找到文件ID。
将数据集导入Colab笔记本:
import io
Import pandas as pd
data = pd.read_csv(io.StringIO(data.GetContentString()))
data.head()
已从数据中删除所有表情符号和符号,并且字符已转换为小写。此外,我们的数据集已经分为火车和测试集。 您可以从此处下载此干净数据集 。
第2步:安装Flair
#download flair library
#import torch
!pip install flair
import flair
简要介绍一下Flair数据类型
这个库的核心有两种类型 - 句子和令牌 对象。A Sentence持有 一个文本句子,基本上是令牌列表:
from flair.data import Sentence
# create a sentence #
sentence = Sentence('Blogs of Analytics Vidhya are Awesome.')
# print the sentence to see what’s in it. #
print(Sentence)
第3步:准备文本以使用Flair
#extracting the tweet part#
text = data['tweet']
## txt is a list of tweets ##
txt = text.tolist()
print(txt[:10])
第4步:使用Flair嵌入Word
如果您是单词嵌入的新手,请随意首先阅读本文:对Word嵌入的直观理解。
## Importing the Embeddings ##
from flair.embeddings import WordEmbeddings
from flair.embeddings import CharacterEmbeddings
from flair.embeddings import StackedEmbeddings
from flair.embeddings import FlairEmbeddings
from flair.embeddings import BertEmbeddings
from flair.embeddings import ELMoEmbeddings
from flair.embeddings import FlairEmbeddings
### Initialising embeddings (un-comment to use others) ###
#glove_embedding = WordEmbeddings('glove')
#character_embeddings = CharacterEmbeddings()
flair_forward = FlairEmbeddings('news-forward-fast')
flair_backward = FlairEmbeddings('news-backward-fast')
#bert_embedding = BertEmbedding()
#elmo_embedding = ElmoEmbedding()
stacked_embeddings = StackedEmbeddings( embeddings = [
flair_forward-fast,
flair_backward-fast
])
你会注意到我们刚刚使用了一些上面最流行的单词嵌入。真棒!您可以删除评论'#'以使用所有嵌入。
现在你可能会问 - 世界上什么是“Stacked Embeddings”?在这里,我们可以组合多个嵌入来构建功能强大的单词表示模型,而不会有太多复杂性。很喜欢合奏,不是吗?
我们使用Flair的堆叠嵌入只是为了减少本文中的计算时间。 使用您喜欢的任何组合随意玩这个和其他嵌入。
测试堆叠嵌入:
# create a sentence #
sentence = Sentence(‘ Analytics Vidhya blogs are Awesome .')
# embed words in sentence #
stacked.embeddings(sentence)
for token in sentence:
print(token.embedding)
# data type and size of embedding #
print(type(token.embedding))
# storing size (length) #
z = token.embedding.size()[0]
第5步:向量化文本
我们将使用两种方法展示这一点。
在推文中嵌入词的意思
我们将在这种方法中计算以下内容:
对于每个句子:
from tqdm import tqdm ## tracks progress of loop ##
# creating a tensor for storing sentence embeddings #
s = torch.zeros(0,z)
# iterating Sentence (tqdm tracks progress) #
for tweet in tqdm(txt):
# empty tensor for words #
w = torch.zeros(0,z)
sentence = Sentence(tweet)
stacked_embeddings.embed(sentence)
# for every word #
for token in sentence:
# storing word Embeddings of each word in a sentence #
w = torch.cat((w,token.embedding.view(-1,z)),0)
# storing sentence Embeddings (mean of embeddings of all words) #
s = torch.cat((s, w.mean(dim = 0).view(-1, z)),0)
文档嵌入:矢量化整个推文
from flair.embeddings import DocumentPoolEmbeddings
### initialize the document embeddings, mode = mean ###
document_embeddings = DocumentPoolEmbeddings([
flair_embedding_backward,
flair_embedding_forward
])
# Storing Size of embedding #
z = sentence.embedding.size()[1]
### Vectorising text ###
# creating a tensor for storing sentence embeddings
s = torch.zeros(0,z)
# iterating Sentences #
for tweet in tqdm(txt):
sentence = Sentence(tweet)
document_embeddings.embed(sentence)
# Adding Document embeddings to list #
s = torch.cat((s, sentence.embedding.view(-1,z)),0 )
您可以为您的模型选择任一种方法。 现在我们的文本已经过矢量化,我们可以将其提供给我们的机器学习模型!
步骤6:为训练集和测试集分区数据
## tensor to numpy array ##
X = s.numpy()
## Test set ##
test = X[31962:,:]
train = X[:31962,:]
# extracting labels of the training set #
target = data['label'][data['label'].isnull()==False].values
第6步:构建模型并定义自定义评估程序(用于F1分数)
为XGBoost定义自定义F1评估程序
def custom_eval(preds, dtrain):
labels = dtrain.get_label().astype(np.int)
preds = (preds >= 0.3).astype(np.int)
return [('f1_score', f1_score(labels, preds))]
构建XGBoost模型
import xgboost as xgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score
### Splitting training set ###
x_train, x_valid, y_train, y_valid = train_test_split(train, target,
random_state=42,
test_size=0.3)
### XGBoost compatible data ###
dtrain = xgb.DMatrix(x_train,y_train)
dvalid = xgb.DMatrix(x_valid, label = y_valid)
### defining parameters ###
params = {
'colsample': 0.9,
'colsample_bytree': 0.5,
'eta': 0.1,
'max_depth': 8,
'min_child_weight': 6,
'objective': 'binary:logistic',
'subsample': 0.9
}
### Training the model ###
xgb_model = xgb.train(
params,
dtrain,
feval= custom_eval,
num_boost_round= 1000,
maximize=True,
evals=[(dvalid, "Validation")],
early_stopping_rounds=30
)
我们的模型已经过培训,可以进行评估! 注意:参数取自本笔记本。
第7步:预测的时间!
### Reformatting test set for XGB ###
dtest = xgb.DMatrix(test)
### Predicting ###
predict = xgb_model.predict(dtest) # predicting
我将预测上传到练习题页面,其中0.2为概率阈值:
Word Embedding |
F1- Score |
|
Glove |
0.53 |
|
flair-forward -fast |
0.45 |
|
flair-backward-fast |
0.48 |
|
Stacked (flair-forward-fast + flair-backward-fast) |
0.54 |
|
注意:根据Flair的官方文档,将天赋嵌入与其他嵌入物堆叠在一起通常会产生更好的效果,但是,有一个问题。
在CPU上计算可能需要非常长的时间。我强烈建议利用GPU来获得更快的结果。你可以在Colab中使用免费的!
我们将使用Conll-2003数据集的一个子集,是一个预先标记的英文数据集。从这里下载数据集 。
步骤概述:
第1步:导入数据集
第2步:从数据集中提取句子和PoS标签
第3步:使用NLTK和Flair标记文本
步骤4:针对标记数据集评估来自NLTK和Flair的PoS标记
第1步:导入数据集
### file was uploaded manually to local environment of Colab ###
data = open('pos-tagged_corpus.txt','r')
txt = data.read()
#print(txt)
数据文件每行包含一个单词,空行表示句子边界。
第2步:从数据集中提取句子和PoS标签
### converting text in form of list of (words with their tags) ###
txt = txt.split('\n')
### removing DOCSTART (document header)
txt = [x for x in txt if x != '-DOCSTART- -X- -X- O']
### check ###
for i in range(10):
print(txt[i])
print(‘-’*10)
### Extracting Sentences ###
# Initialize empty list for storing words
words = []
# initialize empty list for storing sentences #
corpus = []
for i in tqdm(txt):
## if blank sentence encountered ##
if i =='':
## previous words form a sentence ##
corpus.append(' '.join(words))
## Refresh Word list ##
words = []
else:
## word at index 0 ##
words.append(i.split()[0])
# did it work? #
for i in range(10):
print(corpus[i])
print(‘-’*10)
### Extracting POS ###
# Initialize empty list for storing word pos
w_pos = []
#initialize empty list for storing sentence pos #
POS = []
for i in tqdm(txt):
## blank sentence = new line ##
if i =='':
## previous words form a sentence POS ##
POS.append(' '.join(w_pos))
## Refresh words list ##
w_pos = []
else:
## pos tag from index 1 ##
w_pos.append(i.split()[1])
# did it work? #
for i in range(10):
print(corpus[i])
print(POS[i])
### Removing blanks form sentence and pos ###
corpus = [x for x in corpus if x!= '']
POS = [x for x in POS if x!= '']
### Check ###
For i in range(10):
print(corpus[i])
print(POS[i])
我们从数据集中提取了我们需要的基本方面。让我们继续第3步。
第3步:使用NLTK和Flair标记文本
首先,导入所需的库:
import nltk
nltk.download('tagsets')
nltk.download('punkt')
nltk.download('averaged_perceptron_tagger')
from nltk import word_tokenize
这将下载所有必要的文件以使用NLTK标记文本。
### Tagging the corpus with NLTK ###
#for storing results#
nltk_pos = []
##for every sentence ##
for i in tqdm(corpus):
# Tokenize sentence #
text = word_tokenize(i)
#tag Words#
z = nltk.pos_tag(text)
# store #
nltk_pos.append(z)
PoS标签采用以下格式:
[('token_1','tag_1'),............ ..,('token_n','tag_n')]
让我们从中提取PoS:
### Extracting final pos by nltk in a list ###
tmp = []
nltk_result = []
## every tagged sentence ##
for i in tqdm(nltk_pos):
tmp = []
## every word ##
for j in i:
## append tag (from index 1) ##
tmp.append(j[1])
# join the tags of every sentence #
nltk_result.append(' '.join(tmp))
### check ###
for i in range(10):
print(nltk_result[i])
print(corpus[i])
NLTK标签已准备就绪。
首先导入库:
!pip install flairfrom flair.data import Sentencefrom flair.models import SequenceTagger
使用Flair标记
# initiating object #
pos = SequenceTagger.load('pos-fast')
#for storing pos tagged string#
f_pos = []
## for every sentence ##
for i in tqdm(corpus):
sentence = Sentence(i)
pos.predict(sentence)
## append tagged sentence ##
f_pos.append(sentence.to_tagged_string())
###check ###
for i in range(10):
print(f_pos[i])
print(corpus[i])
结果如下:
token_1
注意:我们可以在Flair库中使用不同的标记器。随意修补和实验。你可以在这里找到清单。
像在NLTK中那样提取句子标签
Import re
### Extracting POS tags ###
## in every sentence by index ##
for i in tqdm(range(len(f_pos))):
## for every words ith sentence ##
for j in corpus[i].split():
## replace that word from ith sentence in f_pos ##
f_pos[i] = str(f_pos[i]).replace(j,"",1)
## Removing < > symbols ##
for j in ['<','>']:
f_pos[i] = str(f_pos[i]).replace(j,"")
## removing redundant spaces ##
f_pos[i] = re.sub(' +', ' ', str(f_pos[i]))
f_pos[i] = str(f_pos[i]).lstrip()
### check ###
for i in range(10):
print(f_pos[i])
print(corpus[i])
啊哈!我们终于标记了语料库并将其提取出句子。我们可以自由删除所有标点符号和特殊符号。
### Removing Symbols and redundant space ###
## in every sentence by index ##
for i in tqdm(range(len(corpus))):
# Removing Symbols #
corpus[i] = re.sub('[^a-zA-Z]', ' ', str(corpus[i]))
POS[i] = re.sub('[^a-zA-Z]', ' ', str(POS[i]))
f_pos[i] = re.sub('[^a-zA-Z]', ' ', str(f_pos[i]))
nltk_result[i] = re.sub('[^a-zA-Z]', ' ', str(nltk_result[i]))
## Removing HYPH SYM (they are for symbols) ##
f_pos[i] = str(f_pos[i]).replace('HYPH',"")
f_pos[i] = str(f_pos[i]).replace('SYM',"")
POS[i] = str(POS[i]).replace('SYM',"")
POS[i] = str(POS[i]).replace('HYPH',"")
nltk_result[i] = str(nltk_result[i].replace('HYPH',''))
nltk_result[i] = str(nltk_result[i].replace('SYM',''))
## Removing redundant space ##
POS[i] = re.sub(' +', ' ', str(POS[i]))
f_pos[i] = re.sub(' +', ' ', str(f_pos[i]))
corpus[i] = re.sub(' +', ' ', str(corpus[i]))
nltk_result[i] = re.sub(' +', ' ', str(nltk_result[i]))
我们使用NLTK和Flair标记了语料库,提取并删除了所有不必要的元素。 让我们自己看看:
for i in range(1000):
print('corpus '+corpus[i])
print('actual '+POS[i])
print('nltk '+nltk_result[i])
print('flair '+f_pos[i])
print('-'*50)
OUTPUT:
corpus SOCCER JAPAN GET LUCKY WIN CHINA IN SURPRISE DEFEAT
actual NN NNP VB NNP NNP NNP IN DT NN
nltk NNP NNP NNP NNP NNP NNP NNP NNP NNP
flair NNP NNP VBP JJ NN NNP IN NNP NNP
————————————————–
corpus Nadim Ladki
actual NNP NNP
nltk NNP NNP
flair NNP NNP
————————————————–
corpus AL AIN United Arab Emirates
actual NNP NNP NNP NNPS CD
nltk NNP NNP NNP VBZ JJ
flair NNP NNP NNP NNP CD
这看起来很有说服力!
步骤4:针对标记数据集评估来自NLTK和Flair的PoS标记
在这里,我们在定制评估器的帮助下对标签进行逐字评估。
corpus Japan coach Shu Kamo said The Syrian own goal proved lucky for us
actual NNP NN NNP NNP VBD POS DT JJ JJ NN VBD JJ IN PRP
nltk NNP VBP NNP NNP VBD DT JJ JJ NN VBD JJ IN PRP
flair NNP NN NNP NNP VBD DT JJ JJ NN VBD JJ IN PRP
请注意,在上面的示例中,与NLTK和flair标签相比,实际的POS标签包含冗余(如粗体所示)。因此,我们不会考虑句子长度不等的POS标记句子。
### EVALUATION FUNCTION ###
def eval(x,y):
# correct match #
count = 0
#Total comparisons made#
comp = 0
## for every sentence index in dataset ##
for i in range(len(x)):
## if the sentence length match ##
if len(x[i].split()) == len(y[i].split()):
## compare each word ##
for j in range(len(x[i].split())):
if x[i][j] == y[i][j] :
## Match! ##
count = count+1
comp = comp + 1
else:
comp = comp + 1
return (count/comp)*100
最后,我们根据数据集提供的POS标签评估NLTK和Flair的POS标签。
print(“nltk Score”,eval2(POS,nltk_result))
print(“Flair Score”,eval2(POS,f_pos))
我们的结果:
NLTK得分: 85.38654023442645
天赋得分: 90.96172124773179
好吧,好吧。我可以看到为什么Flair在NLP社区得到了如此多的关注。
Flair显然在字嵌入和堆叠字嵌入方面提供了优势。由于其高级API,这些可以毫不费力地实现。Flair嵌入在不久的将来值得关注。