実践型AIプログラミング特講#18

実践型AIプログラミング特講#18

今回は機械学習を用いた言語の判定を行なってみようと思います。言語判定は前提としてなんの言語が使用されているのか情報がアルゴリズムに組み込まれていない場合全く動作をしません。そこで機械学習をする前処理として使用言語として何が用いられているのか事前に判定するシステムを組み込むことで情報をアルゴリズムに組み込むことなく汎用性の高いロジックの構築が可能になるはずです。皆さんもこれを機に言語判定をマスターしてみてはいかがでしょうか。

自然言語処理

機械学習を用いた自然言語処理の始めに、言語判定を行ってみましょう。

言語判定について

「言語判定」とは、与えられた文章が何語(日本語、英語など)で書かれているかを判定することです。この言語判定の技術は、さまざまなところで用いられています。たとえば、最近のブラウザーでは、訪問したWeb サイトが英語だった場合、自動的に日本語に翻訳したページを表示してくれます。その際、英語を日本語に翻訳していますという通知を表示してくれるので翻訳されたものだとわかります。

これは、表示した Web ページが英語であることを判別し、その後、翻訳機を通して英語から日本語に翻訳してくれているのです。しかし、どのようにして言語判定を行っているのでしょうか。ここでは、この言語判定を機械学習で行ってみましょう。

言語判定を機械学習で行ってみよう

言語によって使われている文字の種類が違います。文章を見て、ひらがなと漢字が使われていれば、それが「日本語」であるとわかりますし、ハングル文字が使われていれば、韓国語であることがわかります。しかし、英語とスペイン語など、同じアルファベットの文字が使われている場合は、文字の利用頻度を確認するとそこから言語を判定できます。

たとえば、英語で一番よく使われるのは「E」でもっとも使われない文字は「Z」です。以下は、英語の文章における出現頻度をグラフにしたものです。こうした出現頻度は言語によって異なることが知られています。そこで、ここでは文章を構成する文字に注目し、文章で使われている文字とその頻度から言語を判定してみましょう。

言語判定にUnicode のコードポイントを利用してみよう

Unicodeとはアルファベットしか用いられていないASCIIやシフトJISなどとは異なり様々な文字記号を含んだ非常に多種多様に飛んだ言語データになります。その代わり全て網羅しているためデータとして容量が大きいことがボトルネックになります。それでは、与えられた文章が何語かを判定する、教師あり学習の機械学習プログラムを作成してみましょう。使われている文字の違いや、文字の使用頻度を、どのように調べることができるでしょうか。ここでは、Unicode のコードポイントを利用してみましょう。

具体的には、以下の方法を用います。

・Unicode のコードポイントをアドレスとする配列を用意する。今回は0番地~65535(FFFE)番地までを使用

・配列の各要素は、対応する Unicode のコードポイントの出現回数を表すものとする。初期化時はすべて0にする

・文章中の各文字をUnicode のコードポイントに変換し、上記配列の対応するアドレスの出現回数をインクリメントする

このような配列をたくさん準備して、それぞれが何語かを学習させれば、機械学習で言語判定を行えそうですね。

アルゴリズムを選択しよう

アルゴリズムチートシートを見てみると、LinearSVC アルゴリズムでは上手に分類できない場合で、かつテキストデータの場合、NaiveBayes( ナイーブベイズ)を利用することが推奨されています。LinearSVC アルゴリズムはすでに前節で利用したことがありますので、NaiveBayes を利用してみましょう。また、scikit-learn では3種類のNaiveBayes 分類器が用意されていますが、ここではシンプルに利用できるGaussianNB を利用してみましょう。

利用されている文字が異なる言語を判定してみよう

最初に、言語判定を行う機械学習プログラムとして、利用されている文字が異なる言語を判定してみましょう。具体的には、日本語、英語、タイ語の言語判定を行うプログラムを作成します。まずは、Jupyter Notebook で新規ノートブックを作りましょう。画面右上の[New> Python3]で新規ノートブックが作成できます。そして、以下のプログラムを記述しましょう。

import numpy as np

from sklearn.naive_bayes import GaussianNB

from sklearn.metrics import accuracy_score

# Unicode のコードポイント頻度測定(* 1)

def count_codePoint (str):

# Unicode のコードポイントをアドレスとする配列を用意(* 2)

counter =np.zeros (65535)

for i in range (len(str)):

# 各文字を Unicode のコードポイントに変換(* 3)

code_point= ord(str[i])

if code_point > 65535 :

continue

# 対応するアドレスの出現回数をインクリメント(* 4)

counter [code_point] += 1

# 各要素を文字数で割って正規化(* 5)

counter = counter/len (str)

return counter

# 学習用データの準備

ja_str=’これは日本語の文章です。’

en_str = ‘ This is English Sentences.’

th_str = ‘ นี้เป็นประโยคภาษาไทย”

x_train =[count_codePoint(ja_str), count_codePoint (en_str), count_codePoint (th_str)]

y_train =[‘ja’,’en’,’th’]

# 学習する(*6)

clf = GaussianNB()

clf.fit(x_train, y_train)

# 評価用データの準備

ja_test_str=’こんにちは!’

en_test_str = ‘Hello’

th_test_str =”สวัสดี”

x_test = [count_codePoint (en_test_str),count_codePoint(th_test_str),count_

codePoint (ja_test_str)]

y_test =[‘en’, ‘th’, ‘ja’]

#評価する(* 7)

y-pred= clf.predict (x_test)

print(y_pred)

print(“正解率=”,accuracy_score(y_test, y_pred))

では、Jupyter Notebook からプログラムを実行してみましょう。Run ボタンを押すと、以下のような結果が表示されます。

[‘en’ ‘th’ ‘ja]

正解率 =1.0

正解率は実行ごとに変化しますが、ここでは 100%となっていますので、言語判定を正しく行えていると評価できるでしょう。それでは、プログラムを確認してみましょう。(※1)の部分では、Unicode のコードポイントの頻度を測定する関数を宣言しています。(※2)の部分では、Unicode のコードポイントをアドレスとする配列を用意し、初期化しています配列の初期化には、np.zeros) メソッドを利用しています。np.zeros() メソッドは、要素数を指定するとすべて0で初期化した配列を返します。(※3)の部分では、各文字を Unicodeのコードポイントに変換しています。Unicode のコードポイントへの変換は、ord0 メソッドで行うことができます。(※4)の部分では、対応するアドレスの出現回数をインクリメントしています。(※5)の部分では、各要素を文字数で割って正規化しています。(※6)の部分では、GaussianNB を利用した分類器を作成します。そして、ft() メソッドで学習用データを学習します。(※7)の部分では、評価用データを用いて予測を行い、予測結果と正解ラベルを比べて正解率を計算し、結果を画面に出力しています。これまでと同様、予測には predict()メソッド、正解率の計算には accuracy_score0 メソッドを利用しています。このように、利用されている文字が異なる言語については、機械学習によって言語判定が行えることがわかりました。

利用されている文字が同じ言語を判定してみよう

では次に、利用されている文字が同じ言語についても確認してみましょう。具体的には、ラテン文字(Latin Alphabet)を利用している、英語、スペイン語、ドイツ語の言語判定を行うプログラムを作成しましょう。利用されている文字が同じ場合、利用するデータに関して、もう少し大きいものを準備する必要があります。文字の使用頻度を、ある程度明確にする必要があるからです。ここでは、Wikipedia の各言語のデータを利用してみましょう。

具体的には、Wikipedia から収集した各言語のデータを「(言語コード)_(任意の名前)txt」で保存します。これを学習用に3つずつ(サンプルプログラムの「src/ch4/lang/train」)、評価用に1つずつ(サンプルプログラムの「src/ch4/lang/test」)の合計12個のファイルを準備しました。

まず、これらのファイルを Jupyter Notebook からアップロードしてみましょう。最初に学習用データと評価用データを配置するフォルダーを作成します。画面右上の[New> Folder]で「UntitledFolder」という名前の新規フォルダーが作成できます。その後、「Untitled Folder」を選択し、画面左上の [Rename]ボタンを押して、フォルダー名を変更します。学習用データのフォルダーは「train」、評価用データのフォルダーは「test」としましょう。

次に、学習用データと評価用データをアップロードしましょう。「train」または「test」フォルダーを開き、画面右上の(Upload] ボタンを押してファイルを選択します。その後、ファイルごとに[Upload] ボタンを押します。学習用データと評価用データがアップロードできたら、さっそく言語判定プログラムを作成してのましょう。Jupyter Notebook で新規ノートブックを作ります。フォルダーをルートに戻したのち、画面右上の[New> Python 3] で新規ノートブックが作成できます。そして、以下のプログラムを記述しましょう。

import numpy as np

from sklearn.naive_bayes import GaussianNB

from sklearn.metrics import accuracy_score

import glob

# Unicode のコードポイント頻度測定

def count_codePoint (str):

# Tnicode のコードポイントをアドレスとする配列を用意

counter = np.zeros (65535)

for i in range (len(str)):

# 各文字を Unicode のコードポイントに変換

code_point= ord(str[i])

if code_point > 65535 :

continue

# 対応するアドレスの出現回数をインクリメント

counter [code_point] += 1

# 各要素を文字数で割って正規化

counter =counter/len (str)

return counter

# 学習データの準備(* 1)

index = 0

X_train =[]

y_train=[]

for file in glob.glob(‘./train/*.txt’):

# 言語情報を取得し、ラベルに設定(*2)

y_train.append (file [8:10])

# ファイル内の文字列を連結後、Unicode のコードポイントの頻度を測定し、入力データに設定(* 3)

file_str =””

for line in open (file, ‘r’):

file_str = file_str + line

x_train.append (count_codePoint (file_str))

# 学習する

clf = GaussianNB()

clf.fit(x_train, y_train)

# 評価データの準備(*4)

index = 0

x_test =[]

y_test =[]

for file in glob.glob(‘./test/*.txt’):

# 言語情報を取得し、ラベルに設定

y_test.append (file[7:9])

# ファイル内の文字列を連結後、Unicode のコードポイントの頻度を測定し、入力データに設定

file_str = “”

for line in open (file, ‘r’):

file_str = file_str + line

x_test.append (count_codePoint (file_str))

# 評価する

У-pred= clf.predict (x_test)

print (y_pred)

print(” 正解率 = I, accuracy_score(y_test, y_pred))

では、Jupyter Notebook からプログラムを実行してみましょう。Run ボタンを押すと、以下のような結果が表示されます。

[‘es’ ‘en’ ‘de’]

正解率=1.0

正解率は実行ごとに変化しますが、ここでは 100%となっていますので、言語判定を正しく行えていると評価できるでしょう。それでは、プログラムを確認してみましょう。(※1)の部分では、学習データの最初の準備として、データの初期化後、train フォルダー配下のテキストファイルの一覧を取得しています。ファイルの一覧取得には、glob)メソッドを利用しています。(※2)の部分では、ファイル名から言語情報を取得し、ラベルに設定しています。file 変数の中身は、「/train/de_dog.txt」のようにファイルパスとなっていますので、9文字目 (0 番地から始まるので8を指定)から 10文字目までを切り取っています。(※3)の部分では、ファイル中の文字列を読み込んだ後、count_codePoint) メソッドを実行し、Unicode のコードポイントの出現頻度によりベクトル化しています。(※4)の部分では、学習データの準備時と同様の方法で、評価データの準備をしています。file 変数の中身が今後は「/test/de_lion.txt」のようになります。言語情報を取得する際、文字列の切り取りを行う位置が異なりますので、気をつけてください。このように、使用されている文字が同じ言語についても、機械学習によって言語判定が行えることがわかりました。

応用のヒント

実のところ、言語判定のプログラムを実装する機会は少ないかもしれません。しかし、Unicode のコードポイントの出現頻度を利用する手法は、他の場面に活用できます。たとえば同じ日本語でも、人によって利用する単語や文字種類の割合が異なりますので、句読点やひらがな·カタカナ·漢字の種類や出現率を数えることにより、記述者判定を行うなど、広い範囲で応用できるでしょう。

この節のまとめ

・Unicode のコードポイントの出現頻度を機械学習することにより、言語判定を行える

・言語判定には、NaiveBayes アルゴリズムを利用できる

・Uniode のコードポイントの出現頻度を機械学習する手法は、他の判定に活用できる

 

いかがでしたでしょうか、次回は文字認識の上位技術に値する単語認識について皆様にご紹介いたします。

 

プログラミングカテゴリの最新記事