[中級編]LLMへ至る道~RNNってやつがいるらしい~[9日目]

2023.12.09

みなさんこんにちは!クルトンです。

前回は、単語を埋め込むとはどういう事かを説明し、Word2Vecを動かしていきました。

本日は、文脈を考慮した単語埋め込みをしているモデルをご紹介する前に2つのモデルをご紹介したく、その1つ目に関するブログになります。

RNNってなんだ?をイメージで掴む

RNNと書かれていますが、日本語に訳すと再帰型ニューラルネットワークといいます。ニューラルネットワークについては以前ご紹介した内容を覚えておいででしょうか? もし「忘れちゃったよ!」という方は下記ブログをご参照いただければ幸いです!

ここで気になるとすれば、再帰型の部分ではないでしょうか?ニューラルネットワークにおいて、再帰的に考慮した出力をするという意味ですが言葉だけでは伝わりづらいかもしれないので、まずはイメージずを確認していきましょう! road-to-llm-advent-calendar-2023-09-01

上の図ではhが出力で、xが入力です。xの入力はある文で単語ごとに分けたものだと想像してください。

図の矢印を確認してください。h3(3番目の出力)を確認するには、それの前の出力h2と新しい入力であるx3から計算します。そして、h2という出力は、h1という出力とx2という入力を考慮しています。

つまり、 「現在出力しようとしているもの以前の情報を考慮した出力結果が得られる」というものがRNNです。

上のような図は、順方向(前から後ろに順番)に出力結果を確認しているので、順方向RNNと呼ばれます。「順番である」という方向の話から想像できるかもしれないのですが、逆方向というものもあります。それが下の図で表しているものです。

road-to-llm-advent-calendar-2023-09-02

順方向RNNとは矢印が逆である以外の考え方は同じです。

簡単なコード例

Google Colab(ランタイムはCPU)で簡単に動かせるコード例を記載します。ご興味がある方はご確認ください。(なお、損失関数などは定義していないです。)

import torch
import torch.nn as nn

# RNNモデルの定義
class SampleRNN(nn.Module): # nn.Moduleを継承
    def __init__(self, input_size, hidden_size, output_size):
        super(SampleRNN, self).__init__() # 継承したクラスのメソッドを実行

        # モデルの各種を設定をする
        self.hidden_size = hidden_size
        self.rnn = nn.RNN(input_size, hidden_size, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        out, _ = self.rnn(x) # RNNの機構を使って出力する
        out = self.fc(out[:, -1, :]) # 出力結果をまとめる
        return out

# モデルのインスタンス化
input_size = 10  # 入力時のデータのサイズを指定(特徴量と呼ぶ)
hidden_size = 20  # 隠れ層の設定
output_size = 2  # 出力時のデータのサイズを指定
model = SampleRNN(input_size=input_size, hidden_size=hidden_size, output_size=output_size)

# ダミーデータの生成
sequence_length = 5  # 1組のデータの個数を指定
batch_size = 3  # 何組のデータを作るか指定するのに使う
# input_size個で1つとする入力データ(機械学習モデル1回の学習にあたりsequence_length個使う)をbatch_size回分ランダムな値で作成
input_data = torch.rand(batch_size, sequence_length, input_size) 

# モデルの実行
output = model(input_data)
print(f"{batch_size}個のそれぞれの出力結果:\n{output}")

RNNの長所と課題点

Word2Vecでは単語に一意な分散表現を割り当てているため、文脈を考慮できないという課題点がありました。

RNNではある単語が出てくるか推論する際に、単語の文脈も考慮するのでより適切な出力結果が得られるという長所があります。

こうして文脈を考慮できるようになりましたが、RNNには課題点があります。 それは毎回計算する事で、最初の方の出力結果でなく、直前の出力結果に依存した出力になってしまっているという事です。

つまり、入力された情報の依存関係を長期間保てないという課題点があります。 前の情報が薄れていってしまうのですね。

ここで長期間保つように考慮されたモデルが登場するのですが、こちらは明日のブログでご紹介いたします。

終わりに

本日は、単語埋め込みでの課題点の克服に一歩近づいたRNNについてご紹介し、RNNでの課題点にも簡単に触れました。

明日公開するブログでは、RNNの課題点を克服したモデルについてご紹介していきます。 自然言語処理というのはちょっとずつ改良してきた歴史なんですね。

本日はここまで。それでは、明日もよければご覧ください!