最近の自然言語処理では、文字レベルの言語処理が行われることがあります。 これら文字レベルの言語処理は、ユーザ生成コンテンツに有効であると言われています。 その理由として、ユーザ生成コンテンツのような崩れたテキストでは、形態素解析の性能が大幅に低下し、単語レベルの処理が上手くいかなくなることが挙げられています。
文字レベルの言語処理を行うなら、単語レベルの場合と同じく文字分散表現を事前学習したくなります。 文字分散表現を事前学習しておくことで、①良い文字ベクトルの初期値を得られる、②学習データに現れない文字のベクトルを教師なしで得られる、といった恩恵を受けられます。
本記事では、日本語の文字に対して文字分散表現を学習してみます。 本文は次の2つの内容で構成されています。
- 学習データの準備
- 文字分散表現の学習
学習データの準備
まずは、文字分散表現の学習に用いるデータを用意します。 以前、以下の記事で単語分散表現を学習するためのコーパスを作成したことがありました。 今回は、そのコーパスを文字分散表現の学習用に変換して使うことにしましょう。
はじめに、コーパスのダウンロードと解凍を行います。
wget
を用いてコーパスをダウンロードし、unzip
でファイルを解凍しましょう。
ファイルを解凍すると、ja.text8
という名前のコーパスが現れます。
$ wget https://s3-ap-northeast-1.amazonaws.com/dev.tech-sketch.jp/chakki/public/ja.text8.zip $ unzip ja.text8.zip
次に、単語単位で区切られているja.text8
を文字単位に区切りましょう。
文字単位で空白に区切っておくことで、コーパスの読み込みが簡単にできるようになります。
以下のスクリプトを書いて、文字単位の区切りに変換しましょう。
with open('ja.text8') as f: text = f.read() chars = [c for c in text if c != ' '] with open('ja.char8', 'w') as f: f.write(' '.join(chars))
上記のスクリプトを実行することで、文字単位に区切られたコーパスja.char8
が生成されます。
ja.char8
の中身をみると、以下のように空白を区切り文字として、文字単位に区切られていることがわかります。
ち ょ ん 掛 け ( ち ょ ん が け 、 丁 斧 掛 け ・ 手 斧 掛 け と も 表 記 ) と は 、 相 撲 の 決 ま り 手 の ひ と つ で あ る 。 自 分 の 右 ( 左 ) 足 の 踵 を 相 手 の 右 ( 左 ) 足 の 踵 に 掛 \ け 、 後 方 に 捻 っ て 倒 す 技 。 ...
学習用のデータが用意できたので、文字分散表現を学習しましょう。
文字分散表現の学習
作成したコーパスとgensim
のword2vec
を使って文字分散表現を学習させてみます。
ja.char8
と同じディレクトリで、以下のコードを実行して学習させましょう。
文字分散表現の学習は数分で終わるはずです。
import logging from gensim.models import word2vec logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) sentences = word2vec.Text8Corpus('ja.char8') model = word2vec.Word2Vec(sentences, size=50, window=50, workers=4)
今回はハイパーパラメータとして、文字分散表現の次元数を50
、windowサイズを50
にしています。
次元数が比較的低次元なのは、文字は単語と比べて語彙数が少ないため、次元数を大きくする必要がないからです。
また、windowサイズを広めに取ったのは、トピックの近い文字が空間上で近くなるように学習させる意図があります。
学習が終わったら、実際に試してみます。
>>> model.most_similar(["膝"]) [('肘', 0.835448145866394), ('腱', 0.7766674160957336), ('蹴', 0.7529205083847046), ('腕', 0.7077324986457825), ('靱', 0.7001078128814697), ('腰', 0.697993278503418), ('踵', 0.685279369354248), ('痛', 0.6709409952163696), ('折', 0.6706937551498413), ('肩', 0.6704100370407104)] >>> model.most_similar(["猫"]) [('犬', 0.7227709293365479), ('羊', 0.6398827433586121), ('昔', 0.6368851661682129), ('妖', 0.6360131502151489), ('裸', 0.6287463903427124), ('匂', 0.6252028346061707), ('鳥', 0.6074063181877136), ('蛇', 0.6036850810050964), ('禽', 0.5951928496360779), ('猿', 0.5902674198150635)]
うん、意図したとおりトピックの近い文字が空間上で近くなるように学習されたようですね。
おわりに
本記事では日本語のコーパス(ja.text8)を用いて文字分散表現の学習を行いました。 学習の際、windowサイズを広く取ることで、トピックの近い文字が空間上で近くなることが確認できました。 本記事が皆様のお役に立てば幸いです。
私のTwitterアカウントでも機械学習や自然言語処理に関する情報をつぶやいています。
この分野にご興味のある方のフォローをお待ちしています。