算法原理在一、二部分:
代碼流程如下:
1、讀取天龍八部小說文檔,並轉換爲Series 數據結構。Series是一個一維數組,是基於NumPy的ndarray結構。Pandas會默然用0到n-1來作爲series的index,但也可以自己指定index(可以把index理解爲dict裏面的key)。
f = open('天龍八部.txt', 'r',encoding='utf-8') # 讀取文章
s = f.read() # 讀取爲一個字符串
t = [] # 保存結果用。
t.append(pd.Series(list(s)).value_counts()) # 逐字統計 value_counts()返回值爲 series,所有的元素排序返回。
tsum = t[0].sum() # 統計總字數。獨一無二的字的個數。
rt = [] # 保存結果用
2、數據預處理,標點字符過濾
# 定義要去掉的標點字
drop_dict = [u',', u'\n', u'。', u'、', u':', u'(', u')', u'[', u']', u'.', u',', u' ', u'\u3000', u'”', u'“', u'?', u'?',
u'!', u'‘', u'’', u'…']
for i in drop_dict: # 去掉標點字
s = s.replace(i, '')
3、因爲要對2、3、4字的詞語分別進行匹配,定義字典
# 爲了方便調用,自定義了一個正則表達式的詞典
myre = {2: '(..)', 3: '(...)', 4: '(....)', 5: '(.....)', 6: '(......)', 7: '(.......)'}
4、 定義四個參數,依次爲(二)中定義的頻數、內部凝固程度,自由運用程度,詞語長度
min_count = 10 # 錄取詞語最小出現次數
min_support = 30 # 錄取詞語最低支持度,1代表着隨機組合
min_s = 3 # 錄取詞語最低信息熵,越大說明越有可能獨立成詞
max_sep = 4 # 候選詞語的最大字數
5、由於re.findall() 返回的是匹配到的 non-overlapping 字符串,因此從i 從0到m進行遍歷以得到所有可能的組合。
s = 'abcdede'
ree = '(..)'
res = re.findall(ree, s)
print(res) # ['ab', 'cd', 'ed']
計算內部凝固程度,進行第一步的篩選。
for m in range(2, max_sep + 1):
print(u'正在生成%s字詞...' % m)
t.append([]) # 2,3,4 三個空的列表。
for i in range(m): # 生成所有可能的m字詞
t[m - 1] = t[m - 1] + re.findall(myre[m], s[i:])
t[m - 1] = pd.Series(t[m - 1]).value_counts() # 逐詞統計
t[m - 1] = t[m - 1][t[m - 1] > min_count] # 最小次數篩選
tt = t[m - 1][:]
for k in range(m - 1):
qq = np.array(list(map(lambda ms: tsum * t[m - 1][ms] / t[m - 2 - k][ms[:m - 1 - k]] / t[k][ms[m - 1 - k:]],
tt.index))) > min_support # 最小支持度篩選。
tt = tt[qq]
rt.append(tt.index)
6、定義信息熵計算函數,並計算其左右鄰信息熵得到最終結果
def cal_S(sl): # 信息熵計算函數
return -((sl / sl.sum()).apply(log) * sl / sl.sum()).sum()
for i in range(2, max_sep + 1):
print(u'正在進行%s字詞的最大熵篩選(%s)...' % (i, len(rt[i - 2])))
pp = [] # 保存所有的左右鄰結果
for j in range(i + 2):
pp = pp + re.findall('(.)%s(.)' % myre[i], s[j:])
pp = pd.DataFrame(pp).set_index(1).sort_index() # 先排序,這個很重要,可以加快檢索速度
index = np.sort(np.intersect1d(rt[i - 2], pp.index)) # 作交集
# 下面兩句分別是左鄰和右鄰信息熵篩選
index = index[np.array(list(map(lambda s: cal_S(pd.Series(pp[0][s]).value_counts()), index))) > min_s]
rt[i - 2] = index[np.array(list(map(lambda s: cal_S(pd.Series(pp[2][s]).value_counts()), index))) > min_s]
for j in range(i+2) : s[j:] 的作用同5,找到所有可能的左右鄰。
s = 'abcdede'
ree = '(..)'
pp = []
for j in range(2 + 2):
pp = pp + re.findall('(.)%s(.)' % ree, s[j:])
print(pp)
#[('a', 'bc', 'd'), ('b', 'cd', 'e'), ('c', 'de', 'd'), ('d', 'ed', 'e')]
7、保存結果。 result.txt 文件部分內容如下
無崖子,60
木婉清,738
王語嫣,859
# 下面都是輸出前處理
for i in range(len(rt)):
t[i + 1] = t[i + 1][rt[i]]
t[i + 1].sort_values(ascending = False)
# 保存結果並輸出
pd.DataFrame(pd.concat(t[1:])).to_csv('result.txt', header=False)
完整代碼及數據集下載:
關注微信公衆號:曉說AI
留言:天龍八部 獲取下載鏈接