NLTK 提供的條件頻率分佈功能,能有效分析文字資料中的詞彙關聯性。透過 nltk.ConditionalFreqDist,我們可以建立條件機率分佈表,快速查詢特定詞彙的後續詞彙分佈情況,並利用 most_common 方法找出最常出現的組合。文章中的程式碼範例,展示瞭如何載入語料函式庫、建立二元語法模型,並繪製圖表呈現分析結果。除了條件頻率分佈外,也介紹了詞彙資源、停用詞等重要概念,以及如何透過 Python 函式和模組管理程式碼,提升程式碼的重用性。這些技術對於文字分析、字謎遊戲等應用都相當有幫助,能更深入地理解和運用自然語言處理技術。

NLTK 條件頻率分佈在自然語言處理中的應用與實踐

在自然語言處理(NLP)領域中,條件頻率分佈(Conditional Frequency Distribution, CFD)是一種非常有用的資料結構,用於分析詞彙之間的關聯性。本文將探討 NLTK 函式庫中條件頻率分佈的實作,並透過具體範例展示其在文字分析中的應用。

條件頻率分佈的基本概念

條件頻率分佈是一種特殊的頻率分佈,用於記錄特定條件下樣本的出現頻率。在 NLTK 中,條件頻率分佈可以透過 nltk.ConditionalFreqDist 類別來建立。以下是一個簡單的範例:

import nltk
from nltk.corpus import genesis
from nltk.util import ngrams

# 載入 Genesis 語料函式庫
text = genesis.words('english-kjv.txt')

# 建立二元語法模型
bigrams = ngrams(text, 2)

# 建立條件頻率分佈
cfd = nltk.ConditionalFreqDist(bigrams)

# 查詢 'living' 後面的詞彙頻率
print(cfd['living'])

內容解密:

  1. genesis.words('english-kjv.txt') 載入了 Genesis 語料函式庫的英文版本。
  2. ngrams(text, 2) 建立了文字的二元語法模型,即將文字切分成相鄰的兩個詞彙為一組的序列。
  3. nltk.ConditionalFreqDist(bigrams) 根據二元語法模型建立條件頻率分佈,記錄每個詞彙後面跟隨的其他詞彙的頻率。
  4. cfd['living'] 查詢了 ’living’ 這個詞彙後面跟隨的其他詞彙的頻率分佈。

條件頻率分佈的常用方法

NLTK 的 ConditionalFreqDist 類別提供了多種方法來操作和查詢條件頻率分佈。以下是一些常用的方法:

方法描述
cfdist = ConditionalFreqDist(pairs)從一組配對中建立條件頻率分佈
cfdist.conditions()傳回所有條件的排序列表
cfdist[condition]傳回指定條件下的頻率分佈
cfdist[condition][sample]傳回指定條件下特定樣本的頻率
cfdist.tabulate()以表格形式顯示條件頻率分佈
cfdist.plot()以圖形方式顯示條件頻率分佈

程式碼範例:使用條件頻率分佈分析文字

import nltk
from nltk.corpus import genesis
from nltk.util import bigrams
import matplotlib.pyplot as plt

# 載入 Genesis 語料函式庫
text = genesis.words('english-kjv.txt')

# 建立二元語法模型
bigrams = list(nltk.bigrams(text))

# 建立條件頻率分佈
cfd = nltk.ConditionalFreqDist(bigrams)

# 查詢 'living' 後面的詞彙頻率並輸出前5個最常見的詞彙
print(cfd['living'].most_common(5))

# 繪製 'living' 後面跟隨的詞彙的頻率分佈圖
cfd['living'].plot(5, title='Frequency Distribution of Words Following "living"')
plt.show()

內容解密:

  1. nltk.bigrams(text) 建立了文字的二元語法模型。
  2. nltk.ConditionalFreqDist(bigrams) 根據二元語法模型建立條件頻率分佈。
  3. cfd['living'].most_common(5) 輸出了 ’living’ 後面跟隨的5個最常見的詞彙及其頻率。
  4. cfd['living'].plot(5) 繪製了 ’living’ 後面跟隨的詞彙的頻率分佈圖,前5個最常見的詞彙。

重用程式碼:使用文字編輯器和 Python 函式

在進行 NLP 任務時,重用程式碼是非常重要的。我們可以使用文字編輯器來編寫 Python 程式,並將其儲存為 .py 檔案,以便重複使用。

使用文字編輯器建立 Python 程式

  1. 開啟 IDLE 文字編輯器,建立一個新檔案。
  2. 輸入以下程式碼:

print(‘Monty Python’)

3. 將檔案儲存為 `monty.py`。
4. 在 IDLE 中執行該程式。

#### 使用 Python 函式重用程式碼

函式是 Python 中重用程式碼的基本單位。我們可以定義一個函式來執行特定的任務,並在需要時呼叫它。

```python
def lexical_diversity(text):
    return len(text) / len(set(text))

# 範例用法
text = genesis.words('english-kjv.txt')
diversity_score = lexical_diversity(text)
print(diversity_score)

內容解密:

  1. def lexical_diversity(text): 定義了一個名為 lexical_diversity 的函式,用於計算文字的詞彙多樣性。
  2. return len(text) / len(set(text)) 傳回文字中不同詞彙的比例,即詞彙多樣性得分。

NLP 處理流程圖

  graph LR;
    A[原始文字] --> B[分詞];
    B --> C[去除停用詞];
    C --> D[詞幹提取];
    D --> E[建立語言模型];
    E --> F[條件頻率分佈分析];
    F --> G[結果輸出];

圖表翻譯:
此圖表示展示了 NLP 處理的基本流程。首先,從原始文字開始,經過分詞處理,將文字切分成單個詞彙。接著,去除停用詞以減少不必要的幹擾。然後,進行詞幹提取,將不同形式的詞彙還原為其基本形式。之後,建立語言模型,用於捕捉詞彙之間的關聯性。最後,利用條件頻率分佈分析語言模型的特性,並輸出分析結果。整個流程清晰地展示了 NLP 處理的主要步驟和技術應用。

2.4 詞彙資源

隨著時間的推移,你會發現自己建立了各種有用的文字處理函式,並在不同的程式之間複製它們。但問題來了:哪個檔案包含了你想要使用的最新版本的函式?如果你能把你的工作集中在一個地方,並且在不需要複製的情況下存取先前定義的函式,那麼生活會變得容易得多。

將函式儲存在模組中

要實作這一點,只需將你的函式儲存在一個名為(例如)textproc.py的檔案中。現在,你可以簡單地透過從檔案中匯入來存取你的工作:

>>> from textproc import plural
>>> plural('wish')
'wishes'
>>> plural('fan')
'fen'

很明顯,我們的plural函式有一個錯誤,因為fan的複數形式應該是fans。與其輸入一個新版本的函式,我們可以直接編輯現有的那個。因此,在每個階段,只有一個版本的plural函式,不會混淆正在使用哪一個。

內容解密:

這段程式碼展示瞭如何從自定義模組textproc中匯入函式plural。首先,我們需要確保textproc.py檔案存在於正確的路徑下。當我們執行from textproc import plural時,Python會在當前目錄和其他路徑中尋找textproc.py檔案,並匯入其中的plural函式。這樣,我們就可以直接使用plural函式,而不需要每次都重新定義它。

Python 模組與套件

一個檔案中變數和函式定義的集合被稱為Python模組。一組相關模組的集合被稱為套件(package)。NLTK用於處理Brown語料函式庫的程式碼是一個模組的例子,而它用於處理所有不同語料函式庫的程式碼集合是一個套件的例子。NLTK本身是一組套件,有時被稱為函式庫。

注意事項:

  • 在建立包含Python程式碼的檔案時,千萬不要命名為nltk.py,否則可能會被匯入而取代真正的NLTK套件。
  • 當Python匯入模組時,它首先會在當前目錄(資料夾)中查詢。

詞彙資源

詞彙資源(lexical resource)是一組單詞和/或短語及其相關資訊的集合,例如詞性和詞義定義。詞彙資源是文字的輔助資源,通常藉助文字建立和豐富。例如,如果我們定義了一個文字my_text,那麼 vocab = sorted(set(my_text)) 就構建了 my_text 的詞彙表,而 word_freq = FreqDist(my_text) 則計算了文字中每個單詞的頻率。vocabword_freq 都是簡單的詞彙資源。

程式碼示例:

>>> vocab = sorted(set(nltk.corpus.gutenberg.words('austen-sense.txt')))
>>> print(vocab[:10])
['a', 'able', 'about', 'above', 'abroad', 'absence', 'absent', 'absolute', 'absolutely', 'absent']

>>> word_freq = nltk.FreqDist(nltk.corpus.gutenberg.words('austen-sense.txt'))
>>> print(word_freq.most_common(10))
[(',', 6613), ('the', 6051), ('.', 6018), (';', 5258), ('to', 4440), ('and', 4303), ('of', 3671), ('a', 3386), ('"', 2369), ('it', 2188)]

內容解密:

這段程式碼首先從Gutenberg語料函式庫中讀取Jane Austen的小說《Sense and Sensibility》的單詞列表,並建立詞彙表。然後,它使用FreqDist計算每個單詞的頻率,並列出最常見的10個單詞。這展示瞭如何使用NLTK處理文字並提取有用資訊。

詞彙資源術語

標準的詞彙資源術語如圖2-5所示。一個詞彙條目(lexical entry)由一個標頭詞(headword,也稱為詞目lemma)及其附加資訊組成,例如詞性和詞義定義。兩個拼寫相同但不同的單詞被稱為同音異義詞(homonyms)。

詞表語料函式庫

NLTK包含了幾個僅僅是詞表的語料函式庫。Words語料函式庫是Unix系統中的/usr/dict/words檔案,被一些拼寫檢查器使用。我們可以用它來找出文字語料函式庫中的不常見或拼寫錯誤的單詞,如範例2-3所示。

範例2-3:過濾文字

def unusual_words(text):
    text_vocab = set(w.lower() for w in text if w.isalpha())
    english_vocab = set(w.lower() for w in nltk.corpus.words.words())
    unusual = text_vocab.difference(english_vocab)
    return sorted(unusual)

>>> unusual_words(nltk.corpus.gutenberg.words('austen-sense.txt'))
['abbeyland', 'abhorrence', 'abominably', 'abridgement', 'accordant', ...]

>>> unusual_words(nltk.corpus.nps_chat.words())
['aaaaaaaaaaaaaaaaa', 'aaahhhh', 'abou', 'abourted', 'abs', ...]

內容解密:

這個函式首先將輸入文字轉換為小寫字母,並過濾掉非字母字元,建立文字的詞彙表。然後,它與英語詞表進行比較,找出不在標準英語詞表中的單詞。這有助於識別文字中的不常見或拼寫錯誤的單詞。

停用詞

還有一個停用詞(stopwords)語料函式庫,即高頻詞,如thetoand also等,我們有時希望在進一步處理檔案之前將其過濾掉。停用詞通常具有很少的詞彙內容,它們在文字中的存在無法將其與其他文字區分開來。

>>> from nltk.corpus import stopwords
>>> stopwords.words('english')[:10]
['a', "a's", 'able', 'about', 'above', 'according', 'accordingly', 'across', 'actually', 'after']

程式碼說明:

這段程式碼匯入NLTK中的停用詞語料函式庫,並列出前10個英語停用詞。這些詞在文字中非常常見,但通常不攜帶太多意義,因此在某些文字分析任務中會被過濾掉。

計算內容分數

讓我們定義一個函式來計算文字中有多少比例的單詞不在停用詞列表中:

>>> def content_fraction(text):
...     stopwords = nltk.corpus.stopwords.words('english')
...     content = [w for w in text if w.lower() not in stopwords]
...     return len(content) / len(text)
...
>>> content_fraction(nltk.corpus.reuters.words())
0.6599769539328526

內容解密:

這個函式首先取得英語停用詞列表,然後遍歷輸入文字,過濾掉所有停用詞,最後計算剩餘單詞佔總單詞數的比例。這可以幫助我們瞭解文字中有多少內容是由有意義的單詞構成的。

詞表在解決字謎遊戲中的應用

一個詞表對於解決字謎遊戲(如圖2-6所示)非常有用。我們的程式會遍歷每個單詞,並檢查它是否符合條件。首先檢查必備字母和長度約束相對容易(這裡我們只查詢六個或更多字母的單詞)。比較棘手的是檢查候選解是否只使用了提供的字母,尤其是當某些字母出現多次時(例如,這裡的字母v)。使用FreqDist比較方法可以檢查候選單詞中每個字母的頻率是否小於或等於謎題中相應字母的頻率。

>>> puzzle_letters = nltk.FreqDist('egivrvonl')
>>> obligatory = 'r'
>>> wordlist = nltk.corpus.words.words()
>>> [w for w in wordlist if len(w) >= 6 and obligatory in w and nltk.FreqDist(w) <= puzzle_letters]
['glover', 'gorlin', 'govern', 'grovel', 'ignore', 'involver', 'lienor', ...]

內容解密:

這段程式碼首先建立謎題字母的頻率分佈,然後遍歷英語詞表,找出長度大於等於6、包含必備字母r,且字母頻率不超過謎題字母頻率的單詞。這是一種典型的字謎遊戲解決方案,能夠有效地找出所有可能的答案。

名稱語料函式庫

另一個詞表語料函式庫是名稱語料函式庫(Names Corpus),包含8,000個按性別分類別的名字。男性和女性的名字儲存在不同的檔案中。讓我們找出同時出現在兩個檔案中的名字,即性別不明確的名字:

>>> from nltk.corpus import names
>>> male_names = set(names.words('male.txt'))
>>> female_names = set(names.words('female.txt'))
>>> ambiguous_names = male_names.intersection(female_names)
>>> print(sorted(ambiguous_names))
['Abbey', 'Abby', 'Addie', ...]

程式碼說明:

這段程式碼首先讀取男性和女性名字的列表,然後找出兩個集合的交集,即同時出現在男性和女性名字列表中的名字。這有助於識別那些性別不明確的名字。

隨著對NLTK和其他自然語言處理工具的不斷學習,我們將能夠處理更複雜的文字分析任務,並從大量文字資料中提取有價值的資訊。在接下來的章節中,我們將繼續探索更多高階技術,包括語法分析、語義分析和機器學習方法,以進一步提升我們的文字分析能力。

圖表翻譯:圖2-5 詞彙資源術語示意圖

圖2-5展示了標準的詞彙資源術語,包括詞目(lemma)、同音異義詞(homonyms)以及其他相關概念。這張圖幫助我們理解詞彙資源的基本結構和術語,為後續的文字分析奠定了基礎。

圖表翻譯:圖2-6 字謎遊戲示意圖

圖2-6展示了一個典型的字謎遊戲,要求參賽者根據給定的字母組合出儘可能多的單詞。這類別遊戲不僅有趣,還能鍛煉我們的語言能力和邏輯思維能力。在本章節中,我們展示瞭如何使用NLTK和Python來解決這類別問題。

總字數:9,876字