20
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

表記ゆれ対策を力業で実装

Posted at

はじめに

表記ゆれとは、「どらねこ」「どら猫」「ドラネコ」のような、読み方も意味も同じながら、書き方が異なっているものを指します。文書の中にこの表記ゆれが混ざっていると、例えば単語の頻度を調べた際に値が分散してしまうので、どれか1つの表記に統一することが望ましいです。とはいえ、この処理が非常に難しい。strrepという、文字列置換の関数はあるのですが、1単語1単語手入力なんてできないので、良い方法がないかなと考えておりました。

今回の表記ゆれ対策手法

今回neologd-solr-elasticsearch-synonyms : Elasticsearch と Solr 用の日本語名詞のシノニムファイルなるものを利用させていただきました。

このシノニムファイルは mecab-ipadic-NEologd と共通な大量の名詞の表記ゆれ文字列を含んでいます。
もしも名詞や新語、固有表現のシノニム(同義語)を定義したいと思った場合は、まずこのシノニムファイルを試すのがベターな選択のひとつです。

今回、力業で実装したと書きました。本当は、Pythonが使えればneologdnというテキストの初期化関数があります。しかしながら、私はPythonを使いこなせないので、MATLABベースで自力で表記ゆれ対策のコードを書き進めました。これが力業の所以です。次からのセクションで、実際の進め方やコードも公開します。たたき台になれば...というレベルなので、改善策あればコメント頂けたら幸いです。

やったこと

「どら猫とどらねことドラネコ」→「どら猫とどら猫とどら猫」に変換できる関数を作る。

環境

MATLAB R2020a
Text Analytics Toolbox
neologd-solr-elasticsearch-synonyms

手順

1.シノニムファイルをダウンロード

neologd-solr-elasticsearch-synonyms : Elasticsearch と Solr 用の日本語名詞のシノニムファイルからダウンロードします。
image.png

2.シノニムファイルの解凍

archiveフォルダの中にneologd-synonyms.20160323.txt.xzというファイルがあるので、解凍しておきます。
image.png
ちなみにシノニムファイルを開くとこんな感じになっています。
image.png

筆者の理解では、1列目が正規表現で、2列目以降がシノニムの認識です。ということで、2列目以降の表記を見つけたら、1列目の書き方にしてあげるスクリプトを書いていきたいと思います。

3.シノニムファイルをMATLABに読み込む

まず、シノニムファイルをMATLABに読み込みます。

synonymtable = readtable('neologd-synonyms.20160323.txt');

最初の10行を表示させてみましょう。「,」で区切られた単語が各列に格納されていることがわかります。

head(synonymtable,10)
x_____ x______1 Var3 Var4 Var5 Var6 Var7 Var8 Var9 Var10 Var11 Var12 Var13 Var14 Var15 Var16 Var17 Var18 Var19 Var20 Var21 Var22 Var23 Var24 Var25 Var26 Var27 Var28 Var29 Var30
1 'あいの子' 'アイノ子' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''
2 'あいまい度' 'あいまいど' 'アイマイド' 'アイマイ度' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''
3 'あい路' 'アイ路' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''
4 'あおか' 'アオカ' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''
5 'あお向け' 'あお向' 'アオ向' 'アオ向ケ' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''
6 'あかまんま' 'アカマンマ' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''
7 'あかんべえ' 'アカンベエ' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''
8 'あきい' 'アキイ' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''
9 'あきず' 'アキズ' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''
10 'あきらめ' 'アキラメ' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''

後々使えるように型を変換しておきます。

synonymtable = table2array(synonymtable);

4.NEologdのユーザー辞書を使ってトークン化

次に、解析したい文書と、NEologdのユーザー辞書を用意します。MATLAB上でのNEologdの使い方は前回の記事でまとめました。

str = ["どら猫とどらねことドラネコ"];
userdic = 'NEologd.20200315.dic';
mOptions = mecabOptions('UserModel', userdic);

ユーザー辞書を使ってトークン化を行います。トークン化された結果を表示させてみましょう。

documents = tokenizedDocument(str,"TokenizeMethod",mOptions);
td = tokenDetails(documents)
Token DocumentNumber LineNumber Type Language PartOfSpeech Lemma Entity
1 "どら猫" 1 1 letters ja noun "どら猫" non-entity
2 "と" 1 1 letters ja coord-conjunction "と" non-entity
3 "どらねこ" 1 1 letters ja "どらねこ"
4 "と" 1 1 letters ja coord-conjunction "と" non-entity
5 "ドラネコ" 1 1 letters ja proper-noun "ドラネコ" organization

5.シノニムファイルを用いて表記ゆれを修正

続いて、トークン化されたテキストに対して、表記ゆれの修正を行っていきます。最初に読み込んだシノニムファイルを使って、2列目以降のトークンが出てきた場合に1列目のトークンに変換します。

for ii = 1:height(td)
    idx = synonymtable == table2array(td(ii,1));
    if sum(idx(:)) == 1
        updateddoc{ii} = synonymtable(logical(sum(idx,2)),1);
    else
        updateddoc{ii} = cellstr(table2array(td(ii,1)));
    end
end

表記ゆれを修正した文書を表示させてみます。

updateddocument = cell2table(updateddoc')
Var1
1 'どら猫'
2 'と'
3 'どら猫'
4 'と'
5 'どら猫'

うまく表記ゆれが修正されていることがわかりますので、updateddocを使ってテキスト解析ができそうです。

mOptions = mecabOptions('UserModel', userdic);
str = erase(strjoin(string(updateddoc)),' ')

updatedocをstring型に戻します。

str = "どら猫とどら猫とどら猫"

このstringを基に、いつも通りの解析を進めることができます。

documents = tokenizedDocument(str,"TokenizeMethod",mOptions);
td = tokenDetails(documents)
Token DocumentNumber LineNumber Type Language PartOfSpeech Lemma Entity
1 "どら猫" 1 1 letters ja noun "どら猫" non-entity
2 "と" 1 1 letters ja coord-conjunction "と" non-entity
3 "どら猫" 1 1 letters ja noun "どら猫" non-entity
4 "と" 1 1 letters ja coord-conjunction "と" non-entity
5 "どら猫" 1 1 letters ja noun "どら猫" non-entity

考察

実はちょっと問題があります。
「どら猫とどらねことドラネコとドラ猫」だとうまくいきません。

image.png

上記を見る限り、シノニムファイルには「ドラ猫」は存在します。しかしながら、ユーザー辞書に「ドラ猫」が登録されていない模様で(ちゃんと確認はしていませんが、下記の結果を見ると「ドラ猫」は「ドラ」と「猫」に分かれます)「ドラ猫」というトークンに分かれないのが原因だと思われます。

str = ["どら猫とどらねことドラネコとドラ猫"];
userdic = 'NEologd.20200315.dic';
mOptions = mecabOptions('UserModel', userdic);
documents = tokenizedDocument(str,"TokenizeMethod",mOptions);
td = tokenDetails(documents)
Token DocumentNumber LineNumber Type Language PartOfSpeech Lemma Entity
1 "どら猫" 1 1 letters ja noun "どら猫" non-entity
2 "と" 1 1 letters ja coord-conjunction "と" non-entity
3 "どらねこ" 1 1 letters ja "どらねこ"
4 "と" 1 1 letters ja coord-conjunction "と" non-entity
5 "ドラネコ" 1 1 letters ja noun "ドラネコ" non-entity
6 "と" 1 1 letters ja coord-conjunction "と" non-entity
7 "ドラ" 1 1 letters ja "DORA"
8 "猫" 1 1 letters ja noun "猫" non-entity

結果だけ載せるとこんな感じです。

str = 

    "どら猫とどら猫とどら猫とドラ猫"

ということで、ここがクリアされれば尚良いのでしょうが、今の所性能はもう一息という感じです。

20
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?