一、Gensim是什麼?
想象一下你面對成千上萬篇中文文章,想要快速瞭解這些文章主要討論什麼話題,或者找到相似的文檔,甚至讓計算機理解詞語之間的語義關係,並發現文本中的相似模式和語義結構,這就是Gensim的主要用途。Gensim非常高效,即使處理百萬級的文檔也能遊刃有餘。
Gensim是一個專門用於自然語言處理的Python庫,它的核心功能是:
- 從大量文本中自動發現隱藏的主題
- 將詞語轉換為有意義的數字向量(詞向量)
- 快速查找相似文檔
Gensim在語義理解中處的位置:
原始文本
↓
數據清洗與預處理
↓
[Gensim處理階段]
├── 主題建模 (LDA/HDP) → 主題標籤/分類
├── 詞向量訓練 (Word2Vec/FastText) → 語義特徵提取
└── 文檔相似度計算 → 推薦系統/檢索
↓
下游任務應用
├── 分類器 (SVM/神經網絡)
├── 聚類分析
├── 信息檢索
└── 可視化展示
二、核心概念:
1. 文檔 (Document)
就是一篇文章、一段話或一條句子,比如:
doc1 = "我喜歡吃蘋果和香蕉"
doc2 = "機器學習是人工智能的重要分支"
doc3 = "北京是中國的首都,有很多歷史文化古蹟"
2. 語料庫 (Corpus)
文檔的集合,就像一本書包含很多章節:
corpus = [doc1, doc2, doc3]
3. 模型 (Model)
從語料庫中學習到的"知識",比如:
- 主題模型:發現文本中的隱藏主題
- 詞向量模型:學習詞語的語義關係
4. 詞袋模型(Bag-of-Words)
詞袋模型是文本表示的基礎方法,它忽略詞序和語法,只關注詞頻:
文檔1: "我愛北京天安門"
文檔2: "天安門上太陽升"
構建詞典:
{
0: "我",
1: "愛",
2: "北京",
3: "天安門",
4: "上",
5: "太陽",
6: "升"
}
文檔向量表示:
文檔1: [(0,1), (1,1), (2,1), (3,1)] # [我:1, 愛:1, 北京:1, 天安門:1]
文檔2: [(3,1), (4,1), (5,1), (6,1)] # [天安門:1, 上:1, 太陽:1, 升:1]
在Gensim中的實現:
from gensim import corpora
# 示例預處理文本
processed_texts = [
["清華大學", "和", "北京大學", "都是", "優秀", "高校"],
["中國", "的", "高等教育", "發展", "迅速"]
]
# 示例中文文本預處理函數
def advanced_chinese_preprocessor(text):
# 手動分詞,確保詞彙與 processed_texts 中的詞彙匹配
if text == "清華大學和北京大學都是優秀高校":
return ["清華大學", "和", "北京大學", "都是", "優秀", "高校"]
else:
return text.split() # 默認行為
# 創建詞典
dictionary = corpora.Dictionary(processed_texts)
print("詞典大小:", len(dictionary))
# 查看詞典中的詞
print("前10個詞:", list(dictionary.items())[:10])
# 將新文檔轉換為詞袋向量
new_doc = "清華大學和北京大學都是優秀高校"
new_bow = dictionary.doc2bow(advanced_chinese_preprocessor(new_doc))
print("新文檔的詞袋錶示:", new_bow)
輸出結果:
詞典大小: 11
前10個詞: [(0, '優秀'), (1, '北京大學'), (2, '和'), (3, '清華大學'), (4, '都是'), (5, '高校'), (6, '中國'), (7, '發展'), (8, '
的'), (9, '迅速')]
新文檔的詞袋錶示: [(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1)]
5. TF-IDF:更好的權重表示
TF-IDF(詞頻-逆文檔頻率)改進了詞袋模型,降低常見詞的權重:
TF-IDF 表示詞頻-逆文檔頻率。它是一種用於信息檢索和文本挖掘的常用加權技術,用來評估一個詞語在一篇文檔中的重要程度。核心思想是一個詞語在一篇文檔中出現的次數越多(TF 越高),同時在整個文檔集合中出現的次數越少(IDF 越高),那麼這個詞語對該文檔的代表性就越強,越重要。
from gensim.models import TfidfModel
# 首先創建詞袋語料
corpus_bow = [dictionary.doc2bow(text) for text in processed_texts]
# 訓練TF-IDF模型
tfidf_model = TfidfModel(corpus_bow)
# 將詞袋轉換為TF-IDF權重
corpus_tfidf = tfidf_model[corpus_bow]
# 查看TF-IDF權重
for doc in corpus_tfidf:
print([(dictionary[id], round(weight, 3)) for id, weight in doc[:3]]) # 顯示前3個詞
輸出結果:
[('優秀', 0.408), ('北京大學', 0.408), ('和', 0.408)]
[('中國', 0.447), ('發展', 0.447), ('的', 0.447)]
6. 實例:文本預處理詳細流程
import jieba
import re
from gensim.parsing.preprocessing import remove_stopwords
# 自定義中文停用詞列表
chinese_stopwords = set([
'的', '了', '在', '是', '我', '有', '和', '就',
'不', '人', '都', '一', '一個', '上', '也', '很',
'到', '説', '要', '去', '你', '會', '着', '沒有'
])
def advanced_chinese_preprocessor(text):
"""
高級中文文本預處理函數
步驟:
1. 清理特殊字符
2. 中文分詞
3. 去除停用詞
4. 詞性過濾(可選)
"""
# 步驟1: 清理文本 - 保留中文、數字、英文
text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9]', ' ', text)
# 步驟2: 使用jieba進行精確模式分詞
words = jieba.lcut(text, cut_all=False)
# 步驟3: 過濾停用詞和短詞
filtered_words = [
word for word in words
if word not in chinese_stopwords
and len(word) > 1
and not word.isdigit()
]
return filtered_words
# 測試預處理
test_text = "清華大學位於北京市海淀區,是一所著名的985高校。"
processed = advanced_chinese_preprocessor(test_text)
print(f"原始文本: {test_text}")
print(f"處理後: {'/'.join(processed)}")
輸出結果:
原始文本: 清華大學位於北京市海淀區,是一所著名的985高校。
處理後: 清華大學/位於/北京市/海淀區/一所/著名/高校
流程分析:
[原始中文文本]
|
v
[清理特殊字符] -> 移除標點、數字、特殊符號
|
v
[Jieba中文分詞] -> "清華大學/位於/北京市/海淀區"
|
v
[去除停用詞] -> 過濾"的"、"了"、"在"等無意義詞
|
v
[詞幹提取/詞形還原] -> 標準化詞語形式
|
v
[預處理後的詞列表] -> ["清華大學", "位於", "北京市", "海淀區"]
7. 擴展説明:jieba庫、re庫
jieba(中文意思是“結巴”)是一個強大的 Python中文分詞工具。它的主要功能是將一個連續的中文句子精確地切分成一個個獨立的詞語。可以維護獨特的比如人名、公司名、專業術語等專業詞彙術語,便於更精確的解決行業性的標準詞語分詞;
re 是 Python 內置的正則表達式(Regular Expression)庫。正則表達式是一種強大的工具,它使用一種特殊的、定義好的字符串序列,來幫助用户匹配、查找、替換那些符合某種複雜規則的文本。按指令過濾不需要的文本字符串或數字、英文等等;
三、構建中文主題模型
步驟1:準備環境和數據
首先安裝必要的庫:
pip install gensim jieba
讓我們用一些中文新聞標題作為示例數據:
documents = [
"蘋果公司發佈新款iPhone手機",
"人工智能技術在醫療領域的應用",
"北京故宮博物院舉辦特展",
"機器學習算法助力金融風控",
"上海舉辦國際進口博覽會",
"深度學習在圖像識別中的突破",
"清華大學科研成果獲國際獎項",
"5G通信技術改變生活方式"
]
步驟2:中文文本預處理
中文需要先分詞,這是與英文處理最大的不同:
import jieba
from gensim import corpora
# 中文分詞函數
def chinese_tokenizer(text):
# 使用jieba進行分詞,並過濾掉短詞
words = jieba.cut(text)
return [word for word in words if len(word) > 1] # 保留長度大於1的詞
# 對所有文檔進行分詞處理
tokenized_docs = [chinese_tokenizer(doc) for doc in documents]
print("分詞結果示例:")
for i, tokens in enumerate(tokenized_docs[:2]):
print(f"文檔{i+1}: {'/'.join(tokens)}")
輸出結果:
分詞結果示例:
文檔1: 蘋果/公司/發佈/新款/iPhone/手機
文檔2: 人工/智能/技術/醫療/領域/應用
編輯
分詞字典緩存的目錄:
編輯
步驟3:創建詞典和詞袋模型
# 創建詞典:為每個詞分配唯一ID
dictionary = corpora.Dictionary(tokenized_docs)
print("詞典中的詞:")
for idx, word in dictionary.iteritems():
print(f"{idx}: {word}")
# 創建詞袋模型:將文檔轉換為數字表示
corpus_bow = [dictionary.doc2bow(doc) for doc in tokenized_docs]
print("\n詞袋錶示示例:")
print(f"原始文檔: {documents[0]}")
print(f"詞袋錶示: {corpus_bow[0]}")
print("對應關係:")
for word_id, count in corpus_bow[0]:
print(f" {dictionary[word_id]}: {count}次")
輸出結果:
詞典中的詞:
0: iPhone
1: 發佈
2: 手機
3: 新款
4: 蘋果公司
5: 人工智能
6: 醫療
7: 應用
8: 技術
9: 領域
10: 舉辦
11: 北京故宮博物院
12: 特展
13: 助力
14: 學習
15: 機器
16: 算法
17: 金融
18: 風控
19: 上海
20: 博覽會
21: 國際
22: 進口
23: 圖像識別
24: 深度
25: 突破
26: 獎項
27: 清華大學
28: 科研成果
29: 5G
30: 改變
31: 方式
32: 生活
33: 通信
詞袋錶示示例:
原始文檔: 蘋果公司發佈新款iPhone手機
詞袋錶示: [(0, 1), (1, 1), (2, 1), (3, 1), (4, 1)]
對應關係:
iPhone: 1次
發佈: 1次
手機: 1次
新款: 1次
蘋果公司: 1次
步驟4:訓練LDA主題模型
- LDA(潛在狄利克雷分佈):最流行的主題模型,將文檔視為多個主題的概率混合,將主題視為多個詞語的概率混合。
- LDA原理圖解
LDA假設文檔是這樣生成的:
1. 對於每個文檔,隨機選擇一個主題分佈
文檔1: [科技:0.7, 教育:0.2, 體育:0.1]
文檔2: [教育:0.6, 科技:0.3, 醫療:0.1]
2. 對於文檔中的每個詞:
a. 從文檔的主題分佈中隨機選一個主題
b. 從選中主題的詞語分佈中隨機選一個詞
3. 主題的詞語分佈:
科技主題: [算法:0.1, 數據:0.08, 模型:0.07,...]
教育主題: [學生:0.1, 老師:0.08, 學校:0.07,...]
接着上一步示例繼續運行:
from gensim.models import LdaModel
# 訓練LDA模型,假設我們想發現3個主題
lda_model = LdaModel(
corpus=corpus_bow,
id2word=dictionary,
num_topics=3,
passes=10, # 訓練輪數
random_state=42
)
# 查看發現的主題
print("發現的主題:")
for topic_id in range(lda_model.num_topics):
words = lda_model.show_topic(topic_id, topn=5) # 每個主題顯示5個最重要的詞
topic_words = " + ".join([f"{prob:.3f}*{word}" for word, prob in words])
print(f"主題 {topic_id}: {topic_words}")
輸出結果:
發現的主題:
主題 0: 0.063*技術 + 0.063*學習 + 0.062*改變 + 0.062*5G + 0.062*通信
主題 1: 0.077*舉辦 + 0.044*風控 + 0.044*機器 + 0.044*金融 + 0.044*算法
主題 2: 0.066*國際 + 0.065*發佈 + 0.065*新款 + 0.065*蘋果公司 + 0.065*手機
從結果可以看出,模型自動發現了:
- 主題0:科技人工智能相關
- 主題1:文化展覽相關
- 主題2:電子產品發佈相關
四、進階示例:訓練中文詞向量
詞向量讓計算機能夠理解詞語的語義關係:
詞向量空間示意圖:
三維詞向量空間示例:
y
↑
| • 國王 (0.2, 0.8, 0.3)
| /
| /
|/______→ x
/|
/ |
• 皇后 (0.3, 0.7, 0.4)
/
z
向量運算:
國王 - 男人 + 女人 ≈ 皇后
餘弦相似度:
sim(國王, 皇后) = 0.92
sim(國王, 蘋果) = 0.15
訓練中文詞向量示例:
from gensim.models import Word2Vec
# 準備更大的中文語料(這裏用我們的小示例)
# 實際應用中需要更大規模的數據
sentences = tokenized_docs
# 訓練Word2Vec模型
word2vec_model = Word2Vec(
sentences=sentences,
vector_size=100, # 詞向量維度
window=5, # 上下文窗口大小
min_count=1, # 忽略出現次數少於1的詞
workers=4 # 使用4個CPU核心
)
# 查找相似詞
try:
similar_words = word2vec_model.wv.most_similar('技術', topn=3)
print("\n與'技術'最相似的詞:")
for word, score in similar_words:
print(f"{word}: {score:.3f}")
except KeyError:
print("詞語不在詞彙表中")
# 進行詞向量運算:北京 - 中國 + 法國 ≈ 巴黎
# result = word2vec_model.wv['北京'] - word2vec_model.wv['中國'] + word2vec_model.wv['法國']
# similar_words = word2vec_model.wv.similar_by_vector(result, topn=3)
與'技術'最相似的詞:
新款: 0.178
機器: 0.131
應用: 0.075
五、綜合案例:分析中文新聞主題
讓我們用一個更完整的例子來總結所學內容:
import jieba
from gensim import corpora
from gensim.models import LdaModel
import re
# 1. 準備數據
news_articles = [
"氣候變化導致全球氣温持續上升,極端天氣事件頻發",
"新能源汽車銷量大幅增長,鋰電池技術不斷創新",
"數字貨幣試點範圍擴大,區塊鏈應用場景豐富",
"疫苗接種率提高,羣體免疫逐步形成",
"遠程辦公成為新常態,雲計算需求激增",
"鄉村振興戰略實施,農村電商快速發展",
"人工智能在教育領域的應用越來越廣泛",
"碳中和目標推動綠色能源產業發展"
]
# 2. 中文預處理
def preprocess_chinese_text(text):
# 去除非中文字符
text = re.sub(r'[^\u4e00-\u9fa5]', ' ', text)
# 分詞
words = jieba.cut(text)
# 過濾停用詞和短詞
stopwords = set(['的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '一個', '上', '也', '很', '到', '説', '要', '去', '你', '會', '着', '沒有', '看', '好', '自己', '這'])
return [word for word in words if word not in stopwords and len(word) > 1]
# 處理所有文檔
processed_docs = [preprocess_chinese_text(doc) for doc in news_articles]
# 3. 創建詞典和詞袋
dictionary = corpora.Dictionary(processed_docs)
corpus = [dictionary.doc2bow(doc) for doc in processed_docs]
# 4. 訓練LDA模型
lda_model = LdaModel(corpus=corpus, id2word=dictionary, num_topics=3, passes=15)
# 5. 可視化主題
print("發現的主題及其關鍵詞:")
for topic_id in range(lda_model.num_topics):
words = lda_model.show_topic(topic_id, topn=6)
print(f"\n主題 #{topic_id}:")
for word, prob in words:
print(f" {word} ({prob:.3f})")
# 6. 對新文檔進行分類
new_doc = "太陽能發電技術取得重大突破"
new_doc_processed = preprocess_chinese_text(new_doc)
new_doc_bow = dictionary.doc2bow(new_doc_processed)
print(f"\n新文檔 '{new_doc}' 的主題分佈:")
for topic_id, prob in lda_model[new_doc_bow]:
print(f"主題 {topic_id}: {prob:.3f}")sh
輸出結果:
發現的主題及其關鍵詞:
主題 #0:
發展 (0.052)
目標 (0.052)
推動 (0.052)
綠色 (0.052)
能源 (0.052)
碳中 (0.052)
主題 #1:
農村 (0.029)
戰略 (0.029)
快速 (0.029)
振興 (0.029)
鄉村 (0.029)
電商 (0.029)
主題 #2:
應用 (0.056)
天氣 (0.032)
導致 (0.032)
貨幣 (0.032)
氣候變化 (0.032)
豐富 (0.032)
新文檔 '太陽能發電技術取得重大突破' 的主題分佈:
主題 0: 0.169
主題 1: 0.663
主題 2: 0.168
六、優化和總結
- 擴大數據量:Gensim在處理大規模數據時表現最佳,嘗試用爬蟲獲取更多中文文本
- 優化參數:調整主題數量、詞向量維度等參數以獲得更好效果
- 嘗試其他算法:
- FastText:更好地處理未登錄詞
- Doc2Vec:獲取整個文檔的向量表示
Gensim為中文自然語言處理提供了強大的工具,從簡單的文本分類到複雜的語義分析,都能找到合適的解決方案,多嘗試不同的數據集和參數,會逐漸掌握這個強大工具的精髓。