NLP的Flair简介:一个简单但功能强大的最先进的NLP库

 

目录

什么是'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概念。如果您需要快速复习,可以查看以下文章:

  • 在Python中理解和实现文本分类的综合指南
  • 理解和实现自然语言处理的终极指南(使用Python编写代码)
  • 对Word嵌入的直观理解:从计数向量到Word2Vec
  • PyTorch简介 - 一个简单而强大的深度学习库

 

目录

  1. 什么是'Flair'图书馆?
  2. 什么赋予Flair the Edge
  3. 用于序列标记的上下文字符串嵌入简介
  4. 使用Flair在Python中执行NLP任务
  5. Flair的下一步是什么?

 

什么是'Flair'图书馆?

Flair是一个简单的自然语言处理(NLP)库,由Zalando Research开发和开源。Flair的框架直接构建在PyTorch上,PyTorch是最好的深度学习框架之一。Zalando Research团队还为以下NLP任务发布了几个预先训练的模型:

  1. 名称 - 实体识别(NER):它可以识别单词是代表文本中的人,位置还是名称。
  2. 词性标注(PoS):将给定文本中的所有单词标记为它们所属的“词性”。
  3. 文本分类:根据标准对文本进行分类(标签)
  4. 培训定制模型:制作我们自己的定制模型。

所有这些看起来很有希望。但真正引起我注意的是当我看到Flair在NLP中超越了几项最先进的成绩时。看看这张桌子:

注意:F1分数是主要用于分类任务的评估指标。在评估模型时,它通常用于机器学习项目中的精度度量。F1分数考虑了现有课程的分布。

 

什么赋予了边缘?

Flair库中包含了许多令人敬畏的功能。这是我最挑选的一些:

  1. 包括流行的和最先进的字嵌入,如GloVe,BERT,ELMo,字符嵌入等。感谢Flair API非常容易使用
  2. Flair的界面允许我们组合不同的单词嵌入并使用它们来嵌入文档。这反过来导致结果显着上升
  3. 'Flair Embedding'是Flair库中提供的标志性嵌入。它由上下文字符串嵌入提供支持。我们将在下一节中详细了解这一概念
  4. Flair支持多种语言 - 并且总是希望添加新语言

 

用于序列标记的上下文字符串嵌入简介

在处理NLP任务时,上下文非常重要。学习基于先前字符预测下一个字符构成了序列建模的基础。

上下文字符串嵌入利用训练有素的字符语言模型的内部状态来产生一种新颖的字嵌入类型。 简单来说,它使用受过训练的角色模型的某些内部原则,使得单词在不同的句子中可以具有不同的含义。

注意: 语言和字符模型是单词/字符的概率分布,这样每个新单词或字符都取决于前面的单词或字符。看看  这里 了解更多。

有两个主要因素支持上下文字符串嵌入:

  1. 这些单词被训练为角色(没有任何单词的概念)。Aka,它的工作方式类似于字符嵌入
  2. 嵌入由其周围文本进行上下文化。这意味着根据上下文,相同的单词可以具有不同的嵌入。很像天然的人类语言,不是吗?在不同的情况下,同一个词可能有不同的含义

让我们看一个例子来理解这个:

  • 案例1:读一本书
  • 案例2:请预订火车票

说明:

  • 在案例1中,书是一个  对象
  • 在案例2中,book是VERB

语言是如此美妙而复杂的东西。您可以在本研究论文中阅读有关Contextual String Embeddings的更多信息  。

 

使用Flair在Python中执行NLP任务

是时候让Flair进行测试了!我们已经看到了这个令人敬畏的图书馆的全部内容。现在让我们亲眼看看它在我们的机器上是如何工作的。

我们将使用Flair在Python中执行以下所有NLP任务:

  1. 使用Flair嵌入进行文本分类
  2. 部分语音标记(PoS)和与NLTK库的比较

 

建立环境


我们将使用Google Colaboratory运行我们的代码。Colab最棒的一点是它免费提供GPU支持!这对于培训深度学习模型非常方便。

 

为何使用Colab?

  • 完全免费
  • 配备相当不错的硬件配置
  • 它位于您的Web浏览器上,因此即使是具有过时硬件的旧机器也可以运行它
  • 已连接到您的Google云端硬盘
  • 与Github很好地集成

您只需要一个稳定的互联网连接。

 

关于数据集

我们将研究Twitter Sentiment Analysis实践问题。继续从那里下载数据集(您需要先注册/登录)。

这一挑战带来的问题是:

这项任务的目的是检测推文中的仇恨言论。为了简单起见,我们说一条推文包含仇恨言论,如果它具有与之相关的种族主义或性别歧视情绪。因此,任务是从其他推文中对种族主义或性别歧视的推文进行分类。

 

1.使用Flair嵌入的文本分类

步骤概述:

第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步:向量化文本

我们将使用两种方法展示这一点。

 

在推文中嵌入词的意思

我们将在这种方法中计算以下内容:

对于每个句子:

  1. 为每个单词生成单词嵌入
  2. 计算每个单词的嵌入的平均值以获得句子的嵌入

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中使用免费的!

2.使用Flair标记语音(POS)

我们将使用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标记文本

  • 使用NLTK标记:

首先,导入所需的库:

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标签已准备就绪。

  • 现在把注意力转向Flair

首先导入库:

!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 token_2 ..................... .. token_n

注意:我们可以在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嵌入在不久的将来值得关注。

 

你可能感兴趣的:(NLP,NLU,NLI,自然语言处理,理解,推理)