使用kenlm进行文本纠错

简介

  1. kenlm是Kenneth Heafield个人开发的语言模型工具,参考:https://kheafield.com/code/kenlm/
  2. GitHub: https://github.com/kpu/kenlm

安装流程省略

文本纠错应用

模型训练

  • 准备数据
    • 哈工大信息检索研究中心(HIT CIR)语言技术平台共享资源
    http://ir.hit.edu.cn/demo/ltp/Sharing_Plan.htm
    http://ir.hit.edu.cn/demo/ltp/HIT-CIR_LTP_Corpora_Sample_v1.rar
    
    • 使用prepare.py脚本预处理,处理成如下的格式
    中 国 开 展 登 月 计 划 的 意 义
    神 舟 五 号 载 人 飞 船 带 着 亿 万 炎 黄 子 孙 的 期 盼 遨 游 九 天 。
    关 于 月 亮 的 咏 叹 比 比 皆 是 :
    我 国 古 代 , 帝 王 就 有 春 天 祭 日 、 秋 天 祭 月 的 礼 制 。
    在 民 间 , 每 逢 八 月 中 秋 , 也 有 拜 月 或 祭 月 的 风 俗 。
    关 于 月 球 的 传 说 家 喻 户 晓 :
    
  • 训练模型:文本以单字切分,使用n-gram
bin/lmplz -o 2 --text ./data.txt  --arpa lm.arpa -S 80% --discount_fallback

-o 指定n-gram
-S 指定使用多少内存
--discount_fallback 需要指定 不然会报下面的错

Unigram tokens 205390 types 2106
=== 2/5 Calculating and sorting adjusted counts ===
Chain sizes: 1:25272 2:18370318336 3:34444349440 4:55110959104
/data/xqchen4/3rd/kenlm/lm/builder/adjust_counts.cc:60 in void lm::builder::{anonymous}::StatCollector::CalculateDiscounts(const lm::builder::DiscountConfig&) threw BadDiscountException because `discounts_[i].a
mount[j] < 0.0 || discounts_[i].amount[j] > j'.ERROR: 4-gram discount out of range for adjusted count 3: -29.239872.  This means modified Kneser-Ney smoothing thinks something is weird about your data.  To override this error for e.g. a class-based model, r
erun with --discount_fallback
  • 模型压缩
bin/build_binary -s lm.arpa lm.bin

demo应用测试

  • 详细请参考evaluation.py
代码示例:
# 使用kenlm进行文本纠错
import kenlm
import json

def correction(lm,sentence,dict):
    result = []
    s1 = lm.perplexity(" ".join(sentence))
    for i in range(len(sentence)):
        cur_word = sentence[i]
        if cur_word not in dict:
            continue
        cur_candidates = []
        for candi in dict[cur_word]:
            new_sentence = sentence
            new_sentence[i] = candi
            s2 = lm.perplexity(" ".join(new_sentence))
            if s2 < s1:
                cur_candidates.append({
                    "original":cur_word,
                    "correction":candi,
                    "position":i,
                    "perplexity":s2
                })
        #存在多个候选结果,则按照perplexity得分进行排序,取top1结果
        if len(cur_candidates) > 1:
            cur_candidates.sort(key = lambda e:e.__getitem__('perplexity'))
        if len(cur_candidates) > 0:
            result.append(cur_candidates[0])
    return result

if __name__ == "__main__":
    #提前训练好的模型
    lm_model_path = "./model/lm.bin"
    #别字词典
    similarity_dictionary = {"泳":["永","咏"],"事":["是"]}
    sentence = "关于月亮的泳叹比比皆事"
    #加载模型
    lm = kenlm.Model(lm_model_path)
    #别字纠错计算
    result = correction(lm,list(sentence),similarity_dictionary)
    if result:
        result.sort(key=lambda e: e.__getitem__('perplexity'))
        print(json.dumps(result,ensure_ascii=False,indent=2))

Reference

原文地址:https://www.cnblogs.com/duothink/p/14303130.html