Python 中文分詞 jieba(小白進)
阿新 • • 發佈:2019-01-26
0、安裝
法1:Anaconda Prompt下輸入conda install jieba
法2:Terminal下輸入pip3 install jieba
1、分詞
1.1、CUT函式簡介
- cut(sentence, cut_all=False, HMM=True)
- 返回
生成器
,遍歷生成器即可獲得分詞的結果 - lcut(sentence)
- 返回
分詞列表
import jieba
sentence = '我愛自然語言處理'
# 建立【Tokenizer.cut 生成器】物件
generator = jieba.cut(sentence)
# 遍歷生成器,列印分詞結果
words = '/'.join( generator)
print(words)
- 列印結果
- 我/愛/自然語言/處理
import jieba
print(jieba.lcut('我愛南海中學'))
- 列印結果
- [‘我’, ‘愛’, ‘南海中學’]
1.2、分詞模式
精確
模式- 精確地切開
全
模式- 所有可能的詞語都切出,速度快
搜尋引擎
模式- 在精確模式的基礎上,對長詞再次切分
import jieba
sentence = '訂單資料分析'
print('精準模式:', jieba.lcut(sentence))
print('全模式:', jieba.lcut(sentence, cut_all=True))
print ('搜尋引擎模式:', jieba.lcut_for_search(sentence))
- 列印結果
- 精準模式: [‘訂單’, ‘資料分析’]
全模式: [‘訂單’, ‘訂單數’, ‘單數’, ‘資料’, ‘資料分析’, ‘分析’]
搜尋引擎模式: [‘訂單’, ‘資料’, ‘分析’, ‘資料分析’]
1.3、詞性標註
- jieba.posseg
import jieba.posseg as jp
sentence = '我愛Python資料分析'
posseg = jp.cut(sentence)
for i in posseg:
print(i.__dict__)
# print(i.word, i.flag)
- 列印結果
- {‘word’: ‘我’, ‘flag’: ‘r’}
{‘word’: ‘愛’, ‘flag’: ‘v’}
{‘word’: ‘Python’, ‘flag’: ‘eng’}
{‘word’: ‘資料分析’, ‘flag’: ‘l’}
標註 | 解釋 | 標註 | 解釋 | 標註 | 解釋 |
---|---|---|---|---|---|
a | 形容詞 | mq | 數量詞 | tg | 時語素 |
ad | 副形詞 | n | 名詞 | u | 助詞 |
ag | 形語素 | ng | 例:義 乳 亭 | ud | 例:得 |
an | 名形詞 | nr | 人名 | ug | 例:過 |
b | 區別詞 | nrfg | 也是人名 | uj | 例:的 |
c | 連詞 | nrt | 也是人名 | ul | 例:了 |
d | 副詞 | ns | 地名 | uv | 例:地 |
df | 例:不要 | nt | 機構團體 | uz | 例:著 |
dg | 副語素 | nz | 其他專名 | v | 動詞 |
e | 嘆詞 | o | 擬聲詞 | vd | 副動詞 |
f | 方位詞 | p | 介詞 | vg | 動語素 |
g | 語素 | q | 量詞 | vi | 例:沉溺於 等同於 |
h | 前接成分 | r | 代詞 | vn | 名動詞 |
i | 成語 | rg | 例:茲 | vq | 例:去浄 去過 唸過 |
j | 簡稱略語 | rr | 人稱代詞 | x | 非語素字 |
k | 後接成分 | rz | 例:這位 | y | 語氣詞 |
l | 習用語 | s | 處所詞 | z | 狀態詞 |
m | 數詞 | t | 時間詞 | zg | 例:且 丗 丟 |
1.4、詞語出現的位置
- jieba.tokenize(sentence)
import jieba
sentence = '訂單資料分析'
generator = jieba.tokenize(sentence)
for position in generator:
print(position)
- 列印結果
- (‘訂單’, 0, 2)
(‘資料分析’, 2, 6)
2、詞典
2.1、預設詞典
import jieba, os, pandas as pd
# 詞典所在位置
print(jieba.__file__)
jieba_dict = os.path.dirname(jieba.__file__) + r'\dict.txt'
# 讀取字典
df = pd.read_table(jieba_dict, sep=' ', header=None)[[0, 2]]
print(df.head())
# 轉字典
dt = dict(df.values)
print(dt.get('暨南大學'))
2.2、添詞和刪詞
- 往詞典添詞
- add_word(word, freq=None, tag=None)
- 往詞典刪詞,等價於
add_word(word, freq=0)
- del_word(word)
import jieba
sentence = '天長地久有時盡,此恨綿綿無絕期'
# 添詞
jieba.add_word('時盡', 999, 'nz')
print('新增【時盡】:', jieba.lcut(sentence))
# 刪詞
jieba.del_word('時盡')
print('刪除【時盡】:', jieba.lcut(sentence))
- 列印結果
- 新增【時盡】: [‘天長地久’, ‘有’, ‘時盡’, ‘,’, ‘此恨綿綿’, ‘無’, ‘絕期’]
刪除【時盡】: [‘天長地久’, ‘有時’, ‘盡’, ‘,’, ‘此恨綿綿’, ‘無’, ‘絕期’]
2.3、自定義詞典載入
- 新建詞典,按照格式【單詞 詞頻 詞性】添詞,以UTF-8編碼儲存
- 使用函式
load_userdict
載入詞典
import os, jieba
# 建立自定義字典
my_dict = 'my_dict.txt'
with open(my_dict, 'w', encoding='utf-8') as f:
f.write('慕容紫英 9 nr\n雲天河 9 nr\n天河劍 9 nz')
# 載入字典進行測試
sentence = '慕容紫英為雲天河打造了天河劍'
print('載入前:', jieba.lcut(sentence))
jieba.load_userdict(my_dict)
print('載入後:', jieba.lcut(sentence))
os.remove(my_dict)
- 列印結果
- 載入前: [‘慕容’, ‘紫英為’, ‘雲’, ‘天河’, ‘打造’, ‘了’, ‘天河’, ‘劍’]
載入後: [‘慕容紫英’, ‘為’, ‘雲天河’, ‘打造’, ‘了’, ‘天河劍’]
2.4、使單詞中的字元連線或拆分
- suggest_freq(segment, tune=False)
import jieba
sentence = '上窮碧落下黃泉,兩處茫茫皆不見'
print('修正前:', ' | '.join(jieba.cut(sentence)))
jieba.suggest_freq(('落', '下'), True)
print('修正後:', ' | '.join(jieba.cut(sentence)))
- 列印結果
- 修正前: 上窮 | 碧 | 落下 | 黃泉 | , | 兩處 | 茫茫 | 皆 | 不見
修正後: 上窮 | 碧落 | 下 | 黃泉 | , | 兩處 | 茫茫 | 皆 | 不見
- 基於詞典,對句子進行詞圖掃描,生成所有成詞情況所構成的有向無環圖(
Directed Acyclic Graph
) - 根據DAG,反向計算最大概率路徑
- 根據路徑獲取最大概率的分詞序列
import jieba
sentence = '中心小學放假'
DAG = jieba.get_DAG(sentence)
print(DAG)
route = {}
jieba.calc(sentence, DAG, route)
print(route)
- DAG
- {0: [0, 1, 3], 1: [1], 2: [2, 3], 3: [3], 4: [4, 5], 5: [5]}
- 概率路徑
- {6: (0, 0), 5: (
-9.4
, 5), 4: (-12.6
, 5), 3: (-20.8
, 3), 2: (-22.5
, 3), 1: (-30.8
, 1), 0: (-29.5
, 3)}
- 詞圖掃描生成DAG,根據DGA反向計算概率
概率<1、log(概率)<0,取對數防止下溢,乘法運算轉為加法
詳情猛戳→jieba分詞原理
4、其它
4.1、並行分詞
- 開啟並行分詞模式,引數為併發數
- jieba.enable_parallel(n)
- 關閉並行分詞模式
- jieba.disable_parallel()
示例:使【Blade Master】這類中間有空格的詞被識別
import jieba, re
sentence = 'Blade Master疾風刺殺Archmage'
jieba.add_word('Blade Master') # 添詞
print('修改前:', jieba.lcut(sentence))
jieba.re_han_default = re.compile('(.+)', re.U) # 修改格式
print('修改後:', jieba.lcut(sentence))
- 列印結果
- 修改前: [‘
Blade
’, ’ ', ‘Master
’, ‘疾風’, ‘刺殺’, ‘Archmage’]
修改後: [‘Blade Master
’, ‘疾風’, ‘刺殺’, ‘Archmage’]
4.3、關鍵詞提取
- 基於TF-IDF:jieba.analyse
- 基於TextRank:jieba.textrank
import jieba.analyse as ja, jieba
text = '柳夢璃施法破解了狐仙的法術'
jieba.add_word('柳夢璃', tag='nr')
keywords1 = ja.extract_tags(text, allowPOS=('n', 'nr', 'ns', 'nt', 'nz'))
print('基於TF-IDF:', keywords1)
keywords2 = ja.textrank(text, allowPOS=('n', 'nr', 'ns', 'nt', 'nz'))
print('基於TextRank:', keywords2)
- 列印結果
- 基於TF-IDF: [‘柳夢璃’, ‘狐仙’, ‘法術’]
基於TextRank: [‘狐仙’, ‘柳夢璃’, ‘法術’]
from gensim import corpora, models, similarities
import jieba
# 文字集和搜尋詞
text1 = '吃雞這裡所謂的吃雞並不是真的吃雞,也不是我們常用的諧音詞刺激的意思'
text2 = '而是出自策略射擊遊戲《絕地求生:大逃殺》裡的臺詞'
text3 = '我吃雞翅,你吃雞腿'
texts = [text1, text2, text3]
keyword = '玩過吃雞嗎?今晚一起來吃雞'
# 1、將【文字集】生成【分詞列表】
texts = [jieba.lcut(text) for text in texts]
# 2、基於文字集建立【詞典】,並提取詞典特徵數
dictionary = corpora.Dictionary(texts)
feature_cnt = len(dictionary.token2id.keys())
# 3、基於詞典,將【分詞列表集】轉換成【語料庫】(存放稀疏向量的列表)
corpus = [dictionary.doc2bow(text) for text in texts]
# 4、使用【TF-IDF模型】處理語料庫
tfidf = models.TfidfModel(corpus)
# 5、同理,用【詞典】把【搜尋詞】也轉換為【稀疏向量】
kw_vector = dictionary.doc2bow(jieba.lcut(keyword))
# 6、對【稀疏向量集】建立【索引】
index = similarities.SparseMatrixSimilarity(tfidf[corpus], num_features=feature_cnt)
# 7、相似度計算
sim = index[tfidf[kw_vector]]
for i in range(len(sim)):
print('keyword 與 text%d 相似度為:%.2f' % (i+1, sim[i]))
- 列印結果
- keyword 與 text1 相似度為:0.62
keyword 與 text2 相似度為:0.00
keyword 與 text3 相似度為:0.12
from gensim import corpora, models
import jieba.posseg as jp, jieba
# 文字集
texts = [
'美國教練坦言,沒輸給中國女排,是輸給了郎平',
'美國無緣四強,聽聽主教練的評價',
'中國女排晉級世錦賽四強,全面解析主教練郎平的執教藝術',
'為什麼越來越多的人買MPV,而放棄SUV?跑一趟長途就知道了',
'跑了長途才知道,SUV和轎車之間的差距',
'家用的轎車買什麼好']
# 分詞過濾條件
jieba.add_word('四強', 9, 'n')
flags = ('n', 'nr', 'ns', 'nt', 'eng', 'v', 'd') # 詞性
stopwords = ('沒', '就', '知道', '是', '才', '聽聽', '坦言', '全面', '越來越', '評價', '放棄', '人') # 停詞
# 分詞
words_ls = []
for text in texts:
words = [word.word for word in jp.cut(text) if word.flag in flags and word.word not in stopwords]
words_ls.append(words)
# 構造詞典
dictionary = corpora.Dictionary(words_ls)
# 基於詞典,使【詞】→【稀疏向量】,並將向量放入列表,形成【稀疏向量集】
corpus = [dictionary.doc2bow(words) for words in words_ls]
# lda模型,num_topics設定主題的個數
lda = models.ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=2)
# 列印所有主題,每個主題顯示4個詞
for topic in lda.print_topics(num_words=4):
print(topic)
# 主題推斷
print(lda.inference(corpus))
- 結果
- 主題0(
體育
):‘0.081*“郎平” + 0.080*“中國女排” + 0.077*“輸給” + 0.074*“主教練”’
主題1(汽車
):‘0.099*“長途” + 0.092*“SUV” + 0.084*“跑” + 0.074*“轎車”’