iT邦幫忙

2025 iThome 鐵人賽

DAY 13
0
AI & Data

讓電腦聽懂人話:30 天 NLP 入門系列 第 13

Day 13|語境中的向量:Contextual Embedding

  • 分享至 

  • xImage
  •  

引言

昨天我們介紹 Word2Vec,學會了怎麼把文字變成 語意向量。但這只是用數字來表示語意的第一步!語意可是比你想得更複雜許多~~還記得我們在本系列的第二篇文 文字探勘(Text Mining)的挑戰 中提到,語言有 「歧義性」(ambiguity) 嗎?

簡單來說就是一段文字可以有不同意思。那麼如果一個詞在不同語境下意義不同,Word2Vec 能抓到真正的語意嗎?答案是:辦不到 ❌

原因是因為 Word2Vec 所產生的是 「靜態向量」(static embedding),無論這個詞出現在什麼句子裡,它的向量都是一樣的。
但是今天要介紹的 Contextual Embedding 是 「動態向量」(dynamic embedding),它可以隨上下文改變。這種方法讓電腦能夠捕捉語境的差異,更智慧地理解語意,也讓文字向量真正活起來!


圖片來源:https://manikanthgoud123.medium.com/understanding-contextualized-word-embeddings-the-evolution-of-language-understanding-in-ai-8bf79a98eb51

今天的內容我們先不談太深奧的模型架構(之後的文章才會提到),先來輕鬆的了解這個概念,還有用簡單的程式實作來看看同一個詞在不同句子裡長得不一樣的模樣吧~

Contextual Embedding

首先,我們來看兩個句子:

  • 我在超市買了蘋果
  • 蘋果推出了新手機

身為人類,我們應該可以輕鬆地靠上下文判斷「蘋果」在這兩句話的差異吧~

  • 我在超市買了蘋果 → 一種水果
  • 蘋果推出了新手機 → 一間公司

Contextual Embedding 就是要解決「多義詞」的問題。它會根據句子的上下文,為同一個詞生成不同的向量。

目前常用的做法,是利用大型預訓練模型(例如 BERT)來生成這種向量。這些模型會觀察整句話,去注意哪些詞是比較重要的,然後再動態調整每個詞的向量。所以整個生成 contextual embedding 的過程大概會經歷下面幾個步驟:

  1. 每個詞先轉成向量:像 Word2Vec 一樣,讓每個詞先有初步的 embedding。
  2. 計算注意力權重:模型會比較句子中每個詞對其他詞的重要性,去計算權重。

    例如:「蘋果」在「我買了蘋果」這句話中可能更重視「買了」這個詞;在「蘋果推出新產品」這句話中可能更重視「產品」這個詞。

  3. 加權求和,生成新向量:透過自己的原向量與其他詞向量的加權組合,來產生每個詞的新向量。這個向量就同時包含了自己本身的意思和上下文的訊息。

然後模型會透過多層的計算,讓向量能捕捉更精準、深層的語意關係。

程式實作

實作的部分,我們使用中文的 BERT 模型bert-base-chinese,並且選了幾個包含「蘋果」的句子。但是「蘋果」在這幾個句子的意思都不同,我們就透過模型來轉成 contextual embedding,然後在可視化空間中看他們的分布跟距離~

  1. 安裝必要套件,使用 BERT 中文模型
from transformers import AutoTokenizer, AutoModel
import torch
from sklearn.decomposition import PCA
import plotly.express as px

# 選用 BERT 中文模型
tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese")
model = AutoModel.from_pretrained("bert-base-chinese")

# 測試句子
docs = [
    "我去買蘋果",       # 水果
    "我喜歡吃蘋果",     # 水果
    "蘋果推出了新產品",  # 公司
    "蘋果的手機很好用",  # 公司
    "我買了蘋果日報"     # 報紙
]
  1. 斷詞並找出 target word 的 embedding

BERT 中文斷詞通常會是一個字一個 token,如果 target_word 多個字,要取 embedding 有幾種常見方法:

  • 取平均(mean pooling):把「蘋」和「果」兩個向量做平均
  • 取加總(max pooling):把「蘋」和「果」兩個向量相加

在這裡我們使用 mean pooling

target_word = "蘋果"
vectors = []   # 存 target_word 的向量
contexts = []  # 存含有 target_word 句子

for sent in docs:
    # 斷詞/編碼
    inputs = tokenizer(sent, return_tensors="pt")
    outputs = model(**inputs)
    embeddings = outputs.last_hidden_state  # shape: (batch_size, seq_len, hidden_size)
    
    # 查看斷詞結果
    tokens = tokenizer.tokenize(sent)
    print(sent, "→", tokens)
    
    # 找出 target_word 的位置範圍
    target_tokens = tokenizer.tokenize(target_word)
    target_len = len(target_tokens)

    for idx in range(len(tokens) - target_len + 1):
        if tokens[idx: idx + target_len] == target_tokens:
            # 把 subword 的向量取平均
            word_vector = embeddings[0, idx: idx + target_len, :].mean(dim=0).detach().numpy()
            vectors.append(word_vector)
            contexts.append(sent)
            break
# 查看結果
print(f"\ntarget word 向量維度:{len(vectors[0])}")           
# === Output ===
我去買蘋果 → ['我', '去', '買', '蘋', '果']
我喜歡吃蘋果 → ['我', '喜', '歡', '吃', '蘋', '果']
蘋果推出了新產品 → ['蘋', '果', '推', '出', '了', '新', '產', '品']
蘋果的手機很好用 → ['蘋', '果', '的', '手', '機', '很', '好', '用']
我買了蘋果日報 → ['我', '買', '了', '蘋', '果', '日', '報']

target word 向量維度:768
  1. 降維至 2D,並用 Plotly 做圖
# 降維
pca = PCA(n_components=2)
vectors_2d = pca.fit_transform(vectors)

# 建立 DataFrame
import pandas as pd
df = pd.DataFrame({
    "x": vectors_2d[:,0],
    "y": vectors_2d[:,1],
    "sentence": contexts
})
print(df)

# 用 Plotly 畫散點圖
fig = px.scatter(df, x="x", y="y", text="sentence", title=f"Contextual Embedding of '{target_word}'")
fig.update_traces(textposition='top center')
fig.show()
# === Output ===
           x         y     sentence
0   5.907347 -4.127521     我去買蘋果
1   7.210994 -5.499431    我喜歡吃蘋果
2 -11.100585  0.684716  蘋果推出了新產品
3 -10.296168  0.128546  蘋果的手機很好用
4   8.278411  8.813690   我買了蘋果日報

https://ithelp.ithome.com.tw/upload/images/20250925/20178719QDcDAyjsjD.png
我們可以看到「蘋果」在不同的語境底下,會有不同的 embedding,並且可以看到意思相近的,向量真的有比較靠近!很神奇吧~~

結語

今天介紹的 Contextual Embedding 看到了一個很重要的突破,是讓電腦可以更貼近人類理解語言的方式,捕捉到語意會隨著上下文而變化的特性。那這系列的 主題三:特徵與表示 就在這裡畫下句點,明天開始會進入 主題四:模型與方法 啦~~

你可能會好奇,這些 embedding 背後到底是怎麼算出來的?有了這些文字特徵,接下來要如何做運算?
其實這就涉及到各種不同的模型方法,從比較傳統的 機器學習(Machine Learning),再到 神經網路架構(Neural Network),一路到 深度學習(Deep Learning),再到現在更強大的大型語言模型(Large Language Model)。接下來的幾天,我們就會慢慢介紹這些演算法,一步步揭開這些模型背後的祕密!

References


上一篇
Day 12|語意向量:Word2Vec
系列文
讓電腦聽懂人話:30 天 NLP 入門13
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言