AIって結局何なのかよく分からないので、とりあえず100日間勉強してみた Day93
経緯についてはこちらをご参照ください。
■本日の進捗
- LSTMを用いた言語モデルの実装
■はじめに
今回も「ゼロから作るDeep Learning② 自然言語処理編(オライリー・ジャパン)」から学んでいきます。
今回は、前回実装した時系列処理に対応したLSTM層を用いて言語モデルを理解していきます。
■LSTM言語モデル
早速これまで実装してきた時系列処理に対応した各層を用いた言語モデルを理解していきたいと思います。
まずは、語彙数(vocab_size)、単語埋め込みベクトルの次元数(wordvec_size)、LSTM隠れ層の数(hidden_size)を引数として受け取ります。
class Rnnlm: def __init__(self, vocab_size=10000, wordvec_size=100, hidden_size=100): V, D, H = vocab_size, wordvec_size, hidden_size
次にEmbedding層、LSTM層、全結合層で用いる重みとバイアスをそれぞれ初期化していきます。ここでこれらの重みは全てastype(‘f’)により32ビット型に変換されていることに注意してください。これはもちろんメモリ消費を低減する効果があります。
各重みの形状は基本RNNの場合と同様ですが、LSTM層においては1回のタイムステップで行う3つのゲートと入力の計算をまとめて行えるように4倍のサイズに定義されています。
rn = np.random.randn embed_W = (rn(V, D) / 100).astype('f') lstm_Wx = (rn(D, 4 * H) / np.sqrt(D)).astype('f') lstm_Wh = (rn(H, 4 * H) / np.sqrt(H)).astype('f') lstm_b = np.zeros(4 * H).astype('f') affine_W = (rn(H, V) / np.sqrt(H)).astype('f') affine_b = np.zeros(V).astype('f')
今回用いる層を定義します。再帰型ニューラルネットワークでの言語モデルの時と同様に、単語埋め込み層、LSTM層、全結合層、ソフトマックス、交差エントロピー誤差という並びで構成します。
self.layers = [ TimeEmbedding(embed_W), TimeLSTM(lstm_Wx, lstm_Wh, lstm_b, stateful=True), TimeAffine(affine_W, affine_b) ] self.loss_layer = TimeSoftmaxWithLoss() self.lstm_layer = self.layers[1]
最後に重みと勾配をリストにまとめたら初期化は終了です。
self.params, self.grads = [], [] for layer in self.layers: self.params += layer.params self.grads += layer.grads
今回はこれまで順伝播としてまとめて行っていた処理を、順伝播を実行するpredictメソッドと損失を求めるforwardメソッドに分解しています。
これは学習において行う損失誤差の計算が、学習後の重みを用いて行う推論時には不要になるためです。(つまり推論を見越した実装ということです。)
def predict(self, xs): for layer in self.layers: xs = layer.forward(xs) return xs def forward(self, xs, ts): score = self.predict(xs) loss = self.loss_layer.forward(score, ts) return loss
逆伝播の場合は、学習時にしか行わないのでこれまでと同様の実装になります。各層の逆伝播を層の定義と逆順で実行して勾配を求めていきます。
def backward(self, dout=1): dout = self.loss_layer.backward(dout) for layer in reversed(self.layers): dout = layer.backward(dout) return dout
LSTM内部のる隠れ状態やセル状態をリセットするためのメソッドを定義しておきます。
def reset_state(self): self.lstm_layer.reset_state()
学習した結果を保存したり再利用できるようにI/Oメソッドを追加します。
def save_params(self, file_name='Rnnlm.pkl'): with open(file_name, 'wb') as f: pickle.dump(self.params, f) def load_params(self, file_name='Rnnlm.pkl'): with open(file_name, 'rb') as f: self.params = pickle.load(f)
■おわりに
少々簡単ではありますが、今回はここまでとさせてください。明日はいい加減に(いや、ようやく?)学習させていきたいと思います。
■参考文献
- 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