在RNN中詞使用one_hot表示的問題
- 假設有10000個詞
- 每個詞的向量長度都為10000,整體大小太大
- 沒能表示出詞與詞之間的關系
- 例如Apple與Orange會更近一些,Man與Woman會近一些,取任意兩個向量計算內積都為0
目錄
1.詞嵌入
1.1.特點
1.3.word2vec介紹
1.3.Word2Vec案例
1.3.1.訓練語料
1.3.2.步驟
1.3.3.代碼
?2.測試代碼
1.詞嵌入
定義:指把一個維數為所有詞的數量的高維空間嵌入到一個維數低得多的連續向量空間中,每個單詞或詞組被映射為實數域上的向量。
注:這個維數通常不定,不同實現算法指定維度都不一樣,通常在30~500之間。
如下圖所示:
1.1.特點
- 能夠體現出詞與詞之間的關系
- 比如說我們用Man - Woman,或者Apple - Orange,都能得到一個向量
- 能夠得到相似詞,例如Man - Woman = King - ?
- ? = Queen
1.2.word2vec介紹
Bengio等人在一系列論文中使用了神經概率語言模型使機器“習得詞語的分布式表示。
2013年,谷歌托馬斯·米科洛維(Tomas Mikolov)領導的團隊發明了一套工具word2vec來進行詞嵌入。
Word2Vec 是一種廣泛使用的??詞嵌入(Word Embedding)??技術,由 Google 團隊(Tomas Mikolov 等)于 2013 年提出。它通過神經網絡模型將單詞映射到??低維稠密向量空間??,使得語義相似的詞在向量空間中距離相近。Word2Vec 是 NLP 領域的基礎技術之一,廣泛應用于文本分類、機器翻譯、推薦系統等任務。
Word2Vec 的核心假設是:??“具有相似上下文的單詞,其語義也相似”??。它通過訓練神經網絡,使得模型能夠從大量文本中學習單詞的分布式表示(Distributed Representation)。
1.??主要特點??
- ??稠密向量表示??:每個單詞用一個固定長度的低維向量(如 100~300 維)表示,相比傳統的 one-hot 編碼更高效。
- ??語義相似性??:語義相近的詞(如 "king" 和 "queen")在向量空間中距離較近。
- ??計算高效??:采用??負采樣(Negative Sampling)??或??層次 Softmax(Hierarchical Softmax)??優化訓練速度。
2. Word2Vec 的兩種模型??
Word2Vec 包含兩種不同的訓練方式:
??(1) CBOW(Continuous Bag of Words)??
- ??目標??:根據上下文單詞預測當前單詞。
- ??適用場景??:適合小型數據集或高頻詞。
- ??示例??:
- 輸入:
["the", "cat", "on", "the"]
(上下文窗口=4) - 輸出:預測?
"mat"
(中心詞)
- 輸入:
??(2) Skip-Gram??
- ??目標??:根據當前單詞預測上下文單詞。
- ??適用場景??:適合大型數據集或低頻詞,效果通常比 CBOW 更好。
- ??示例??:
- 輸入:
"mat"
(中心詞) - 輸出:預測?
["the", "cat", "on", "the"]
(上下文窗口=4)
- 輸入:
- skip-gram
算法學習實現:https://www.tensorflow.org/tutorials/representation/word2vec
下載gensim庫
pip install gensim
1.3.Word2Vec案例
1.3.1.訓練語料
由于語料比較大,就提供了一個下載地址:搜狗搜索引擎 - 上網從搜狗開始
- 搜狗新聞中文語料(2.7G)
- 做中文分詞處理之后的結果
1.3.2.步驟
-
1、訓練模型
-
2、測試模型結果
1.3.3.代碼
- 訓練模型API
- from gensim import Word2Vec
- Word2Vec(LineSentence(inp), size=400, window=5, min_count=5)
- LineSentence(inp):把word2vec訓練模型的磁盤存儲文件
- 轉換成所需要的格式,如:[[“sentence1”],[”sentence1”]]
- size:是每個詞的向量維度
- window:是詞向量訓練時的上下文掃描窗口大小,窗口為5就是考慮前5個詞和后5個詞
- min-count:設置最低頻率,默認是5,如果一個詞語在文檔中出現的次數小于5,那么就會丟棄
- 方法:
- inp:分詞后的文本
- save(outp1):保存模型
這里需要傳入訓練好的分詞結果:corpus_seg.txt
訓練的代碼如下
import sys
import multiprocessingfrom gensim.models import Word2Vec
from gensim.models.word2vec import LineSentenceif __name__ == '__main__':if len(sys.argv) < 3:sys.exit(1)# inp表示語料庫(分詞),outp:模型inp, outp = sys.argv[1:3]model = Word2Vec(LineSentence(inp), size=400, window=5, min_count=5, workers=multiprocessing.cpu_count())model.save(outp)
運行命令
python trainword2vec.py ./corpus_seg.txt ./model/*
指定好分詞的文件以及,保存模型的文件
- 加載模型測試代碼
- model = gensim.models.Word2Vec.load("*.model")
- model.most_similar('警察')
- model.similarity('男人','女人')
- most_similar(positive=['女人', '丈夫'], negative=['男人'], topn=1)
- model = gensim.models.Word2Vec.load("*.model")
improt gensim
gensim.models.Word2Vec.load("./model/corpus.model")model.most_similar("警察")Out:
[('警員', 0.6961891651153564),('保安人員', 0.6414757370948792),('警官', 0.6149201989173889),('消防員', 0.6082159876823425),('憲兵', 0.6013336181640625),('保安', 0.5982533693313599),('武警戰士', 0.5962344408035278),('公安人員', 0.5880240201950073),('民警', 0.5878666639328003),('刑警', 0.5800305604934692)]model.similarity('男人','女人')
Out: 0.8909852730435042model.most_similar(positive=['女人', '丈夫'], negative=['男人'], topn=1)
Out: [('妻子', 0.7788498997688293)]
?2.測試代碼
??步驟?? | ??功能描述?? | ??關鍵點/注意事項?? |
---|---|---|
??1. 導入庫?? | 加載必要的Python庫 | gensim ?用于Word2Vec,nltk ?用于分詞,os ?用于路徑操作。 |
??2. 檢查NLTK數據?? | 確保punkt 分詞數據存在,若缺失則自動下載 | - 使用try-except 避免中斷。-? quiet=True 隱藏下載日志。 |
??3. 定義示例數據?? | 提供待訓練的文本句子 | 實際應用中需替換為大規模文本(如從文件讀取)。 |
??4. 分詞處理?? | 將句子拆分為單詞列表 | - 優先用word_tokenize 處理標點。- 失敗時回退到 split() (效果較差)。 |
??5. 訓練Word2Vec?? | 根據分詞結果訓練詞向量模型 | -?vector_size=100 : 詞向量維度。-? sg=1 : 使用Skip-Gram算法(適合小數據)。 |
??6. 保存模型?? | 將模型保存到磁盤 | 后續可通過Word2Vec.load("word2vec.model") 復用模型。 |
??7. 測試模型?? | 驗證詞向量效果(查詢詞向量和相似詞) |
from gensim.models import Word2Vec
from nltk.tokenize import word_tokenize
import nltk
import os# 確保下載必要的NLTK數據
try:nltk.data.find('tokenizers/punkt')print("NLTK punkt data already downloaded")
except LookupError:print("Downloading NLTK punkt data...")nltk.download('punkt', quiet=True)# 某些環境可能需要額外下載punkt_tabtry:nltk.download('punkt_tab', quiet=True)except:print("punkt_tab not available, using only punkt")# 示例文本數據
sentences = ["I love natural language processing.","Word2Vec is a popular embedding technique.","Deep learning is changing the world."
]# 分詞(帶錯誤回退機制)
try:tokenized_sentences = [word_tokenize(sent.lower()) for sent in sentences]print("Tokenizer succeeded!")
except LookupError as e:print(f"Tokenizer failed: {e}")print("Falling back to simple whitespace tokenizer...")tokenized_sentences = [sent.lower().split() for sent in sentences]# 訓練 Word2Vec 模型
model = Word2Vec(sentences=tokenized_sentences,vector_size=100, # 向量維度window=5, # 上下文窗口大小min_count=1, # 忽略低頻詞sg=1, # 1=Skip-Gram, 0=CBOWnegative=5, # 負采樣數量epochs=10 # 訓練輪次
)# 保存模型
model.save("word2vec.model")
print("Model saved successfully!")# 測試詞向量
try:print("Example word vector for 'learning':", model.wv['learning'])print("Most similar to 'processing':", model.wv.most_similar('processing'))
except KeyError as e:print(f"Word not in vocabulary: {e}")
# 加載模型
model = Word2Vec.load("word2vec.model")# 獲取單詞向量
vector = model.wv["word2vec"] # 獲取 "word2vec" 的向量# 計算相似詞
similar_words = model.wv.most_similar("nlp", topn=3)
print(similar_words) # 輸出:[('natural', 0.92), ('language', 0.88), ('processing', 0.85)]