1. 程式人生 > >沒有物件也要談戀愛之女朋友的情緒監控 之 分詞

沒有物件也要談戀愛之女朋友的情緒監控 之 分詞

?? 通過女朋友的一句話分析她的心情 。

Analyze her mood through her girlfriend's words .

通過一句話分析女朋友的情緒變化,最重要的就是對這句話先進行詞法分析,將話中的每一個關鍵詞分離開來,然後分析關鍵詞。

關鍵詞我們可以以情緒值來進行估算最終情緒,然後總體一個基址,每次都在此上加減。

第一章 分詞

1、JieBa庫

“結巴”中文分詞:做最好的 Python 中文分片語件

"Jieba" (Chinese for "to stutter") Chinese text segmentation: built to be the best Python Chinese word segmentation module.

2、特點

  • 支援三種分詞模式:
    • 精確模式,試圖將句子最精確地切開,適合文字分析;
    • 全模式,把句子中所有的可以成詞的詞語都掃描出來, 速度非常快,但是不能解決歧義;
    • 搜尋引擎模式,在精確模式的基礎上,對長詞再次切分,提高召回率,適合用於搜尋引擎分詞。
  • 支援繁體分詞
  • 支援自定義詞典
  • MIT 授權協議

3、演算法

  • 基於字首詞典實現高效的詞圖掃描,生成句子中漢字所有可能成詞情況所構成的有向無環圖 (DAG)
  • 採用了動態規劃查詢最大概率路徑, 找出基於詞頻的最大切分組合
  • 對於未登入詞,採用了基於漢字成詞能力的 HMM 模型,使用了 Viterbi 演算法

4、主要功能

1) 分詞

  • jieba.cut
    方法接受三個輸入引數: 需要分詞的字串;cut_all 引數用來控制是否採用全模式;HMM 引數用來控制是否使用 HMM 模型
  • jieba.cut_for_search 方法接受兩個引數:需要分詞的字串;是否使用 HMM 模型。該方法適合用於搜尋引擎構建倒排索引的分詞,粒度比較細
  • 待分詞的字串可以是 unicode 或 UTF-8 字串、GBK 字串。注意:不建議直接輸入 GBK 字串,可能無法預料地錯誤解碼成 UTF-8
  • jieba.cut 以及 jieba.cut_for_search 返回的結構都是一個可迭代的 generator,可以使用 for 迴圈來獲得分詞後得到的每一個詞語(unicode),或者用
  • jieba.lcut 以及 jieba.lcut_for_search 直接返回 list
  • jieba.Tokenizer(dictionary=DEFAULT_DICT) 新建自定義分詞器,可用於同時使用不同詞典。jieba.dt 為預設分詞器,所有全域性分詞相關函式都是該分詞器的對映。
seg_list = jieba.cut("我要有女朋友了", cut_all=True)
print("全模式: " + "/ ".join(seg_list))  # 全模式

seg_list = jieba.cut("我要有女朋友了", cut_all=False)
print("預設模式: " + "/ ".join(seg_list))  # 預設模式

seg_list = jieba.cut("我要有女朋友了")
print(", ".join(seg_list))

seg_list = jieba.cut_for_search("我要有女朋友了,然後我要打爆室友的狗頭")  # 搜尋引擎模式
print("搜尋引擎模式: "+", ".join(seg_list))  

output :

全模式: 我/ 要/ 有/ 女朋友/ 朋友/ 了
預設模式: 我要/ 有/ 女朋友/ 了
我要, 有, 女朋友, 了
搜尋引擎模式: 我要, 有, 朋友, 女朋友, 了, ,, 然後, 我要, 打爆, 室友, 的, 狗頭

2) 新增自定義詞典

載入詞典

  • 開發者可以指定自己自定義的詞典,以便包含 jieba 詞庫裡沒有的詞。雖然 jieba 有新詞識別能力,但是自行新增新詞可以保證更高的正確率
  • 用法: jieba.load_userdict(file_name) # file_name 為檔案類物件或自定義詞典的路徑
  • 詞典格式和 dict.txt 一樣,一個詞佔一行;每一行分三部分:詞語、詞頻(可省略)、詞性(可省略),用空格隔開,順序不可顛倒。file_name 若為路徑或二進位制方式開啟的檔案,則檔案必須為 UTF-8 編碼。
  • 詞頻省略時使用自動計算的能保證分出該詞的詞頻。
print('/'.join(jieba.cut('這個東梨會不會被分開呢。', HMM=False)))
# 新增字典
print(jieba.suggest_freq(('東梨'), True)) # 新增一個詞語'東梨'
print('/'.join(jieba.cut('這個東梨會不會被分開呢。', HMM=False)))

output :

這個/東/梨/會/不會/被/分開/呢/。
這個/東梨/會/不會/被/分開/呢/。

調整詞典

  • 使用 add_word(word, freq=None, tag=None)del_word(word) 可在程式中動態修改詞典。
  • 使用 suggest_freq(segment, tune=True) 可調節單個詞語的詞頻,使其能(或不能)被分出來。

  • 注意:自動計算的詞頻在使用 HMM 新詞發現功能時可能無效。

3) 關鍵詞提取

基於 TF-IDF 演算法的關鍵詞抽取

import jieba.analyse

  • jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())
    • sentence 為待提取的文字
    • topK 為返回幾個 TF/IDF 權重最大的關鍵詞,預設值為 20
    • withWeight 為是否一併返回關鍵詞權重值,預設值為 False
    • allowPOS 僅包括指定詞性的詞,預設值為空,即不篩選
  • jieba.analyse.TFIDF(idf_path=None) 新建 TFIDF 例項,idf_path 為 IDF 頻率檔案
s = "作業系統(Operation System,簡稱OS)是管理計算機硬體與軟體資源的程式,是計算機系統的核心與基石;作業系統本質上是執行在計算機上的軟體程式 ;為使用者提供一個與系統互動的操作介面 ;作業系統分核心與外殼(我們可以把外殼理解成圍繞著核心的應用程式,而核心就是能操作硬體的程式)。"
for x, w in jieba.analyse.extract_tags(s, withWeight=True):
    print('%s %s' % (x, w))

print('-'*40)
print(' TextRank')
print('-'*40)

for x, w in jieba.analyse.textrank(s, withWeight=True):
    print('%s %s' % (x, w))

output :

核心 1.0625279118105262
作業系統 0.7315222629276317
外殼 0.4645002019336842
軟體程式 0.36580730663157895
軟體資源 0.34756659135263157
程式 0.3333060550794737
操作介面 0.32345367735526315
Operation 0.31459914481315787
System 0.31459914481315787
OS 0.31459914481315787
計算機硬體 0.2800679240526316
應用程式 0.2763021123763158
計算機系統 0.23982068182078944
互動 0.23731251919447366
基石 0.23595272944342105
硬體 0.22168984473789474
本質 0.18271527055526315
使用者 0.1795351598005263
計算機 0.1790732744968421
圍繞 0.177282393885
----------------------------------------
 TextRank
----------------------------------------
核心 1.0
程式 0.5362199524590612
系統 0.48948949335129555
提供 0.48602227553244165
圍繞 0.4446670737747918
執行 0.4225011310851474
管理 0.4151898395341863
基石 0.4131936048253403
計算機系統 0.38302557644090945
硬體 0.36775003601316436
操作 0.36615155530109056
本質 0.3554627436547271
計算機硬體 0.3491604047032015
理解 0.3433887505596043
外殼 0.3419635842574655
應用程式 0.33616306371021853
使用者 0.33122514947879544
互動 0.3287196036788538
計算機 0.23122054865622482
簡稱 0.22777433887730136

4) 詞性標註

  • jieba.posseg.POSTokenizer(tokenizer=None) 新建自定義分詞器,tokenizer 引數可指定內部使用的 jieba.Tokenizer 分詞器。jieba.posseg.dt 為預設詞性標註分詞器。
  • 標註句子分詞後每個詞的詞性,採用和 ictclas 相容的標記法。
  • 用法示例
words = jieba.posseg.cut("我愛北京天安門")
for word, flag in words:
    print('%s %s' % (word, flag))
print('='*40)

output :

我 r
愛 v
北京 ns
天安門 ns

5) 並行分詞

  • 原理:將目標文字按行分隔後,把各行文字分配到多個 Python 程序並行分詞,然後歸併結果,從而獲得分詞速度的可觀提升
  • 基於 python 自帶的 multiprocessing 模組,目前暫不支援 Windows
  • 用法:
    • jieba.enable_parallel(4) # 開啟並行分詞模式,引數為並行程序數
    • jieba.disable_parallel() # 關閉並行分詞模式

6) Tokenize:返回詞語在原文的起止位置

  • 注意,輸入引數只接受 unicode
  • 預設模式
print(' 預設模式')
print('-'*40)
result = jieba.tokenize('永和服裝飾品有限公司')
for tk in result:
    print("word %s\t\t start: %d \t\t end:%d" % (tk[0],tk[1],tk[2]))

print('-'*40)
print(' 搜尋模式')
print('-'*40)

result = jieba.tokenize('永和服裝飾品有限公司', mode='search')
for tk in result:
    print("word %s\t\t start: %d \t\t end:%d" % (tk[0],tk[1],tk[2]))

output :

word 永和      start: 0        end:2
word 服裝      start: 2        end:4
word 飾品      start: 4        end:6
word 有限公司        start: 6        end:10
----------------------------------------
 搜尋模式
----------------------------------------
word 永和      start: 0        end:2
word 服裝      start: 2        end:4
word 飾品      start: 4        end:6
word 有限      start: 6        end:8
word 公司      start: 8        end:10
word 有限公司        start: 6        end:10

5、一個完整的分詞可執行例項

目錄結構

jieba是我們要匯入的第三方庫,在專案中我直接把它放在了裡面。

│  run.py
│
└─jieba
    │  dict.txt
    │  _compat.py
    │  __init__.py
    │  __main__.py
    │
    ├─analyse
    │  │  analyzer.py
    │  │  idf.txt
    │  │  textrank.py
    │  │  tfidf.py
    │  │  __init__.py
    │  │
    │  └─__pycache__
    │          analyzer.cpython-37.pyc
    │          textrank.cpython-37.pyc
    │          tfidf.cpython-37.pyc
    │          __init__.cpython-37.pyc
    │
    ├─finalseg
    │  │  prob_emit.p
    │  │  prob_emit.py
    │  │  prob_start.p
    │  │  prob_start.py
    │  │  prob_trans.p
    │  │  prob_trans.py
    │  │  __init__.py
    │  │
    │  └─__pycache__
    │          prob_emit.cpython-37.pyc
    │          prob_start.cpython-37.pyc
    │          prob_trans.cpython-37.pyc
    │          __init__.cpython-37.pyc
    │
    ├─posseg
    │  │  char_state_tab.p
    │  │  char_state_tab.py
    │  │  prob_emit.p
    │  │  prob_emit.py
    │  │  prob_start.p
    │  │  prob_start.py
    │  │  prob_trans.p
    │  │  prob_trans.py
    │  │  viterbi.py
    │  │  __init__.py
    │  │
    │  └─__pycache__
    │          char_state_tab.cpython-37.pyc
    │          prob_emit.cpython-37.pyc
    │          prob_start.cpython-37.pyc
    │          prob_trans.cpython-37.pyc
    │          viterbi.cpython-37.pyc
    │          __init__.cpython-37.pyc
    │
    └─__pycache__
            _compat.cpython-37.pyc
            __init__.cpython-37.pyc

run.py中編寫程式碼,並且呼叫jieba庫實現分詞。

run.py

#encoding=utf-8
from __future__ import unicode_literals
import jieba

if __name__=="__main__":
    ch = input()
    seg_list = jieba.cut(str(ch))
    print(", ".join(seg_list))

在此處輸入"我馬上就要有女朋友了"。

即可得到輸出結果如下。

我, 馬上, 就要, 有, 女朋友, 了

6、程式碼地址

Github : [https://github.com/CasterWx/python-girlfriend-mood](https://github.com/CasterWx/python-girlfriend-mood)