AIって結局何なのかよく分からないので、とりあえず100日間勉強してみた Day89
経緯についてはこちらをご参照ください。
■本日の進捗
- RNNの実装を理解
■はじめに
今回も「ゼロから作るDeep Learning② 自然言語処理編(オライリー・ジャパン)」から学んでいきます。
今回は、これまで用意してきた時系列データに対応した層を用いて、再帰型ニューラルネットワークを実装していきます。
■言語モデル
これから言語モデルの実現を目指して再帰型ニューラルネットワークを実装していきます。
そもそも言語モデル(Language Model)とは、近年話題性のあるGPTなどで知られる大規模言語モデル(Large Language Model:LLM)の一種で、単語やフレーズを分散表現に展開して意味を捉え、確率分布で学習する自然言語処理モデルとして用いられます。
単語の予測を行い類似性や意味的な解析に用いてきたCBoWやSkipGramなどの埋め込みで学習してきたモデルと違い、文章の生成などいわゆる生成AIを構成する手法です。
再帰型ニューラルネットワークはこのような言語モデルに利用されていることが知られています。
■RNNを用いた言語モデル
それではこれまで構築してきた層を用いて再帰型ニューラルネットワークを実装していきます。
再帰型ニューラルネットワークを用いた言語モデルでは、入力を単語埋め込みに変換し、RNNで時系列データを処理してソフトマックスによって単語の確率分布を予測します。
まずは、語彙数(V)、埋め込みの次元数(D)、隠れ状態の次元数(H)を引数として受け取り初期化を行います。
class SimpleRnnlm: def __init__(self, vocab_size, wordvec_size, hidden_size): V, D, H = vocab_size, wordvec_size, hidden_size rn = np.random.randn
続いて重みを初期化していきます。(括弧内は形状)
●embed_W
単語埋め込み層の重み
(語彙数×埋め込み次元数)
●rnn_Wx
入力からRNNへの重み
(埋め込み次元数×隠れ状態次元数)
●rnn_Wh
隠れ状態から次の隠れ状態への重み
(隠れ状態次元数×隠れ状態次元数)
●rnn_b
RNNでのバイアス
(隠れ状態次元数)
●affine_W
全結合層での重み
(隠れ状態次元数×語彙数)
●affine_b
全結合層でのバイアス
(語彙数)
embed_W = (rn(V, D) / 100).astype('f') rnn_Wx = (rn(D, H) / np.sqrt(D)).astype('f') rnn_Wh = (rn(H, H) / np.sqrt(H)).astype('f') rnn_b = np.zeros(H).astype('f') affine_W = (rn(H, V) / np.sqrt(H)).astype('f') affine_b = np.zeros(V).astype('f')
(入力層を除いた)1層目にEmbedding層を、2層目にRNN層を、3層目に全結合層をそれぞれ時系列データに適応した形で層を生成します。ここで、RNN層ではタイムステップ毎に隠れ状態を保持し、全結合層で出力を語彙数に変換します。
学習のために出力層にソフトマックスと損失関数を設定します。
self.layers = [ TimeEmbedding(embed_W), TimeRNN(rnn_Wx, rnn_Wh, rnn_b, stateful=True), TimeAffine(affine_W, affine_b) ] self.loss_layer = TimeSoftmaxWithLoss() self.rnn_layer = self.layers[1]
最後にパラメータと勾配を初期化しておきます。
self.params, self.grads = [], [] for layer in self.layers: self.params += layer.params self.grads += layer.grads
順伝播では各層のforward関数を実行し、入力データ(xs)と正解ラベル(ts)を引数として損失を計算します。
def forward(self, xs, ts): for layer in self.layers: xs = layer.forward(xs) loss = self.loss_layer.forward(xs, ts) return loss
逆伝播では出力層から逆順に各層のbackward関数を実行していき勾配を伝播させます。
def backward(self, dout=1): dout = self.loss_layer.backward(dout) for layer in reversed(self.layers): dout = layer.backward(dout) return dout
最後にミニバッチ学習においてバッチ間で隠れ状態をリセットする必要がある場合にRNNの隠れ状態を初期化できるような関数を用意しておきます。
def reset_state(self): self.rnn_layer.reset_state()
■おわりに
今回は言語モデルを学び、これまで実装してきたクラスを用いて言語モデルにも用いられる再帰型ニューラルネットワークを実装しました。
ようやく生成AIに片足を突っ込むところまで来ましたが、まだまだ学習ループを実装できていないので、明日はこのモデルを用いた学習過程を構築していきたいと思います。
■参考文献
- Andreas C. Muller, Sarah Guido. Pythonではじめる機械学習. 中田 秀基 訳. オライリー・ジャパン. 2017. 392p.
- 斎藤 康毅. ゼロから作るDeep Learning Pythonで学ぶディープラーニングの理論と実装. オライリー・ジャパン. 2016. 320p.
- 斎藤 康毅. ゼロから作るDeep Learning② 自然言語処理編. オライリー・ジャパン. 2018. 432p.
- ChatGPT. 4o mini. OpenAI. 2024. https://chatgpt.com/
- API Reference. scikit-learn.org. https://scikit-learn.org/stable/api/index.html
- PyTorch documentation. pytorch.org. https://pytorch.org/docs/stable/index.html
- Keiron O’Shea, Ryan Nash. An Introduction to Convolutional Neural Networks. https://ar5iv.labs.arxiv.org/html/1511.08458
- API Reference. scipy.org. 2024. https://docs.scipy.org/doc/scipy/reference/index.html