今日も窓辺でプログラム今回は、前回のコードを少しだけいじって、単語レベルの言語モデルを実装します。RNNのセルも、単純なものからLSTMに切り替えてみます。やること今回やることは、前回の記事の知識を前提とします。前回の記事をまだ読んでいない方は、先にそちらに目を通していただけるとこの記事が読みやすいかもしれません。確率を出力するモデルを作成します。次のような確率がモデルの出力です。入力はn個の単語、出力は次に来る単語です。入出力の単語は語彙数の次元を持つベクトルのone-hot表現で扱います。入力層と出力層は語彙数の分だけノードが並んだ形になります。隠れ層は、LSTMのユニットの層を1層だけ用意します。詳しくは後述しますが、個数は今回は30個並べます。言語モデルというと入力層と隠れ層の中にEmbedding層を導入しているものもありますが、今回はいきなりLSTMにつないでしまいましょう。onlyの一部を使用します。(文字レベルの時と同じサイトです)今回は、少しフォーマルな内容の"newspaper_newswire"というフォルダの中にあるファイル(161KB)を使用します。実装コード全体まず、コード全体はいつものようにGitHubにあげておくので必要に応じて参照していただければと思います。GitHubコーパスから辞書を作るまずはコーパス全体を読み込み、コーパスに含まれている単語から辞書を作成します。いう未知語を意味する記号にひとまとめにしてしまいます。して扱うようにしました。私の実装は下記の通りです。この関数は大まかに3つの部分に分かれており、それぞれ(1)コーパス中の単語の出現回数をカウントする部分、(2)出現回数の低い単語をにまとめる部分、(3)辞書をファイルに保存する部分で構成されています。dictionaryモデルの定義モデル自体はも文字レベルの言語モデルを作った時と大差ありません。以前はBasicRNNCellを使用していましたが、今回はBasicLSTMCellを使ってRNNのユニットをLSTMにしています。学習させるときに入力する単語列の長さは、self.chunk_sizeで定義しており、今回は5としています。optimizer学習を回す部分モデルの定義が終わったので、次は学習を回す部分を定義します。trainという関数が学習を回している部分になります。ここの実装も前回と大きく変わってはいないかと思いますが、学習の進行度を見るためにイテレーションを回すごとにパープレキシティを計算して表示するようにしています。実際にコーパスからデータを読み込んでバッチごとに区切ったデータを用意しているのはgenerate_batchという関数です。イテレータとして実装しているので、generate_batch()に対してforループを回してあげると、コーパス全体のデータが順に得られるようになっています。学習させてみる以上で実装が終わったので、実際に学習させてみます。先述の通り、コーパスはnewspaper_newswireというフォルダのテキストを使用します。辞書の作成まずは辞書を作成します。./data/newspaper.dic出現頻度が低いものを除くと、ユニークな単語は1146個存在したようです。学習の実行いよいよ学習を走らせます。意図的にコーパスを小さめにしているので、我が家のCPUでも100エポックが30分程度?で終わりました。./data/newspaper.ckptパープレキシティも13程度まで下がり、学習がうまく進んでいる様子が確認できます。今回はTensorFlowのBasicLSTMCellというセルを使用して実装しました。この実装の問題点は、self.chunk_sizeで定義した長さの単語列を与えないとモデルからの出力が得られない点です。(私の知る限りは、ですが。何か手段があったらご教示ください。)可変長の単語列を与えようと思うと、なにやらtf.nn.dynamic_rnnなるものを使わないといけないようなのですが、これに関してはまだ詳しく調査できていません。TensorFlow今回と同じモデルをCNTKを使っても実装してみたのですが、そちらの場合は可変長の単語列も入力として使えました。一度CNTKの方の実装を紹介してから、余力があったらdynamic_rnnの使い方も調べてみようと思っています。アーカイブおすすめの本はてなブログをはじめよう!kanohkさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。