Linear SVCによる言語判定 - 頻出単語を特徴量に使う
scikit-learnは機械学習用ライブラリで以下のアルゴリズムが使用できます。
- classification(識別:教師あり学習)
- clustering(分類:教師なし学習)
- regression(回帰:教師あり学習)
- dimensionality reduction(次元削減,主成分分析:教師なし学習)
classificationアルゴリズムの一つ、Linear Support Vector Classificationを用いた言語判定器を作ります。線形の境界を引いて識別する手法です。
英語では'the'が最も使用頻度が高いのですが、登場頻度の高い単語(頻出単語)が言語によって違うだろうと考え、その出現頻度を特徴量として機械学習させ言語判定します。手順は
- 学習用データとして6つの言語のテキストファイルを作り、それぞれの頻出単語(ベスト5)を調べる
- 全言語の頻出単語リストを特徴量リストとする
- 学習用データを4分割して特徴量リストの出現頻度を調べ特徴量とする
- 分類器(Linear SVC)による言語判定
環境
- windows10 home
- Anaconda 3/ jupyter notebook 5.6.0
- Python 3.7.0
- scikit-learn 0.19.2
準備
ドイツ語、英語、フランス語、インドネシア語、イタリア語、マレーシア語のニュースサイトなどから複数の記事をコピーペーストして4000語程度のテキストファイルを作り、フォルダlanguage内に保存します(例、Deutsch.txt)。また、テスト用データとして数100語程度のテキストファイルを作り、同様にフォルダlanguage内に保存します(例、Deutsch_test.txt)。
コード
#モジュールのインポート import collections from sklearn import svm, metrics #各言語のテキストファイルから頻出単語を抽出 words_n = 5 feature_words =[] language_list=['Deutsch','English','French','Indonesian','Italian','Malay'] print('■■各言語の頻出単語■■') for language in language_list: file_name = 'languages/'+language+'.txt' with open(file_name,mode='r',encoding = 'utf-8-sig') as f: read_text = f.read() word_list=read_text.split() c = collections.Counter(word_list) for i in range(words_n): feature_words.append(c.most_common(words_n)[i][0]) for language,i in zip(language_list,range(len(language_list))): print(language,feature_words[i*words_n:(i+1)*words_n]) feature_words_unique = list(set(feature_words)) print('■■重複する単語を除いたリスト■■') print(feature_words_unique) #学習用データ作成 label=[] data_set_matrix=[] for language in language_list: file_name = 'languages/'+language+'.txt' with open(file_name,mode='r',encoding = 'utf-8-sig') as f: read_text = f.read() word_list=read_text.split() data_size=int(len(word_list)/4) for i in range(4): label.append(language) data_set = [] for feature_word in feature_words_unique: counter = word_list[i*data_size:(i+1)*data_size].count(feature_word)/data_size data_set.append(counter) data_set_matrix.append(data_set) #機械学習 clf = svm.SVC() clf.fit(data_set_matrix,label) print('■■学習データを使って検証■■') predict = clf.predict(data_set_matrix) score = metrics.accuracy_score(label,predict) print('<正解>') print(label) print('<予測>') print(predict) print('<正解率>') print(score) print('■■テスト用データを使って検証■■') label_test=[] test_data_set=[] for language in language_list: file_name = 'languages/'+language+'_test.txt' with open(file_name,mode='r',encoding = 'utf-8-sig') as f: read_text = f.read() word_list=read_text.split() label_test.append(language) data_set=[] for feature_word in feature_words_unique: counter = word_list.count(feature_word)/len(word_list) data_set.append(counter) test_data_set.append(data_set) predict = clf.predict(test_data_set) score = metrics.accuracy_score(label_test,predict) print('<正解>') print(label_test) print('<予測>') print(predict) print('<正解率>') print(score)
実行結果
6言語から各5個、計30個の頻出単語が抽出され、そこから重複する単語(la,yang,dan,di)をそれぞれ重複分に減らし、24個の頻出単語リストができました。(これを特徴量に使います)
24個の学習用データを使った場合、1個不正解で正解率は0.958となりました。マレーシア語をインドネシア語に間違えています。
また、テスト用データを用いた場合にもマレーシア語をインドネシア語に間違えて正解率は0.833となりました。
■■各言語の頻出単語■■
Deutsch ['die', 'der', 'und', 'in', 'zu']
English ['the', 'to', 'and', 'of', 'a']
French ['de', 'la', 'à', 'le', 'les']
Indonesian ['yang', 'dan', 'di', 'untuk', 'dengan']
Italian ['di', 'e', 'la', 'a', 'il']
Malay ['dan', 'yang', 'di', 'kepada', 'ini']
■■重複する単語を除いたリスト■■
['zu', 'a', 'e', 'yang', 'the', 'les', 'le', 'la', 'dan', 'di', 'of', 'dengan', 'ini', 'die', 'untuk', 'and', 'de', 'der', 'il', 'à', 'to', 'in', 'kepada', 'und']
■■学習データを使って検証■■
<正解>
['Deutsch', 'Deutsch', 'Deutsch', 'Deutsch', 'English', 'English', 'English', 'English', 'French', 'French', 'French', 'French', 'Indonesian', 'Indonesian', 'Indonesian', 'Indonesian', 'Italian', 'Italian', 'Italian', 'Italian', 'Malay', 'Malay', 'Malay', 'Malay']
<予測>
['Deutsch' 'Deutsch' 'Deutsch' 'Deutsch' 'English' 'English' 'English' 'English' 'French' 'French' 'French' 'French' 'Indonesian' 'Indonesian' 'Indonesian' 'Indonesian' 'Italian' 'Italian' 'Italian' 'Italian' 'Indonesian' 'Malay' 'Malay' 'Malay']
<正解率>
0.9583333333333334
■■テスト用データを使って検証■■
<正解>
['Deutsch', 'English', 'French', 'Indonesian', 'Italian', 'Malay']
<予測>
['Deutsch' 'English' 'French' 'Indonesian' 'Italian' 'Indonesian']
<正解率>
0.8333333333333334
以下のサイトを参考にさせていただきました
scikit-learn >> Choosing the right estimator
scikit-learn >> 1.4. Support Vector Machines
scikit-learn >> sklearn.svm.LinearSVC
ウエディングパーク Tech Blog >> 【機械学習入門|Python|scikit-learn】結局何ができる?cheat-sheetから解説してみる篇