文中实现了 n-gram 中最简单的 bi-gram 的简单案例,具体的原理可以见参考中的详解。
代码
## 这里只给出了几个分词,得到字频和单词集合
def init():
texts = ['政苑小区','万家花城','朝晖一区']
## 字频统计
wordcount = {}
## 加入了 s 和 e 表示开始和结束,如 政苑小区 --> s政苑小区e ,是为了进行之后的概率计算
words = []
for word in texts:
if word and len(word)>2:
word = 's' + word + 'e'
words.append(word)
for c in word:
if c not in wordcount:
wordcount[c] = 1
else:
wordcount[c] += 1
return wordcount,words
## 字符和数字互相映射的字典
def createDict(CHAR_FREQ):
c2n = {}
n2c = {}
count = 0
for c in CHAR_FREQ:
c2n[c] = count
n2c[count] = c
count += 1
return c2n,n2c
## 字频统计 和 单词
wordcount,words = init()
## 映射字典
c2n,n2c = createDict(wordcount)
## 得到 bi-gram 矩阵中的频率值
def calMatrix():
matrix = [[0]*len(wordcount) for i in range(len(wordcount))]
## 统计 bi-gram 出现频率
for key in words:
for i,c in enumerate(key):
if i == 0 or len(key)-1==i:
continue
else:
matrix[c2n[key[i-1]]][c2n[c]] += 1
## 计算 bi-gram 概率矩阵
for i,line in enumerate(matrix):
for j,freq in enumerate(line):
matrix[i][j] = round(matrix[i][j]/wordcount[n2c[i]],7)
return matrix
## 计算给定单词的概率值
def predict(strings):
matrix = calMatrix()
result = []
for s in strings:
r = 0
s = 's' + s + 'e'
for i,c in enumerate(s):
if i==0:
continue
if c in c2n:
r += math.log(matrix[c2n[s[i-1]]][c2n[s[i]]]+1)
else:
r = 0
break
result.append(r)
return result
print(predict(['政区区区','政朝小区','政苑小区','政家小区']))
复制代码
结果打印:
[0.28768204745178066, 0.9808292280117259, 2.3671235891316167, 0.9808292280117259]
复制代码
假如在不知道的情况下输入“政区区区”、“政朝小区”、“政苑小区”、“政家小区”四个词,从结果可以看出来“政苑小区”是得分最高的分词,所以优先选择这个答案。
参考
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END