Flair:一款简单但技术先进的NLP库

过去的几年里,在NLP(天然语言处理)领域,咱们已经见证了多项使人难以置信的突破,如ULMFiT、ELMo、Facebook的PyText以及谷歌的BERT等等。浏览器

这些技术大大推动了NLP的前沿性研究,尤为是语言建模。只要给出前几个单词的顺序,咱们就能够预测下一个句子。app

但更重要的是,机器也找到了长期没法实现推测语句的关键因素。框架

那就是:语境!dom

对语境的了解打破了阻碍NLP技术进步的障碍。而今天,咱们就来讨论这样的一个库:Flair。机器学习

 

Flair:一款简单但技术先进的NLP库

 

 

 

至今为止,单词要么表示为稀疏矩阵,要么表示为嵌入式词语,如GLoVe,Bert和ELMo。可是,事物总有改进的空间,Flair就愿意更正不足。oop

在本文中,首先咱们将了解Flair是什么以及其背后的概念。而后将深刻讨论使用Flair实现NLP任务。学习

Flair:一款简单但技术先进的NLP库

 

 

一. 什么是Flair库?测试

Flair:一款简单但技术先进的NLP库

 

 

 

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

1. 名称-实体识别(NER):它能够识别单词是表明文本中的人,位置仍是名称。google

2. 词性标注(PoS):将给定文本中的全部单词标记为它们所属的“词性”。

3. 文本分类:根据标准对文本进行分类(标签)。

4. 培训定制模型:制做咱们本身的定制模型。

全部的这些模型,看起来颇有前景。但真正引发我注意的是,当我看到Flair在NLP中超越了几项最早进成绩的时候。看看这个目录:

 

Flair:一款简单但技术先进的NLP库

 

 

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

 

Flair:一款简单但技术先进的NLP库

 

 

二. Flair库的优点是什么?

 

Flair库中包含了许多强大的功能,如下是最突出的一些方面:

· 它包括了最通用和最早进的单词嵌入方式,如GloVe,BERT,ELMo,字符嵌入等。凭借Flair API技术,使用起来很是容易。

· Flair的界面容许咱们组合不一样的单词嵌入并嵌入文档,显著优化告终果。

· 'Flair 嵌入'是Flair库提供的签名嵌入。它由上下文字符串嵌入提供支持,咱们将在下一节中详细了解这一律念。

· Flair支持多种语言,并有望添加新语种。

Flair:一款简单但技术先进的NLP库

 

 

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

 

在处理NLP任务时,上下文语境很是重要。经过先前字符预测下一个字符,这一学习过程构成了序列建模的基础。

上下文字符串的嵌入,是经过熟练利用字符语言模型的内部状态,来产生一种新的嵌入类型。简单来讲,它经过字符模型中的某些内部原则,使单词在不一样的句子中能够具备不一样的含义。

注意:语言和字符模型是单词/字符的几率分布,所以每一个新单词或新字符都取决于前面的单词或字符。

 

Flair:一款简单但技术先进的NLP库

 

 

 

有两个主要因素驱动了上下文字符串的嵌入:

1. 这些单词被理解为字符(没有任何单词的概念)。也就是说,它的工做原理相似于字符嵌入。

2. 嵌入是经过其周围文本进行语境化的。这意味着根据上下文,相同的单词能够有不一样的嵌入意义。很像天然的人类语言,不是吗?在不一样的状况下,同一个词可能有不一样的含义。

让咱们看个例子来理解这个意思:

· 案例1:读一本书(Reading a book)

· 案例2:请预订火车票(Please book a train ticket)

说明:

· 在案例1中,book是一个名词

· 在案例2中,book是动词

语言是如此奇妙而复杂的东西啊!

Flair:一款简单但技术先进的NLP库

 

 

四. 使用Flair在Python中执行NLP任务

 

是时候让Flair进行测试了!咱们已经了解了这个神奇图书馆的所有内容。如今让咱们亲眼看看它在机器上是如何运行的。

咱们将使用Flair在Python中执行如下全部NLP任务:

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

2.词性标记(PoS)与NLTK库的比较

创建环境

 

Flair:一款简单但技术先进的NLP库

 

 

咱们将使用Google Colaboratory运行咱们的代码。Colab最棒的一点就是它免费提供GPU支持!这极大地方便了学习模型的深度培训。

为何使用Colab?

· 彻底免费

· 具备至关不错的硬件配置

· 你的Web浏览器上都有,即便是硬件过期的旧机器也能够运行

· 链接到你的Google云端硬盘

· 很好地与Github集成

你只须要一个稳定的互联网链接。

关于数据集

咱们将努力研究Twitter Sentiment Analysis(推特敏感度分析)的实践问题。

而这一挑战带来的问题是:

这项任务的目的是检测推文中的仇恨言论。为了简单起见,若是它带有相关的种族主义或性别歧视情绪,咱们则判断这条推文包含仇恨言论。所以,这项任务是将带有种族主义或性别歧视地推文与其余推文分类。

1.使用Flair嵌入进行文本分类

第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数据类型

这个库的对象有两种类型—句子和标记对象。一个句子持有一个文本句子,基本上是标记列表:

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嵌入单词

## 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

])

 

你会注意到,咱们刚刚使用了一些上面最流行的单词嵌入。你能够删除评论'#'以使用全部嵌入。

如今你可能会问,到底什么是“堆叠嵌入”?在这里,咱们能够结合多个嵌入来构建一个功能强大的单词表示模型,不须要太复杂。很像合唱,不是吗?

咱们使用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

 

第7步:构建模型并定义自定义评估程序(用于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

)

 

至此,咱们的模型已经经过训练,能够进行评估了!

第8步: 能够预测了!

### Reformatting test set for XGB ###

dtest = xgb.DMatrix(test)

### Predicting ###

predict = xgb_model.predict(dtest) # predicting

 

咱们能够把预测上传到练习题界面,其中,0.2是几率阈值。

 

Flair:一款简单但技术先进的NLP库

 

 

 

注意:根据Flair的官方文档显示,一个嵌入和其余嵌入堆叠时,效果更佳。可是存在一个问题。

 

Flair:一款简单但技术先进的NLP库

 

 

 

在CPU上计算可能须要很是长的时间,强烈建议利用GPU来得到更快的结果,你能够在Colab中使用免费的。

 

2.词性标注(POS)

咱们将使用Conll-2003数据集的一个子集,是一个预先标记的英文数据集。

第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(' ')

### 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 flair

from flair.data import Sentence

from 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 <tag_1> token_2 <tag_2> ………………….. token_n <tag_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)

 

输出:

 

Flair:一款简单但技术先进的NLP库

 

 

 

结果看起来很是有说服力!

第4步:针对标记数据集评估来自NLTK和Flair的PoS标记

在这里,咱们将在定制评估器的帮助下对标签进行逐字评估。

 

Flair:一款简单但技术先进的NLP库

 

 

 

请注意,在上面的示例中,与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

Flair 评估分数: 90.96172124773179

 

Flair显然在字嵌入和堆叠字嵌入方面占据优点。因为其高级的API,这些嵌入能够绝不费力地实现。

相关文章
相关标签/搜索