Python 实现 Bi-Gram | Python 主题月

文中实现了 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
喜欢就支持一下吧
点赞0 分享