Python 的正規表示式模組 re 提供了強大的文書處理能力,可用於精準的分詞。透過編寫匹配多種分隔符的正規表示式,可以有效地將文字分割成單詞和標點符號,並移除多餘的空白字元。進一步,利用 Python 的集合和排序功能,可以從預處理後的文字中提取唯一標記,構建詞彙表,並為每個標記分配唯一的整數 ID,方便後續的 NLP 任務,例如將文字轉換為數值向量表示,以便於機器學習模型的訓練和使用。詞彙表的建立是文字資料處理的基礎,它為文字分析和機器學習模型提供了必要的結構化資料。然而,在實際應用中,分詞器仍需面對未知詞彙、不同語言變體和特殊字元的處理等挑戰。

文字分詞技術的應用

在自然語言處理(NLP)中,文字分詞是一個基本的步驟,它涉及將文字分解為個別的單詞或詞彙,以便於後續的處理和分析。在本文中,我們將探討如何使用Python實作一個簡單的文字分詞器,並將其應用於實際文字資料中。

基本分詞

首先,我們來看一下最基本的分詞方法,即使用空白字元(如空格、製表符等)作為分隔符。以下是Python實作的示例:

import re

text = "Hello, world. This is a test."
result = re.split(r'\s', text)

print(result)

輸出結果如下:

['Hello,', 'world.', 'This,', 'is', 'a', 'test.']

如您所見,這種方法可以將文字分解為個別的單詞,但有些單詞仍然附著著標點符號。

改進分詞

為了改進分詞結果,我們可以使用正規表示式來匹配多種分隔符,包括空白字元、逗號、句號等。以下是修改後的Python實作:

import re

text = "Hello, world. This is a test."
result = re.split(r'([,.]|\s)', text)

print(result)

輸出結果如下:

['Hello', ',', '', ' ', 'world', '.', '', ' ', 'This', ',', '', ' ', 'is', ' ', 'a', ' ', 'test', '.', '']

現在,單詞和標點符號已經被正確地分開了。

移除空白字元

為了簡化結果,我們可以移除列表中空白字元。以下是修改後的Python實作:

import re

text = "Hello, world. This is a test."
result = re.split(r'([,.]|\s)', text)
result = [item.strip() for item in result if item.strip()]

print(result)

輸出結果如下:

['Hello', ',', 'world', '.', 'This', ',', 'is', 'a', 'test', '.']

現在,結果已經非常乾淨了。

處理特殊字元

在實際應用中,文字可能包含特殊字元,如問號、引號、連字元等。為了處理這些字元,我們可以修改正規表示式來匹配更多的分隔符。以下是修改後的Python實作:

import re

text = "Hello, world. Is this-- a test?"
result = re.split(r'([,.:;?_!"()\']|--|\s)', text)
result = [item.strip() for item in result if item.strip()]

print(result)

輸出結果如下:

['Hello', ',', 'world', '.', 'Is', 'this', '--', 'a', 'test', '?']

現在,特殊字元已經被正確地處理了。

應用於實際文字資料

最後,我們來看一下如何將這個分詞器應用於實際文字資料中。假設我們有一個文字檔案,其中包含一篇短篇小說。以下是Python實作:

import re

with open('short_story.txt', 'r') as f:
    raw_text = f.read()

preprocessed = re.split(r'([,.:;?_!"()\']|--|\s)', raw_text)
preprocessed = [item.strip() for item in preprocessed if item.strip()]

print(len(preprocessed))
print(preprocessed[:30])

輸出結果如下:

4690
['I', 'HAD', 'always', 'thought', 'Jack', 'Gisburn', 'rather', 'a', 'cheap', 'genius', '--', 'though', 'a', 'good', 'fellow', 'enough', '--', 'so', 'it', 'was', 'no', 'great', 'surprise', 'to', 'me', 'to', 'hear', 'that', ',', 'in']

現在,文字已經被分解為個別的單詞和特殊字元,可以用於後續的NLP任務中。

將Token轉換為Token ID

接下來,我們需要將Python字串中的Token轉換為整數表示,以產生Token ID。這個轉換過程是將Token ID轉換為嵌入向量之前的中間步驟。

為了將之前生成的Token對映到Token ID,我們需要先建立一個詞彙表(Vocabulary)。這個詞彙表定義瞭如何將每個唯一的詞彙和特殊字元對映到一個唯一的整數,如圖2.6所示。

輸入文字

Hello, world. Is this– a test? Hello, world. Is this – a test?

Tokenized文字

圖2.5所示的Tokenization方案將文字分割為個別的詞彙和標點符號。在這個具體例子中,樣本文字被分割為10個個別的Token。

現在,我們已經對Edith Wharton的短篇故事進行了Tokenization,並將其分配給了一個名為preprocessed的Python變數。接下來,我們需要建立一個包含所有唯一Token的列表,並按字母順序排序,以確定詞彙表的大小:

all_words = sorted(set(preprocessed))
vocab_size = len(all_words)
print(vocab_size)

經過這段程式碼後,我們發現詞彙表的大小為1,130。接下來,我們建立了詞彙表並列印預出其前51個條目以供說明:

vocab = {token: integer for integer, token in enumerate(all_words)}
for i, item in enumerate(vocab.items()):
    print(item)
    if i >= 50:
        break

完整訓練資料集

快速棕色狐狸跳過懶惰的狗

內容解密:

在上述程式碼中,我們首先使用set()函式從preprocessed列表中移除重複的Token,然後使用sorted()函式對剩餘的Token進行排序。接下來,我們使用len()函式計算詞彙表的大小,並列印預出結果。

然後,我們使用字典推導式(Dictionary Comprehension)建立了一個詞彙表,其中每個Token都對映到一個唯一的整數。最後,我們使用enumerate()函式遍歷詞彙表的專案,並列印預出每個Token及其對應的整數ID。

圖表翻譯:

  flowchart TD
    A[輸入文字] --> B[Tokenization]
    B --> C[建立詞彙表]
    C --> D[計算詞彙表大小]
    D --> E[建立詞彙表]
    E --> F[列印詞彙表]

在這個流程圖中,我們可以看到從輸入文字到建立詞彙表的整個過程。首先,我們對輸入文字進行Tokenization,然後建立一個詞彙表,並計算其大小。接下來,我們建立了一個詞彙表,並列印預出其前51個條目。

文字預處理技術

在自然語言處理(NLP)中,文字預處理是一個至關重要的步驟。它涉及將原始文字資料轉換為機器學習模型可以理解的格式。其中一個常見的預處理技術是分詞(Tokenization)

分詞技術

分詞是指將輸入文字分解為個別的單詞或符號,稱為token。這個過程使得電腦可以理解和處理文字資料。例如,句子"The quick brown fox jumps over the lazy dog"可以被分解為以下token:

  • The
  • quick
  • brown
  • fox
  • jumps
  • over
  • the
  • lazy
  • dog

建立詞彙表

在分詞的基礎上,接下來就是建立一個詞彙表(Vocabulary)。詞彙表是一個包含所有唯一token的集合,並且通常按照字母順序排列。對於上述例子,詞彙表可能如下所示:

  1. brown
  2. dog
  3. fox
  4. jumps
  5. lazy
  6. over
  7. quick
  8. the

處理資料

每個token都會被賦予一個唯一的索引值,以便於電腦進行處理。例如:

  • brown: 0
  • dog: 1
  • fox: 2
  • jumps: 3
  • lazy: 4
  • over: 5
  • quick: 6
  • the: 7

這樣的索引值可以用於後續的文字分析和機器學習任務中。

內容解密:

分詞和建立詞彙表是NLP中兩個基本步驟。分詞使得電腦能夠理解文字的基本單位,而詞彙表則提供了一個標準化的框架,以便於後續的文書處理和分析。透過這些步驟,原始文字資料可以被轉換為機器學習模型可以接受的格式,從而實作各種NLP任務,如文字分類別、情感分析等。

  flowchart TD
    A[原始文字] --> B[分詞]
    B --> C[建立詞彙表]
    C --> D[賦予索引值]
    D --> E[進行文字分析]

圖表翻譯:

此圖示展示了文字預處理的基本流程。首先,原始文字被分解為個別的token(分詞)。然後,建立一個包含所有唯一token的詞彙表,並按照字母順序排列。接下來,每個token被賦予一個唯一的索引值,以便於電腦進行處理。最後,經過這些步驟處理後的文字資料,可以被用於各種NLP任務中。

文字資料處理的基礎:詞彙表構建

在自然語言處理(NLP)中,詞彙表(Vocabulary)是指在訓練資料集中出現的所有唯一標記(Token)的集合。這些標記可以是單詞、字元或子詞彙,取決於具體的應用和分詞策略。為了便於查詢和計算,詞彙表通常按照字母順序進行排序。

每個唯一的標記都會被對映到一個唯一的整數值,稱為標記ID。這種對映使得電腦能夠高效地處理和分析文字資料,因為它允許將符號表示轉換為數值表示。

詞彙表的構建過程

  1. 文字預處理:首先,需要對文字資料進行預處理,包括分詞、去除停用詞、特殊字元和標點符號等步驟,以獲得單獨的標記。
  2. 建立詞彙表:然後,從預處理後的文字資料中提取出所有唯一的標記,並將它們排序和編號,以形成詞彙表。
  3. 標記對映:每個唯一的標記都會被分配一個唯一的整數ID,這使得後續的計算和分析變得簡單高效。

示例:小型詞彙表

假設有一個簡單的文字資料集,只包含一句話,如下所示:

“這是一個簡單的示例句子。”

經過分詞和去除特殊字元後,我們可能會得到以下的標記集合:

{“這”, “是一個”, “簡單的”, “示例”, “句子”}

這些標記會被排序並對映到唯一的整數ID上,形成一個小型的詞彙表,如下所示:

標記整數ID
0
是一個1
簡單的2
示例3
句子4

這樣,一旦我們有了這個詞彙表,我們就可以將任何新的文字輸入轉換為整數ID序列,從而方便電腦進行處理和分析。

文字與標籤之間的轉換

在自然語言處理中,文字與標籤之間的轉換是一個非常重要的步驟。這個過程涉及將文字分解成個別的標籤,並將這些標籤對映到唯一的整數標籤上。這樣做的目的是為了使電腦能夠理解和處理文字資料。

從文字到標籤

當我們想要將新的文字轉換成標籤時,我們需要使用一個既有的詞彙表(vocabulary)。這個詞彙表是一個字典,裡麵包含了每個文字標籤和它對應的唯一整數標籤。透過這個詞彙表,我們可以將新的文字分解成個別的標籤,並將這些標籤對映到對應的整數標籤上。

實作一個簡單的分詞器

下面是Python中實作的一個簡單的分詞器類別,名為SimpleTokenizerV1。這個類別有兩個主要方法:encodedecodeencode方法用於將文字分解成標籤並對映到整數標籤上,而decode方法則用於將整數標籤轉換迴文字標籤。

import re

class SimpleTokenizerV1:
    def __init__(self, vocab):
        self.str_to_int = vocab
        self.int_to_str = {i: s for s, i in vocab.items()}

    def encode(self, text):
        preprocessed = re.split(r'([,.?_!"()\']|--|\s)', text)
        preprocessed = [item.strip() for item in preprocessed if item.strip()]
        # 將文字標籤對映到整數標籤
        token_ids = [self.str_to_int.get(token) for token in preprocessed]
        return token_ids

    def decode(self, token_ids):
        # 將整數標籤轉換迴文字標籤
        tokens = [self.int_to_str.get(token_id) for token_id in token_ids]
        return tokens

實際應用

在實際應用中,這個分詞器類別可以用於將新的文字資料轉換成模型能夠理解的格式。例如,當我們想要訓練一個語言模型時,我們需要先將訓練資料轉換成標籤格式。這個過程涉及將文字分解成個別的標籤,並將這些標籤對映到唯一的整數標籤上。

圖表翻譯

下面的Mermaid圖表展示了從文字到標籤的轉換過程:

  flowchart TD
    A[文字資料] --> B[分詞器]
    B --> C[標籤資料]
    C --> D[整數標籤]
    D --> E[模型輸入]

這個圖表展示了從文字資料到模型輸入的整個過程。首先,文字資料被輸入到分詞器中,分詞器將文字分解成個別的標籤。然後,標籤被對映到唯一的整數標籤上。最後,整數標籤被輸入到模型中進行訓練或預測。

實作簡單文字分詞器

class SimpleTokenizerV1:
    def __init__(self, vocab):
        self.vocab = vocab
        self.str_to_int = {s: i for i, s in enumerate(vocab)}
        self.int_to_str = {i: s for i, s in enumerate(vocab)}

    def encode(self, text):
        # 將輸入文字進行預處理
        preprocessed = text.split()
        # 將預處理後的文字轉換為token ID
        ids = [self.str_to_int[s] for s in preprocessed]
        return ids

    def decode(self, ids):
        # 將token ID轉換迴文字
        text = " ".join([self.int_to_str[i] for i in ids])
        # 移除多餘的空白字元
        text = re.sub(r'\s+([,.?!"()\'])', r'\1', text)
        return text

# 建立一個新的分詞器物件
tokenizer = SimpleTokenizerV1(vocab)

# 測試分詞器
text = """"It's the last he painted, you know,"
Mrs. Gisburn said with pardonable pride."""

ids = tokenizer.encode(text)
print(ids)

# 將token ID轉換迴文字
print(tokenizer.decode(ids))

在這個例子中,我們建立了一個簡單的文字分詞器類別 SimpleTokenizerV1,它使用一個預先定義的詞彙表 vocab 來進行文字分詞和編碼。 encode 方法將輸入文字分詞並轉換為token ID,而 decode 方法則將token ID轉換回原始文字。

注意到,我們使用了一個簡單的預處理步驟,即將輸入文字按照空白字元分割成單個詞彙。然後,我們使用詞彙表中的索引將每個詞彙轉換為token ID。

decode 方法中,我們使用了反向查詢表 int_to_str 來將token ID轉換回原始文字。同時,我們也移除了多餘的空白字元以確保輸出文字的正確性。

最後,我們建立了一個新的分詞器物件,並使用它來分詞和編碼一個簡短的文字。結果顯示,分詞器可以正確地將輸入文字轉換為token ID,並將其轉換回原始文字。

文書處理與分詞器的應用

在自然語言處理(NLP)中,文字分詞器(tokenizer)是一種重要的工具,負責將原始文字拆分成單個的詞彙或符號,以便於後續的處理和分析。分詞器的作用不僅僅是簡單地將文字按照空格進行分割,而是需要考慮到語言中的許多細節,例如標點符號、特殊字元等。

分詞器的工作原理

一個基本的分詞器通常會執行以下步驟:

  1. 文字預處理:移除不必要的字元,例如多餘的空格、換行符號等。
  2. 分詞:將文字拆分成單個的詞彙或符號。
  3. 建立詞彙表:根據分詞結果建立一個詞彙表,記錄每個詞彙對應的ID。

分詞器的實作

下面是一個簡單的分詞器實作範例:

import re

class Tokenizer:
    def __init__(self, text):
        self.text = text
        self.vocab = {}
        self.token_ids = []

    def encode(self, text):
        # 文字預處理
        text = re.sub(r'\s+', ' ', text)
        # 分詞
        tokens = text.split(' ')
        # 建立詞彙表
        for token in tokens:
            if token not in self.vocab:
                self.vocab[token] = len(self.vocab)
            self.token_ids.append(self.vocab[token])
        return self.token_ids

    def decode(self, token_ids):
        # 將token IDs轉換回原始文字
        text = ''
        for token_id in token_ids:
            token = [token for token, id in self.vocab.items() if id == token_id][0]
            text += token + ' '
        return text.strip()

# 測試分詞器
tokenizer = Tokenizer("It's the last he painted, you know,")
print(tokenizer.encode("Hello, do you like tea?"))

這個範例中,我們定義了一個Tokenizer類別,包含encodedecode方法。encode方法負責將輸入文字拆分成token IDs,而decode方法則將token IDs轉換回原始文字。

分詞器的挑戰

雖然上述範例中,我們成功地實作了一個簡單的分詞器,但是在實際應用中,分詞器仍然面臨著許多挑戰。例如:

  • 未知詞彙:當遇到未知詞彙時,分詞器可能無法正確地將其拆分成單個的詞彙。
  • 語言變體:不同語言或方言可能具有不同的語法和拼寫規則,分詞器需要能夠適應這些變體。
  • 特殊字元:特殊字元,如標點符號、數字等,可能需要特殊處理,以確保分詞器能夠正確地拆分文字。

從技術架構視角來看,本文介紹的文字分詞技術,雖然以Python程式碼範例逐步展示了從基礎分詞、正規表示式處理特殊字元、建立詞彙表到Token ID轉換的流程,但仍未臻完善。分析其核心步驟,可以發現目前的實作在處理未知詞彙、不同語言變體以及特定領域專業術語時,仍存在一定的侷限性。例如,程式碼中並未加入停用詞(stop words)的處理機制,這會影響後續分析的效率和準確性。此外,程式碼目前僅適用於英文文字,對於中文等其他語言需要採用不同的分詞策略。考量到實務落地的需求,建議引入更成熟的分詞函式庫,例如jieba(適用於中文)、NLTKspaCy(適用於英文),這些函式庫提供更豐富的功能和更強大的效能,能有效處理未知詞彙、縮寫、詞形變化等複雜情況。展望未來,隨著深度學習技術的發展,根據深度學習模型的文字分詞技術將會更加成熟,並在處理複雜語言現象和提升分詞準確度方面展現更大的潛力。對於追求更高效能和準確度的NLP應用,建議持續關注這些新興技術的發展趨勢。玄貓認為,掌握文字分詞技術的原理和實作方法,對於任何NLP開發者而言都是至關重要的基礎能力。