Python基於共現提取《釜山行》人物關系
一、課程介紹
1. 內容簡介
《釜山行》是一部喪屍災難片,其人物少、關系簡單,非常適合我們學習文本處理。這個項目將介紹共現在關系中的提取,使用python編寫代碼實現對《釜山行》文本的人物關系提取,最終利用Gephi軟件對提取的人物關系繪制人物關系圖。
2. 課程知識點
本課程項目完成過程中將學習:
- 共現網絡的基本原理
- Python代碼對《釜山行》中人物關系提取的具體實現
jieba
庫的基本使用- Gephi軟件的基本使用
3. 課程來源
課程使用的操作系統為 Ubuntu 14.04
。你可以在我的 Github 上找到針對《釜山行》人物關系提取的全部代碼。你也可以直接點擊查看共現網絡簡單的英文介紹。
二、實驗原理
實驗基於簡單共現關系,編寫 Python 代碼從純文本中提取出人物關系網絡,並用Gephi
將生成的網絡可視化。下面介紹共現網絡的基本原理。你可以在我的博客查看對共現網絡簡單的英文介紹。
實體間的共現是一種基於統計的信息提取。關系緊密的人物往往會在文本中多段內同時出現,可以通過識別文本中已確定的實體(人名),計算不同實體共同出現的次數和比率。當比率大於某一閾值,我們認為兩個實體間存在某種聯系。這種聯系可以具體細化,但提取過程也更加復雜。因此在此課程只介紹最基礎的共現網絡。
三、開發准備
打開Xfce終端,進入 Code
目錄,創建 work
文件夾, 將其作為課程的工作目錄。下載並安裝 gephi
。
$ mkdir work && cd work $ mkdir gephi && cd gephi $ wget http://labfile.oss.aliyuncs.com/courses/677/gephi-0.9.1-linux.tar.gz #下載 $ tar -zxvf gephi-0.9.1-linux.tar.gz #解壓
下載《釜山行》的中文劇本。
$ wget http://labfile.oss.aliyuncs.com/courses/677/busan.txt
安裝jieba
中文分詞。
$ sudo pip2 install jieba
四、實驗步驟
你可以通過下面命令將代碼下載到實驗樓環境中,作為參照對比進行學習。
$ wget http://labfile.oss.aliyuncs.com/courses/677/busan.py
1.觀察文本結構、准備詞典
《釜山行》劇本非常適合文本處理,語言簡潔,大致每一段對應一個關鍵情節。人物較少且易於識別,所以非常適合文本處理的學習,因此選用了《釜山行》作為課程的樣例。
由於《釜山行》人物少、關系簡單,所以我們可以通過詞典指定人物名稱的方式做實體識別。你也可以不建立字典並嘗試使用某種分詞算法或包裝好的分詞庫(如教程使用的jieba
),但離開特定詞典的針對特定文本的分詞效果可能會有很大程度削弱。因此對簡單網絡而言,建立字典是效率較高的做法。
可以通過各類百科獲取《釜山行》的主要人物,你可以在百度百科中找到他們的介紹,並將人名寫入一個字典中。項目將主要人物的名稱保存在文件dict.txt
中,你可以通過下面的命令下載這個字典,也可以自己新建一個文件保存。字典dict.txt
需放在文件夾work
下。
$ wget http://labfile.oss.aliyuncs.com/courses/677/dict.txt
2.確定需要的變量
在work
文件下創建代碼文件busan.py
,開始進行python代碼的編寫。
在代碼中,我使用字典類型names
保存人物,該字典的鍵為人物名稱,值為該人物在全文中出現的次數。我使用字典類型relationships
保存人物關系的有向邊,該字典的鍵為有向邊的起點,值為一個字典edge
,edge
的鍵是有向邊的終點,值是有向邊的權值,代表兩個人物之間聯系的緊密程度。lineNames
是一個緩存變量,保存對每一段分詞得到當前段中出現的人物名稱,lineName[i]
是一個列表,列表中存儲第i
段中出現過的人物。
# -*- coding: utf-8 -*- import os, sys import jieba, codecs, math import jieba.posseg as pseg names = {} # 姓名字典 relationships = {} # 關系字典 lineNames = [] # 每段內人物關系
3.文本中實體識別
在具體實現過程中,讀入《釜山行》劇本的每一行,對其做分詞(判斷該詞的詞性是不是“人名”[詞性編碼:nr],如果該詞的詞性不為nr,則認為該詞不是人名),提取該行(段)中出現的人物集,存入lineName
中。之后對出現的人物,更新他們在names
中的出現次數。
jieba.load_userdict("dict.txt") # 加載字典 with codecs.open("busan.txt", "r", "utf8") as f: for line in f.readlines(): poss = pseg.cut(line) # 分詞並返回該詞詞性 lineNames.append([]) # 為新讀入的一段添加人物名稱列表 for w in poss: if w.flag != "nr" or len(w.word) < 2: continue # 當分詞長度小於2或該詞詞性不為nr時認為該詞不為人名 lineNames[-1].append(w.word) # 為當前段的環境增加一個人物 if names.get(w.word) is None: names[w.word] = 0 relationships[w.word] = {} names[w.word] += 1 # 該人物出現次數加 1
你可以在 with
代碼塊之后添加以下代碼輸出生成的 names
來觀察人物出現的次數:
for name, times in names.items(): print name, times
運行代碼
python busan.py
在實驗樓中的顯示結果如下圖:
4.根據識別結果構建網絡
對於 lineNames
中每一行,我們為該行中出現的所有人物兩兩相連。如果兩個人物之間尚未有邊建立,則將新建的邊權值設為 1,否則將已存在的邊的權值加 1。這種方法將產生很多的冗余邊,這些冗余邊將在最后處理。
for line in lineNames: # 對於每一段 for name1 in line: for name2 in line: # 每段中的任意兩個人 if name1 == name2: continue if relationships[name1].get(name2) is None: # 若兩人尚未同時出現則新建項 relationships[name1][name2]= 1 else: relationships[name1][name2] = relationships[name1][name2]+ 1 # 兩人共同出現次數加 1
5.過濾冗余邊並輸出結果
將已經建好的 names
和 relationships
輸出到文本,以方便 gephi
可視化處理。輸出邊的過程中可以過濾可能是冗余的邊,這里假設共同出現次數少於 3 次的是冗余邊,則在輸出時跳過這樣的邊。輸出的節點集合保存為 busan_node.txt
,邊集合保存為 busan_edge.node
。
with codecs.open("busan_node.txt", "w", "gbk") as f: f.write("Id Label Weight\r\n") for name, times in names.items(): f.write(name + " " + name + " " + str(times) + "\r\n") with codecs.open("busan_edge.txt", "w", "gbk") as f: f.write("Source Target Weight\r\n") for name, edges in relationships.items(): for v, w in edges.items(): if w > 3: f.write(name + " " + v + " " + str(w) + "\r\n")
完成所有代碼編寫后,運行
python busan.py
在文件夾work
下將會生成busan_node.txt
和busan_edge.node
。
6.可視化網絡
前面對《釜山行》劇本中的人物關系數據進行了處理,下面我們將使用gephi這個軟件來將人物關系可視化,以便展示的更直觀,畢竟生硬的數字和文本,或許只有你才懂,其他人可看不明白。
使用 gephi
導入生成的網絡,並生成簡單的可視化布局。執行下面命令啟動 gephi
。
$ cd gephi-0.9.1 $ cd bin $ ./gephi
點擊 文件 -> Import SpreadSheets
。
分別選擇節點表格和邊表格導入上面代碼中生成的兩個文件,分隔符選擇 空格
,編碼選擇 GB2312
。
導入后 gephi
將顯示所有節點。此時節點沒有合適的布局,如下圖。你可以在最上方的 數據資料
選項卡中查看圖中所有的邊和節點,對於分詞不准確導致的噪音,可以手動刪除。
分別點擊右側 統計
欄中 平均度
和 模塊化
運行計算。模塊化運算時 Resolution
值填寫 0.5
。
點擊左上角外觀
中節點
第一個選項卡,選擇數值設定
,選擇Modularity Class
。
選中第二個選項卡,選擇數值設定
,選擇連入度
,最小尺寸填10,最大尺寸填40,點擊應用為節點染色、放大。
選擇左下角布局
中的 Force Atlas
,斥力強度填寫 20000.0
,吸引強度填寫 1.0
。點擊運行,稍后點擊停止。
此時布局大致如下圖所示。節點染色根據模塊化計算結果不定,但染色效果大致相同。
點擊最上方的 預覽
按鈕,選中左側 節點標簽
中 顯示標簽
選項,並選擇一種字體,這里選擇 文泉驛微米黑
。
點擊刷新按鈕,右側顯示最終的人物關系圖。