ナイーブベイズで文字化けの種別を判定する。
2018-07-286 min read
目次
背景
古い構成のシステムとかだとソースコード、HTMLの雛形、DB、内部処理のエンコード形式など文字コードがバラバラなんて言うことがある。 euc-jpとshift-jisが混ざってる上にターミナルやvimのエンコードでぐちゃぐちゃ下文字列を見る時の気分は最悪だ。 と言うわけで、コピペするだけでどの文字化けを解くのが目的。 http://lab.kiki-verb.com/mojibakeratta/ (もじばけらった)とか こう言うものもあるが、スマートで一発に解くのが目的。兼、機械学習のお勉強。
概要
scikit-learnのナイーブベイズ分類器を使って、エンコードされてしまった文字列を解析する。
scikit-learnとナイーブベイズ
ナイーブベイズ分類器はいくつか用意されており、その中でもシンプルなガウシアンを利用する。 65535種類あるUTF-8の中から、どんな文字が多く出現しているかをカウントしていく方法で分類
対象とする文字化け
学習データ
# | 元の文字コード | エンコードした文字コード | 例 |
---|---|---|---|
1 | shift-jis | utf-8 | 「縺薙l縺ッUTF-8縺ョ繝・く繧ケ繝医〒縺吶よ怙霑代・谿・←縺薙l縺ァ縺吶・縲」 |
2 | euc-jp | utf-8 | 「ホ・ニ・ュ・ケ・ネ、ヌ、ケ。」、ス、・ハ、熙ヒハリヘ」 |
3 | utf-8 | shift-jis | 「$l$O(Jiso-2022-jp$B$N%F%-%9%H$G$9!#(JJIS$B$H$b8@$C$?$j$7$^$9!#EE;R%a!<%」 |
おまけ1 | - | - | 「This is plane text」 ※英語として分類 |
おまけ2 | - | - | 「この文章は日本語で書かれています」 ※日本語として分類 |
分類するデータ
arr = [
"これはUTF-8のテキストです。最近は殆どこれですね。",
"代・谿・←縺薙l縺ァ縺吶・縲",
"Hello World",
"euc-jp、ホ・ニ・ュ・ケ・ネ、ヌ、ケ。」、ス、・ハ、熙ヒハリヘタ、テ、ソ、ホ、ヌ、゙",
"$B$N%F%-%9%H$G$9!#(JJIS$B$H"
]
結果
['ja-jp'] これはUTF-8のテキストです。最近は殆どこれですね。
['shift-jis->utf-8'] 代・谿・←縺薙l縺ァ縺吶・縲
['en'] Hello World
['euc-jp->utf-8'] euc-jp、ホ・ニ・ュ・ケ・ネ、ヌ、ケ。」、ス、・ハ、熙ヒハリヘタ、テ、ソ、ホ、ヌ、゙
['utf-8->shift-jis'] $B$N%F%-%9%H$G$9!#(JJIS$B$H
となった。 データが集めがザルだったが、それっぽく分類できるのは確認できた。 APIにするのも難しくなさそう。
ソース
import numpy as np
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score
def count_codePoint(str):
counter = np.zeros(65535)
for i in range(len(str)):
code_point = ord(str[i])
if code_point > 65535 :
continue
counter[code_point] += 1
counter = counter/len(str)
return counter
ja_str = '縺薙l縺ッUTF-8縺ョ繝・く繧ケ繝医〒縺吶よ怙霑代・谿・←縺薙l縺ァ縺吶・縲'
en_str = ' This is English Strings.'
x_train = [
count_codePoint('This is plane text'),
count_codePoint('この文章は日本語で書かれています'),
count_codePoint('縺薙l縺ッUTF-8縺ョ繝・く繧ケ繝医〒縺吶よ怙霑代・谿・←縺薙l縺ァ縺吶・縲'),
count_codePoint('ホ・ニ・ュ・ケ・ネ、ヌ、ケ。」、ス、・ハ、熙ヒハリヘ'),
count_codePoint('$l$O(Jiso-2022-jp$B$N%F%-%9%H$G$9!#(JJIS$B$H$b8@$C$?$j$7$^$9!#EE;R%a!<%'),
count_codePoint('$N%F%-%9%H$G$9!#(JJIS$B$H$b8@$C$?$j$7$^$9!#EE;R%a!<')
]
y_train = [
'en',
'ja-jp',
'shift-jis->utf-8',
'euc-jp->utf-8',
'utf-8->JIS',
'utf-8->shift-jis',
]
#学習
clf = GaussianNB()
clf.fit(x_train, y_train)
arr = [
'これはUTF-8のテキストです。最近は殆どこれですね。',
'代・谿・←縺薙l縺ァ縺吶・縲',
'Hello World',
'euc-jp、ホ・ニ・ュ・ケ・ネ、ヌ、ケ。」、ス、・ハ、熙ヒハリヘタ、テ、ソ、ホ、ヌ、゙',
'$B$N%F%-%9%H$G$9!#(JJIS$B$H'
]
for i in arr:
sub_arr = [count_codePoint(i)]
y_pred = clf.predict(sub_arr)
print(y_pred,i)[/python]
参考
http://labs.timedia.co.jp/2010/12/identifying-electronic-ghosts.html
Recommends
New Posts
Hot posts!
Date
Tags
(110)
(54)
(54)
(47)
(45)
(36)
(30)
(29)
(24)
(24)
(22)
(21)
(21)
(20)
(19)
(17)
(16)
(16)
(15)
(14)
(12)
(12)
(12)
(12)
(12)
(12)
(11)
(10)
(10)
(10)
(10)
(10)
(9)
(9)
(8)
(8)
(8)
(8)
(7)
(7)
(6)
(6)
(6)
(6)
(6)
(5)
(5)
(5)
(5)
(4)
Author