基于github項目:https://github.com/shibing624/nlp-tutorial/tree/main
自然語言處理任務
1) 簡單任務
-
拼寫檢查 Spell Checking
-
關鍵詞檢索 Keyword Search
-
同義詞查找 Finding Synonyms
-
解析來自網站、文檔等的信息
-
機器翻譯 Machine Translation
-
語義分析 Semantic Analysis
-
指代消解 Coreference
-
問答系統 Question Answering
文本表示
傳統離散表示
在自然語言處理(Natural Language Processing,NLP)領域,文本表示是處理流程的第一步,主要是將文本轉換為計算機可以運算的數字。
文本表示方法的技術演進:
符號表示法(Symbolic)
示例:詞典編碼「自然語言處理」→ {"自":1, "然":2, "語":3, "言":4, "處":5, "理":6}
from sklearn.feature_extraction.text import CountVectorizer
corpus = ["自然語言處理 是 人工智能 的 重要 分支"]
vectorizer = CountVectorizer(token_pattern=r'\b\w+\b')
X = vectorizer.fit_transform(corpus)
print(vectorizer.get_feature_names_out()) # ['人工智能', '分支', '處理', '自然語言處理', '重要']
詞袋模型(Bag-of-Words, BoW)
原理:忽略詞序,統計每個詞在文檔中的出現次數
from sklearn.feature_extraction.text import CountVectorizer
corpus = ["I love NLP.", "NLP is amazing!"]
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(corpus)
print(X.toarray()) # 輸出:[[1 1 1 0] [0 1 0 1]]
print(vectorizer.vocabulary_) # {'love': 2, 'nlp': 1, 'is': 3, 'amazing': 0}
例子1:
句1:Jane wants to go to Shenzhen 句2:Bob wants to go to Shanghai
使用兩個例句來構造詞袋: [Jane, wants, to, go, Shenzhen, Bob, Shanghai]
兩個例句就可以用以下兩個向量表示,對應的下標與映射數組的下標相匹配,其值為該詞語出現的次數
句1:[1,1,2,1,1,0,0] 句2:[0,1,2,1,0,1,1]
TF-IDF(詞頻-逆文檔頻率)
原理:降低常見詞權重,提升重要詞權重
from sklearn.feature_extraction.text import TfidfVectorizer
corpus = ["The cat sat on the mat.", "Dog on mat."]
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(corpus)
print(X.toarray()) # 非對稱矩陣
優劣對比:
方法 | 優點 | 缺點 |
---|---|---|
BoW | 簡單高效,易于實現 | 忽略詞序、語義信息,維度災難 |
TF-IDF | 減少常見詞干擾 | 仍無法捕捉語義關系 |
?分布式表示(詞嵌入)
核心思想:用稠密向量表示詞語,捕獲語義關聯
Word2Vec
原理:通過上下文預測目標詞(Skip-Gram)或反之(CBOW)
from gensim.models import Word2Vec
sentences = [["nlp", "is", "cool"], ["deep", "learning", "too"]]
model = Word2Vec(sentences, vector_size=100, window=5, min_count=1)
print(model.wv["nlp"]) # 輸出100維向量
向量示例:"king" - "man" + "woman" ≈ "queen"
GloVe(Global Vectors)
原理:基于全局詞共現矩陣的加權最小二乘訓練
from gensim.scripts.glove2word2vec import glove2word2vec
from gensim.models import KeyedVectors
glove2word2vec("glove.txt", "word2vec_format.txt")
model = KeyedVectors.load_word2vec_format("word2vec_format.txt")
優劣對比:
方法 | 優點 | 缺點 |
---|---|---|
Word2Vec | 高效捕獲局部語義 | 未利用全局統計信息 |
GloVe | 結合全局共現統計 | 訓練速度較慢 |
?上下文感知表示
核心突破:根據上下文動態調整詞向量
ELMo(Embeddings from Language Models)
原理:雙向LSTM生成上下文相關向量
from allennlp.modules.elmo import Elmo, batch_to_ids
options_file = "https://allennlp.s3.amazonaws.com/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_options.json"
weight_file = "https://allennlp.s3.amazonaws.com/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5"
elmo = Elmo(options_file, weight_file, 1)
character_ids = batch_to_ids(["hello world"])
embeddings = elmo(character_ids)['elmo_representations'][0]
BERT(Bidirectional Encoder Representations)
原理:Transformer編碼器 + Masked LM訓練
from transformers import BertTokenizer, BertModel
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')
inputs = tokenizer("Hello NLP!", return_tensors="pt")
outputs = model(**inputs)
last_hidden_states = outputs.last_hidden_state # [1, seq_len, 768]
向量示例:
同一詞在不同上下文的BERT表示:
-
"bank" in "river bank" → [0.2, -0.7, ..., 0.4]
-
"bank" in "bank account" → [0.8, 0.1, ..., -0.3]
方法類型 | 典型代表 | 語義捕獲 | 上下文敏感 | 訓練成本 | 應用場景 |
---|---|---|---|---|---|
傳統離散表示 | BoW, TF-IDF | 弱 | ? | 極低 | 簡單文本分類 |
靜態詞嵌入 | Word2Vec | 中等(靜態) | ? | 中等 | 關鍵詞擴展、推薦 |
上下文動態嵌入 | BERT | 強 | ?? | 極高 | 語義理解、問答系統 |