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

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嵌入在不久的將來值得關注。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章