まえがき
※注意 本記事では内容をまとめきれておりません※
こんにちは
GWを活用して『ゼロから作るDeepLearning2-自然言語処理編』を読みました。
こちらの本途中まで読んだことはありますが挫折しまして、半年ぶりくらいの挑戦になりました。
なんとかコードの理解や、文面の理解をしながら無事読了に至りました。
そして、今回は自分の理解を定着させるために概要をまとめよう。。。と思いましたが途中で挫折しました。なので、もっと雑にさらって、また未来の自分にたくそうと思います。
何が壁かと言うと one-hotベクトルと分散表現が体に染み込んでいないことによる感覚的な理解のできなさと思います。
1巻の記事はこちら
今回読んだ本、参考書籍
ゼロから作るDeep Learning ❷ ―自然言語処理編
- 作者:斎藤 康毅
- 発売日: 2018/07/21
- メディア: 単行本(ソフトカバー)
雑に書くよ
1章_ニューラルネットワークの復習
1巻の復習+α
2章_自然言語と単語の分散表現
自然言語処理の3種類のアプローチの紹介、本書のメインは推論ベース
- シソーラスによる手法
- カウントベースの手法
- 推論ベースの手法(word2vec)
3章_word2vec
from word to vector っていう意味です。
"推論"ということなので、ニューラルネットワーク、誤差をもとに学習します。
word2vecには2つのモデルが有る。(G検定でも出るよ)
- CBOWモデル (周りの単語から、間の単語を推測する。)
- skip-gramモデル(一つの単語から周りの単語を予測する)
精度:CBOW < skip-gram
学習速度:CBOW > skip-gram(コンテキストの数だけ損失を求めるから)
4章_word2vecの高速化
Embeddingレイヤの導入
one-hotベクトルと重み行列の内積は、重み行列から特定行を抜き出すことと同等なので、そっちに変える。
多値分類→2値分類
中間層以降の計算の多さを改善をする。
教師データを使用することで、多値分類から、教師データであるかどうかの2値分類にする。
あとはCNNのとき同様、誤差を計算して、逆伝播していく。
NegativeSampling
あえて不正解であるデータをサンプリングし、ちゃんと違うと言えるように学習していく。
そのとき、コーパス内の単語の出現頻度に応じたサンプリングをする。
5章_リカレントニューラルネットワーク(RNN)
再帰構造が含まれてるニューラルネットワーク
最木構造とは、前の時系列の出力を次の時刻の入力データとしても使用する構造
誤差逆伝播法を適用することが出来る。「時間方向に展開したニューラルネットワークの誤差逆伝播法」をBPTTと呼ぶ
Truncated BPTT
順方向はそのままで、逆伝播を適当な長さで"断ち切る"というアイデア
あまりにも長い逆伝播をしようとすると、メモリの使用量の増加や、勾配の消失が起こる事がある
ミニバッチ実施可
実装
長さTの時系列データをちょりする "ITime RNN"レイヤの実装を行う
RNNをつかった言語モデルは、単語の羅列を確率として解釈。
6章_ゲート付きRNN
ただ再帰構造を追加しただけのネットワークでは、勾配消失や勾配爆発が発生するため、長期時系列データに使用できないため、現実的に利用はできない。
勾配爆発への対策
勾配消失への対策
下記2つのゲートにより対策
- LSTM
- GRU
LSTMゲートの実装
LSTMには記憶セルCがある。記憶セルには時刻tでのLSTMの記憶が格納されている。(過去の情報も
この記憶セルをtanh関数によって変換したもの(隠れ状態hと呼ぶ)を次の時刻のLSTMへ出力する
LSTMでは下記のゲートと計算で出力値を作成する。
- アウトプットゲート
tanhの出力をどれだけ通すか決める - forgetゲート
記憶セルから不要のものを取り除く - 新しい記憶の追加
tanhノードを使用して新しい情報を記憶セルに追加するデータを作成する - inputゲート
追加するデータに重み付けをし、取捨選択をする。
このあたりから私は字面での理解はできても実際文章が、単語ベクトルがどうなっているかわからなくなりました。分散表現ベースで新しい記憶を追加したり、いらない記憶を消してるのでしょうがなんとも難しい...
あとはこれをまとめてできるレイヤーの作成、評価をします。
RNNLMの改善
LSTMレイヤの多層化をすることで高精度なモデルを作成することが可能だが、過学習を起こしやすくなるので、Dropoutによる対応が必要。
このDropoutをどこに入れるか、ランダム性や共通したマスクを使用すると良い等、色々研究がなされているとのこと
重み共有というテクニックもあるという、RNNの改善は発想の大切さがすごい気がしてきます。
7章_RNNによる文章作成
単語を予測できるモデルを作ったら次は、一定量の文章を与えたら続く文章を作成できるのでは?っていう考えのもと文章作成をする。
seq2seq
ここで、入力データの反転(Reverse)や、覗き見(Peeky)をすると精度が上がる。
覗き見では、エンコーダからの入力をデコーダの全時系列にも入力させること。
8章_Attention
はいきました現役戦士
seq2seqではエンコーダの最後の時系列の隠れ状態をデコーダに入力していたが、各時刻の隠れ状態を結合して作成した行列をデコーダに出力するように変更。
正直人に説明出来るほどAttentionを理解できてないですが、現役の技術なので解説記事がたくさんあります。
Attentionでは、必要な情報だけに注意が向くようにする仕組みで、そうすることでより高精度な文語生成モデルが作れるということみたいです。すみませんほんとにすみません頭がついていかないです。
最後に
自然言語処理のモデル、技術の発展をまとめている記事がありますので紹介します。
挫折した内容
以下、頑張ってまとめようとして挫折するまでにメモった内容。供養ということでおいておきます。
1章_ニューラルネットワークの復習
1巻の復習プラスα
※CNNでなく計算グラフとかpythonでの行列の扱いの部分
1巻には明記されてませんでしたが、こちらでは1エポックの扱いが全データ1回ずつ見るようなコードに変わってました。
2章_自然言語と単語の分散表現
自然言語
普段人間が使用している言葉
→自然言語処理:自然言語をコンピュータに理解させるための技術
自然言語を意味の最小単位である単語に分解して、単語の意味を理解させる。本書で扱うアプローチは下記の3種
- シソーラスによる手法
- カウントベースの手法
- 推論ベースの手法(word2vec)
シソーラスによる手法
シソーラスとは、類語辞書。上位と下位、全体と部分などの関係が定義されている。
しかし、下記のような問題点があるため運用は現実的でない
- メンテナンスコストが高い。
- 単語の細かなニュアンスが表現できない
カウントベースの手法
コーパスを使って「単語の意味」を抽出する。
※コーパス:自然言語処理の研究などために目的をもって収集された大量のテキストデータ
コンテキストの単語の共起行列を作ることで単語をベクトルで表現する。(分散表現の獲得)
大規模なコーパスを作成する場合計算コストがかかりすぎてしまうので現実的ではない。 ※計算量はO(n3)
分散表現
「色」をより正確に伝えるためには色の名前よりも、RGB値で伝えるほうが確実。
色は3次元ベクトルで表現できる。
自然言語処理においても「単語の意味」をより的確に捉えたベクトル表現を目指す。このことを単語の分散表現という
コンテキスト
ある中央の単語に対して、その周囲にある単語を指す。
「単語の意味は、周囲の単語によって形成される」というアイデアのもとでは重要になる。
共起行列
コーパス内のそれぞれの語彙に対してそのコンテキストに含まれる単語の集計を行いベクトルで表現。
より良い共起行列を作るための工夫
- ただ集計を行うだけだと出現回数からの影響が強いため、相互情報量(PMI)という指標を使う(適用したものをPPMI行列と呼ぶ)。
- PPMI行列は0が多い疎の状態なので次元削減を行う
ベクトル間の類似度
コサイン類似度
- 2つのベクトルがどれだけ同じ方向を向いているか
- -1から1
3章_word2vec
ここからは「推論ベースの手法」
ニューラルネットワークを用いて推論を行う。つまり層を深くすることでDeepLearningになる。
推論ベースの推論とは
コンテキストが与えられたときに中心の単語が何かを推測する。
単語を one-hotベクトル で表す。("you"や"me"という文字の意味を理解するのではない)
補足
■コーパスを " You say goodbye and I say hello . "とする。語彙は7となるので7つの要素になる。
one-hotベクトルで "say"を表すと(0, 1, 0, 0, 0, 0, 0)となる。
one-hotベクトルと重みの内積を取るということは重みの特定の行ベクトルを抜き出すとみなすことが出来るため、実装上ではない席でなく抽出をスようようにすることで計算量の削減ができる。
CBOWモデル
CBOW(continuous bag-of-words)というモデルを使ってword2vecを作成
入力層はコンテキスト数の数だけある。重みは同じものを使う
skip-gramモデル-word2vecの2つ目のモデル
精度:CBOW < skip-gram
学習速度:CBOW > skip-gram(コンテキストの数だけ損失を求めるから)