KenLMで日本語文章の品質の評価

初めに

以下でLLMを使って文章の評価をしていますが、速度が速いと言われるKenLMでも評価してみます

ayousanz.hatenadiary.jp

開発環境

  • Ubuntu22.02

環境構築

sudo apt install build-essential cmake libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-test-dev libeigen3-dev zlib1g-dev libbz2-dev liblzma-dev
pip install https://github.com/kpu/kenlm/archive/master.zip
mkdir -p data/lm_sp
wget -c  -P data/lm_sp http://dl.fbaipublicfiles.com/cc_net/lm/ja.arpa.bin
wget -c  -P data/lm_sp http://dl.fbaipublicfiles.com/cc_net/lm/ja.sp.model

評価コード

import sys
import json
import csv
import kenlm

if __name__ == '__main__':
    with open("testData.txt", "r", encoding="utf-8") as f:
        lines = [line.strip() for line in f.readlines()[:30]]

    m = kenlm.LanguageModel("data/lm_sp/ja.arpa.bin")
    results = []

    for inp in lines:
        sentence = " ".join(inp)
        ppl = m.perplexity(sentence)
        results.append({"text": inp, "perplexity": ppl})
        print(ppl, inp)

    # Save results to JSON
    with open("kenlm_results.json", "w", encoding="utf-8") as f:
        json.dump(results, f, ensure_ascii=False, indent=4)

    # Save results to CSV
    with open("kenlm_results.csv", "w", newline="", encoding="utf-8") as f:
        fieldnames = ["text", "perplexity"]
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(results)

結果

text perplexity
それと僕が材料をお伝えした時にバニラエッセンスを入れたじゃないですか 17708.545685079465
1弦の5フレット、2弦の5フレット、 3弦の5フレット、2弦の7フレット、 38831.77205605622
けどもこれでえっと木スキル使うとさらに カウンターが1個貯まる 24178.439407054473
長い年月をかけて韓国人朝鮮人 と向き合ってきた中国人は韓国人 4482.124515163107
ごいハマり始めて 48969.93621135036
50話 いらっしゃいませ♪ ヘラのグランプリ! 93303.59762963047
オムニテクでは人々を助けを上がっている。 11689.811696733246
ステーキってもんはね 11286.760319052344
これが聞こえてきた 32392.71212184362
なるほどねそうなんだやばいすげ えわ 61553.26800664746
殺菌得ながらを 29143.353748316073
じゃあ呼吸法やりましょう、呼吸、呼吸 38638.26899312117
カンタ : そこやれるの見たいと思ってるよ、みんな 9503.800827281371
すげーなんか色んなものがこう そうなんだそうそうばすごいね 25696.966294762613
前回は standard assets を使って 遊んでいました 11098.166969108926
を獲得しました 9788.759603258804
しかしながら本当の理由はそれ だけではないのです 19715.238260370395
病むなんですが 59993.44877269272
全体混ぜると これね混ぜたら数分蒸らした方がいいです 38897.14236642167
アプリはそういったことを解決して くれるアプリです 15731.816412536211
ご丁寧に 106622.48885797341
下に 20732.22627445443
合わせてかぶせれば... 4003.3841234749957
そういう言い方で 32015.60911488846
朝食 69290.91681309085
流行ったものだそうですが 59954.375082911676
こうなります 9752.564887711484
次は釣りレベルの上限解放です。今度は何を釣らされるんだろうと思っていましたが、タマカイでした。 13016.617360872806
守りたい 17245.44873923792
だってさっきの人从众… 107673.84311097601

sentencepieceを使った場合

以下のコードを実行します

import sys
import kenlm
import sentencepiece
import unicodedata


if __name__ == '__main__':
    if len(sys.argv) < 3:
        print("Need ken_lm.arpa sentencepiece.model")
        sys.exit(-1)

    m = kenlm.LanguageModel(sys.argv[1])

    sp = sentencepiece.SentencePieceProcessor()
    sp.load(sys.argv[2])


    inputs = [
    '東京の夜景は美しい',
    '東京はいつも賑やかだ',
    '東京の街並みは独特だ',
    '東京の交通網は発達している',
    '東京は日本の経済の中心地だ',
    '東京の人口密度は高い',
    '東京の物価は高い',
    '東京の食文化は豊か',
    '東京のファッションは先進的',
    '東京の技術力は世界的だ',
    '東京の大学は有名だ',
    '東京の歴史は古い',
    '東京の伝統文化は守られている',
    '東京のサブカルチャーは多様だ',
    '東京のイベントは年中開催されている',
    '東京の公園は憩いの場だ',
    '東京の建築物はモダンだ',
    '東京の治安は良い',
    '東京の医療水準は高い',
    '東京の教育レベルは高い',
    '東京の環境対策は進んでいる',
    '東京の国際化は進んでいる',
    '東京のスポーツ施設は充実している',
    '東京の芸術活動は盛んだ',
    '東京の観光地は人気がある',
    '東京の祭りは活気がある',
    '東京の若者文化は独特だ',
    '東京の高齢化対策は課題だ',
    '東京の防災意識は高い',
    '東京の未来は明るい'
]

    for inp in inputs:
        # pretrained model in cc_net uses 'NFD' normalization?
        # TODO: Use https://github.com/facebookresearch/cc_net/blob/main/cc_net/text_normalizer.py
        text = unicodedata.normalize('NFD', inp)

        toks = sp.encode(text, out_type=str)
        print(toks)

        sentence = " ".join(toks)
        ppl = m.perplexity(sentence)
        print(ppl, inp)

実行コマンド

python sentencepiece2.py data/lm_sp/ja.arpa.bin data/lm_sp/ja.sp.model

結果

['▁東京', '', '', '晴れ', '']
4335.906162754335 東京はッ晴れ。
['▁東京', '', '元気', '', '', '']
4789.530541202564 東京は元気です。
['', '', '', '', '', '', 'ある', '.', '', '名前は', '', '', 'ない', '.']
677.481230499526 吾輩は猫である. 名前はまだない.
['▁東京', '', '晴れ', '']
1411.807566253476 東京は晴れ。
(venv) jovyan@yousan-0:~/lingua$ python sentencepiece1.py data/lm_sp/ja.arpa.bin data/lm_sp/ja.sp.model
['▁東京', '', '', '晴れ', '']
4335.906162754335 東京はッ晴れ。
['▁東京', '', '元気', '', '', '']
4789.530541202564 東京は元気です。
['', '', '', '', '', '', 'ある', '.', '', '名前は', '', '', 'ない', '.']
677.481230499526 吾輩は猫である. 名前はまだない.
['▁東京', '', '晴れ', '']
1411.807566253476 東京は晴れ。
(venv) jovyan@yousan-0:~/lingua$ python sentencepiece2.py data/lm_sp/ja.arpa.bin data/lm_sp/ja.sp.model
['▁東京', '', '夜景', '', '美しい']
1559.0554329452627 東京の夜景は美しい
['▁東京', '', 'いつも', '', '', '', '']
3771.668858772643 東京はいつも賑やかだ
['▁東京', '', '街並み', '', '', '', '']
2254.075478011484 東京の街並みは独特だ
['▁東京', '', '交通', '', '', '発達', 'している']
462.1914030627983 東京の交通網は発達している
['▁東京', 'は日本の', '経済', 'の中心地', '']
12523.705943574623 東京は日本の経済の中心地だ
['▁東京', '', '人口密度は', '高い']
1873.5702551396657 東京の人口密度は高い
['▁東京', '', '物価', '', '高い']
2306.9409256720432 東京の物価は高い
['▁東京', '', '食文化', '', '', '']
884.7496414993681 東京の食文化は豊か
['▁東京', '', 'ファッション', '', '先進', '']
942.4886609919694 東京のファッションは先進的
['▁東京', 'の技術', '', '', '世界的', '']
6352.528697589843 東京の技術力は世界的だ
['▁東京', '', '大学', '', '有名', '']
4518.518393639697 東京の大学は有名だ
['▁東京', 'の歴史', '', '古い']
1017.684104811051 東京の歴史は古い
['▁東京', '', '伝統文化', '', '', 'られている']
1318.7390808197645 東京の伝統文化は守られている
['▁東京', '', '', '', 'カルチャー', '', '多様', '']
16807.129140261182 東京のサブカルチャーは多様だ
['▁東京', '', '', '', 'ント', '', '', '', '開催されている']
5225.4904688694405 東京のイベントは年中開催されている
['▁東京', '', '公園', '', '憩いの場', '']
8311.233290969833 東京の公園は憩いの場だ
['▁東京', '', '建築物', '', '', '', '', '']
10915.668390212073 東京の建築物はモダンだ
['▁東京', '', '治安', '', '良い']
1337.6293205006057 東京の治安は良い
['▁東京', '', '医療', '水準', '', '高い']
859.5305593891276 東京の医療水準は高い
['▁東京', 'の教育', '', '', '', '', '高い']
11565.088896342308 東京の教育レベルは高い
['▁東京', '', '環境', '対策', '', '', '', '', 'いる']
5312.109623816024 東京の環境対策は進んでいる
['▁東京', 'の国際', '', '', '', '', '', 'いる']
8152.9475124097125 東京の国際化は進んでいる
['▁東京', '', '', '', 'ーツ', '施設は', '充実', 'している']
9341.116680821911 東京のスポーツ施設は充実している
['▁東京', '', '芸術', '活動', '', '盛ん', '']
1878.5996129207565 東京の芸術活動は盛んだ
['▁東京', '', '観光地', '', '人気', '', 'ある']
7621.730945021132 東京の観光地は人気がある
['▁東京', '', '祭り', '', '', '', '', 'ある']
2674.160008880571 東京の祭りは活気がある
['▁東京', '', '若者', '文化', '', '', '', '']
1578.6075972487467 東京の若者文化は独特だ
['▁東京', '', '高齢化', '対策', '', '課題', '']
4875.003477257479 東京の高齢化対策は課題だ
['▁東京', '', '防災', '意識', '', '高い']
1151.5175930579533 東京の防災意識は高い
['▁東京', '', '未来', '', '明るい']
1190.656783416366 東京の未来は明るい

参考サイト

zenn.dev