【ディープラーニングの基本】RNN,LSTMの特徴を簡単に説明|Pytorchでサンプル実装

【ディープラーニング】RNN,LSTMの特徴|Pytorchでサンプル実装 機械学習
【ディープラーニング】RNN,LSTMの特徴|Pytorchでサンプル実装
スポンサーリンク

こんにちは、こがたです。

ディープラーニングは過去のデータより将来を予測することができます。

この記事ではディープラーニングの中でも時系列から予測するRNN,LSTMを説明します。

対象者
  • ディープラーニング初心者
  • RNN/LSTMの概要を知りたい
  • 実装コードで学習したい
  • ディープラーニングの学習方法を知りたい

初めにRNN,LSTMについて技術者でなくてもわかるように説明します
一般的なディープラーニングとの違いを解説するので時系列で予測する仕組みについて理解してもらえたら嬉しいです。

次にPytorchでRNNを用いてコサイン関数にノイズを当てたものを学習させていきます。
数十行のコードで実装することができるので、難しいものと思わずにチャレンジしてみてください。

最後にディープラーニングの学習方法について紹介します。

RNN・LSTMの説明

RNN,LSTMはディープラーニングの手法の1つで、時系列から予測していくものになります。

まずは簡単にディープラーニングそのものについて説明します。

ディープラーニングの基本

ディープラーニングの基本は入力値(x)を中間層(複数のフィルタのようなもの)を通して出力値を割り出します。

出力値と正解値を比べて中間層を更新していきます。

ディープラーニングの詳細は↓↓↓をご覧ください。

ここからRNN,LSTMの特徴を説明していきます。

RNN

RNNは「Recurrent Neural Network」の略で「回帰型ニューラルネットワーク」とも呼ばれています。

RNN

RNNは中間層ごとにデータ(h)を出力して、それを次の中間層に渡すことによって、「入力値、1つ前のデータ」から出力値を割り出すことができます。

1つ前のデータから情報を利用することで時系列として予測していくことができるのです!

中間層は全結合層となっており、層ごとのすべてのニューロンが連結しています。
詳細は↓↓↓

また最後の出力(Yn)以外が点線になっているのは、出力しない方法もあるからです。

LSTM

RNNは短期のデータ(1つ前)を利用して出力値を割り出していました。

一方、LSTMは短期のデータだけでなく、長期のデータも使用することでより時系列として精度を高めることができます。

LSTM

中間層(LSTM層)のニューロンの中に記憶セルというものがあり、学習していくデータから常に更新させていくものがあります。

記憶セルは新しいことを学ぶと同時にこれまでの一部を忘却させたりしながら更新していきます。

これより、1つ前のデータだけでなく、これまでのデータを活用して時系列として学習させていくことができるのです。

ただし、RNNに比べて多くのメモリ・時間が必要になります

RNN・LSTMができること

RNN、LSTMは時系列のデータを利用することに優れています。
つまり、データに一連の動きがあることが必要です。

できること
  • 売り上げデータ
  • 株価予測
  • 画像生成
  • 音声認識
  • 文章・翻訳

「売り上げデータ」「株価予測」は日毎に値が動くので、時系列のデータとしてわかりやすいと思います。

「画像」「音声」「文章」が時系列とはどういうことなのでしょうか?

画像は1枚の絵に見えますが、拡大してみると小さな四角(1色で塗られている)が連続して表されています。
この連続した小さな四角の流れを予測することで画像を生成することができます。

音声・文章も同様に単語で区切ることで連続したデータとなり、学習させていくことができるようになります!

ディープラーニングの基本の実装は↓↓↓をご覧になってください。

RNNの実装

コサイン関数のグラフにノイズを加えたものをPytorchのRNNで学習させていきます。

以下のコードを実行して利用するモジュールを読み込みます。

import numpy as np
import matplotlib.pyplot as plt
import torch
from torch.utils.data import DataLoader
import torch.nn as nn
import torch.nn.functional as F
from torch import optim

「pyplot」はグラフ表示するために利用するモジュールになります。
グラフ表示する必要がない場合は読み込む必要はありません

次は学習させていくデータを作成します。
この記事ではコサイン関数にノイズを与えたものになります。

# コサイン関数にノイズを与える
cos_x = np.linspace(0, 4*np.pi, 120) 
cos_y = np.cos(cos_x)  + np.random.randn(len(cos_x)) * 0.3

# データの表示
plt.plot(cos_x, cos_y)
plt.show()
学習するデータ

次はこのデータを学習できるように準備していきます。

# データを利用できる形に変更
# 与えるデータ数
origin_data_num = 30
# 予測していくデータ数
prd_data_num = len(cos_y) - origin_data_num

# 入力データの用意:予測していくデータ数だけ、与えるデータを用意
input_data = np.zeros((prd_data_num, origin_data_num, 1)) 
# 正解データ:予測していくデータの数用意
correct_data = np.zeros((prd_data_num, 1))

for i in range(prd_data_num):
    input_data[i] = cos_y[i : i + origin_data_num].reshape(-1, 1)
    # 正解データは1つ次のデータ
    correct_data[i] = cos_y[i + origin_data_num : i + origin_data_num + 1]
    
# PyTorchで使用する形に変更
input_data = torch.tensor(input_data, dtype=torch.float)
correct_data = torch.tensor(correct_data, dtype=torch.float)

# DataLoaderでバッチに合わせて取得
dataset = torch.utils.data.TensorDataset(input_data, correct_data)
train_loader = DataLoader(dataset, batch_size=8, shuffle=True) 

「origin_data_num」変数は学習元にするデータの数です。
ここでは30つのデータより次のデータを予測していきます。

予測していくデータ数だけループを回して、「origin_data_num」分だけ入力データを作成しています。
同時に入力データの次の1データを正解データとして準備します

Pytorchで利用するため「Tensor型」にして、「DataLoader」を使用してミニバッチに合わせてデータを分類します。


次はRNNのモデルの作成です。
ここがメインなので、書き方を理解してもらえたら嬉しいです!

# モデルの作成
class Model(nn.Module):
    def __init__(self, input_size, hidden_size):
        # 親クラスのコンストラクタ
        super().__init__()
        
        # RNN
        self.rnn = nn.RNN(
            input_size= input_size,  # 入力サイズ
            hidden_size= hidden_size,  # ニューロン数
            batch_first=True,  # 入力をバッチサイズ, 与えるデータの数, 入力の数にする
        )
        self.output = nn.Linear(hidden_size, 1)
        
    def forward(self, x, h=None):
        # output : 全ての時刻の出力
        # hn : 次の時刻に渡される値
        output, hn = self.rnn(x, h)
        # y : 最後の時刻の出力
        y = self.output(output[:, -1, :])  
        return y
        
model = Model(1, 64)

ここではRNNを使用したモデルを作成しています。

8行目の「nn.RNN」で設定しています。
ここを「nn.LSTM」に書き換えるとLSTMが設定されます。

なんと簡単ですね!

層を増やしてより複雑な学習をさせたい場合は引数に「num_layers=○」を設定してください。
「○」は層数になります。

また活性化関数は引数「nonlinearity」で設定できます。

nonlinearity の値
  • tanh :デフォルト
  • relu

詳細はドキュメントを参照ください。

実際に学習させてみましょう。

# 交差エントロピー誤差関数
loss_fnc = nn.MSELoss()

# 最適化アルゴリズム
optimizer = optim.SGD(model.parameters(), lr=0.01)  # 学習率は0.01

# 表示領域、配置領域の確保
fig, axs = plt.subplots(2,5, figsize=(15.0, 5.0))

# 学習:エポックの数ループ
for i in range(1000):  # 50エポック学習
    # 訓練モード
    model.train()
    
    # ミニバッチで回す
    for j, (x, t) in enumerate(train_loader):
        # 順伝播
        y = model(x)
        # 誤差関数
        loss = loss_fnc(y, t)
        # 勾配の初期化
        optimizer.zero_grad()
        # 逆伝播
        loss.backward()
        # パラメータの更新
        optimizer.step()

    if i%100 == 0:
        # 最初の学習データ
        predicted = list(input_data[0].reshape(-1))
        for t in range(prd_data_num):
            # 近い時系列を取り出す
            x = torch.tensor(predicted[-origin_data_num:])
            # 引数:バッチサイズ, 時系列の数, 入力の数
            x = x.reshape(1, origin_data_num, 1) 
            y = model(x)
            predicted.append(y[0].item())
        fig_num = int(i / 100)
        fig.axes[fig_num].plot(range(len(cos_y)), cos_y, label="Correct")
        fig.axes[fig_num].plot(range(len(predicted)), predicted, label="Predicted")
        fig.axes[fig_num].tick_params(length=0)
plt.show()

ここでは1000エポック学習させ、100エポックごとに実際のデータと学習して割り出したデータを表示させています。

学習

徐々に精度が高まっているのがわかると思います。
エポック数を増やして実行すると精度を高めることができるでしょう!

ディープラーニングの学習方法

まずは「Youtube」で学ぶことをオススメします。
理由は無料だからです!

概要程度は十分理解できるコンテンツがそろっています。

おそらく実装面などでわからないことがでてきます!

こがた
こがた

ぼくも実際にコーディングするまでは理解できませんでした、、、

そこでオススメなのが「Udemy」です。

セール中は1万円代の講座が1,000円代で購入できます。

さらに詳しく学びたい、質問できる環境がほしい場合は『キカガク』がオススメです。

PythonのスキルからAI(ディープラーニング)、AIアプリの開発まで6ヶ月でできるようになります。

またディープラーニングの資格である『E資格』は認定された講座を受講しないと受けることができません、、、
この講座は認定されているため、資格を受けることができます!

費用も「216,000円」からです。
多少高く感じますが、他スクールでは50万円程度が多く、安いです。


書籍が学習する場合は以下の2つがまとまっており理解しやすいです!

最後に

RNN,LSTMは過去の時系列データからこれからのデータを予測することができます。

時系列といっても、時間軸のものでなくても、画像のピクセルのような流れがあれば予測することができます。

Pytorchを利用すると数十行のコードでRNN,LSTMを実装することができます。
一般的にはディープラーニングはムズカしいものだと思われていますが、やることはスゴくシンプルです。

プログラミング初心者でも数ヶ月学習すれば利用できるようになるので是非始めてみましょう。

最後まで読んでくださり、ありがとうございました!!!

コメント

タイトルとURLをコピーしました