自然語言工具包 - 變換詞塊



為什麼變換詞塊?

到目前為止,我們已經從句子中獲得了詞塊或短語,但我們應該如何處理它們呢?一項重要的任務是變換它們。但是為什麼呢?這樣做是為了實現以下目的:

  • 語法校正以及
  • 重新排列短語

過濾掉無關/無用的詞語

假設您想判斷一個短語的含義,那麼有很多常用的詞語,例如“the”、“a”,是無關緊要或無用的。例如,請看以下短語:

“這部電影很好”。

這裡最重要的詞語是“電影”和“好”。其他詞語,“the”和“was”都是無用或無關緊要的。這是因為即使沒有它們,我們也能理解短語的相同含義。“好電影”。

在下面的Python示例中,我們將學習如何藉助詞性標籤去除無用/無關緊要的詞語,並保留重要的詞語。

示例

首先,透過檢視treebank語料庫中的停用詞,我們需要確定哪些詞性標籤是重要的,哪些是不重要的。讓我們看看以下無關詞語和標籤的表格:

單詞 標籤
a DT
All PDT
An DT
And CC
Or CC
That WDT
The DT

從上表可以看出,除了CC之外,所有其他標籤都以DT結尾,這意味著我們可以透過檢視標籤的字尾來過濾掉無關緊要的詞語。

對於此示例,我們將使用一個名為filter()的函式,它接收一個詞塊並返回一個不包含任何無關標籤詞語的新詞塊。此函式過濾掉所有以DT或CC結尾的標籤。

示例

import nltk
def filter(chunk, tag_suffixes=['DT', 'CC']):
   significant = []
   for word, tag in chunk:
      ok = True
      for suffix in tag_suffixes:
         if tag.endswith(suffix):
            ok = False
            break
      if ok:
         significant.append((word, tag))
   return (significant)

現在,讓我們在Python示例中使用此filter()函式來刪除無關緊要的詞語:

from chunk_parse import filter
filter([('the', 'DT'),('good', 'JJ'),('movie', 'NN')])

輸出

[('good', 'JJ'), ('movie', 'NN')]

動詞校正

很多時候,在現實世界的語言中,我們會看到不正確的動詞形式。例如,“is you fine?”是不正確的。此句中的動詞形式不正確。句子應該是“are you fine?”NLTK為我們提供了一種透過建立動詞校正對映來糾正此類錯誤的方法。這些校正對映根據詞塊中是否存在複數或單數名詞來使用。

示例

要實現Python示例,我們首先需要定義動詞校正對映。讓我們建立兩個對映如下:

複數到單數對映

plural= {
   ('is', 'VBZ'): ('are', 'VBP'),
   ('was', 'VBD'): ('were', 'VBD')
}

單數到複數對映

singular = {
   ('are', 'VBP'): ('is', 'VBZ'),
   ('were', 'VBD'): ('was', 'VBD')
}

如上所示,每個對映都包含一個帶標籤的動詞,它對映到另一個帶標籤的動詞。我們示例中的初始對映涵蓋了is到are、was到were的基本對映,反之亦然。

接下來,我們將定義一個名為verbs()的函式,您可以在其中傳遞一個包含不正確動詞形式的詞塊,並獲得一個已更正的詞塊。為了完成此操作,verb()函式使用一個名為index_chunk()的輔助函式,該函式將在詞塊中搜索第一個帶標籤單詞的位置。

讓我們看看這些函式:

def index_chunk(chunk, pred, start = 0, step = 1):
   l = len(chunk)
   end = l if step > 0 else -1
   for i in range(start, end, step):
      if pred(chunk[i]):
         return i
      return None
def tag_startswith(prefix):
   def f(wt):
      return wt[1].startswith(prefix)
   return f

def verbs(chunk):
   vbidx = index_chunk(chunk, tag_startswith('VB'))
   if vbidx is None:
      return chunk
   verb, vbtag = chunk[vbidx]
   nnpred = tag_startswith('NN')
   nnidx = index_chunk(chunk, nnpred, start = vbidx+1)
   if nnidx is None:
      nnidx = index_chunk(chunk, nnpred, start = vbidx-1, step = -1)
   if nnidx is None:
      return chunk
   noun, nntag = chunk[nnidx]
   if nntag.endswith('S'):
      chunk[vbidx] = plural.get((verb, vbtag), (verb, vbtag))
   else:
      chunk[vbidx] = singular.get((verb, vbtag), (verb, vbtag))
   return chunk

將這些函式儲存在您安裝Python或Anaconda的本地目錄中的Python檔案中並執行它。我將其儲存為verbcorrect.py

現在,讓我們對一個詞性標註的is you fine詞塊呼叫verbs()函式:

from verbcorrect import verbs
verbs([('is', 'VBZ'), ('you', 'PRP$'), ('fine', 'VBG')])

輸出

[('are', 'VBP'), ('you', 'PRP$'), ('fine','VBG')]

消除短語中的被動語態

另一個有用的任務是從短語中消除被動語態。這可以透過圍繞動詞交換單詞來完成。例如,“本教程很棒”可以轉換為“很棒的教程”

示例

為了實現這一點,我們定義了一個名為eliminate_passive()的函式,它將使用動詞作為樞軸點,將詞塊的右側與左側交換。為了找到要圍繞其旋轉的動詞,它還將使用上面定義的index_chunk()函式。

def eliminate_passive(chunk):
   def vbpred(wt):
      word, tag = wt
      return tag != 'VBG' and tag.startswith('VB') and len(tag) > 2
   vbidx = index_chunk(chunk, vbpred)
   if vbidx is None:
      return chunk
   return chunk[vbidx+1:] + chunk[:vbidx]

現在,讓我們對一個詞性標註的the tutorial was great詞塊呼叫eliminate_passive()函式:

from passiveverb import eliminate_passive
eliminate_passive(
   [
      ('the', 'DT'), ('tutorial', 'NN'), ('was', 'VBD'), ('great', 'JJ')
   ]
)

輸出

[('great', 'JJ'), ('the', 'DT'), ('tutorial', 'NN')]

交換名詞基數

眾所周知,像5這樣的基數詞在詞塊中被標記為CD。這些基數詞通常出現在名詞之前或之後,但出於規範化的目的,將它們始終放在名詞之前非常有用。例如,日期1月5日可以寫成5月1日。讓我們透過以下示例來理解它。

示例

為了實現這一點,我們定義了一個名為swapping_cardinals()的函式,它將交換任何緊跟在名詞之後的基數與名詞。這樣,基數將出現在名詞之前。為了與給定標籤進行相等比較,它使用了我們命名為tag_eql()的輔助函式。

def tag_eql(tag):
   def f(wt):
      return wt[1] == tag
   return f

現在我們可以定義swapping_cardinals():

def swapping_cardinals (chunk):
   cdidx = index_chunk(chunk, tag_eql('CD'))
   if not cdidx or not chunk[cdidx-1][1].startswith('NN'):
      return chunk
   noun, nntag = chunk[cdidx-1]
   chunk[cdidx-1] = chunk[cdidx]
   chunk[cdidx] = noun, nntag
   return chunk

現在,讓我們對日期“1月5日”呼叫swapping_cardinals()函式:

from Cardinals import swapping_cardinals()
swapping_cardinals([('Janaury', 'NNP'), ('5', 'CD')])

輸出

[('10', 'CD'), ('January', 'NNP')]
10 January
廣告

© . All rights reserved.