質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.80%

MinstをRNN(LSTM)で学習する際のイメージがつかめない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,427

ads3hcgff

score 16

MinistをLSTMで学習させたいのですが
特徴量の入力について疑問があります。
28*28のサイズで28の一行目(模式図のt1)から二行目(t2)というデータを読み込ませたいのですが
ディープニュートラルネットワークの設計としては中間層h0がh1に入るという認識でいいでしょうか?
時系列データとして扱っているのでt1からt2に行くh27とh28が(t2からt3も)つながっていないという認識なのですが・・・
あってますでしょうか?
模式図↓

イメージ説明

具体的なコード

from keras.utils import np_utils      # keras.utilsからnp_utilsをインポート
from keras.datasets import mnist      # MNISTデータセットをインポート

# MNISTデータセットの読み込み
(x_trains, y_trains), (x_tests, y_tests) = mnist.load_data()

# 訓練データ
x_trains = x_trains.astype('float32') # float32型に変換
x_trains /= 255                       # 0から1.0の範囲に変換
# 正解ラベルをワンホット表現に変換
correct = 10                          # 正解ラベルの数
y_trains = np_utils.to_categorical(y_trains, correct)

# テストデータ
x_tests = x_tests.astype('float32')   # float32型に変換
x_tests /= 255                        # 0から1.0の範囲に変換
# 正解ラベルをワンホット表現に変換
y_tests = np_utils.to_categorical(y_tests, correct)

print(x_trains.shape)                 # 訓練データの形状を出力
print(x_tests.shape)                  # テストデータの形状を出力

# RNNの構築
from keras.models import Sequential
from keras.layers import InputLayer, Dense
from keras.layers.recurrent import LSTM
from keras import optimizers,regularizers

# Sequentialオブジェクトを生成
model = Sequential()

## 入力層
# 入力データの形状は(28, 28)
model.add(
    InputLayer(input_shape=(28,28))
    )

## 中間層
# LSTMブロック(ユニット数=128)
weight_decay = 1e-4 # ハイパーパラメーター
model.add(LSTM(units=128, dropout=0.25, return_sequences=True))
model.add(LSTM(units=128, dropout=0.25, return_sequences=True))
model.add(LSTM(units=128, dropout=0.25, return_sequences=False,
               kernel_regularizer=regularizers.l2(weight_decay)) # 正則化
)

## 出力層
model.add(
    Dense(units=10,                  # 出力層のニューロン数は10
          activation='softmax')      # 活性化はシグモイド関数
    )

# Squentialオブジェクをコンパイル
model.compile(
    loss='categorical_crossentropy', # 誤差関数はクロスエントロピー
    optimizer=optimizers.Adam(),     # Adamオプティマイザー
    metrics=['accuracy']             # 学習評価として正解率を指定
    )

model.summary()                      # RNNのサマリ(概要)を出力

# 学習を開始
history = model.fit(x_trains, y_trains, # 訓練データ、正解ラベル
                    batch_size=100,     # ミニバッチのサイズ
                    epochs=10,          # 学習回数
                    verbose=1,          # 学習の進捗状況を出力する
                    validation_data=(   # テストデータの指定
                    x_tests, y_tests)
                    )

# 損失と正解率をグラフにする

import matplotlib.pyplot as plt

# プロット図のサイズを設定
plt.figure(figsize=(15, 6))
# プロット図を縮小して図の間のスペースを空ける
plt.subplots_adjust(wspace=0.2)

# 1×2のグリッドの左(1,2,1)の領域にプロット
plt.subplot(1, 2, 1)
# 訓練データの損失(誤り率)をプロット
plt.plot(history.history['loss'],
         label='training',
         color='black')
# テストデータの損失(誤り率)をプロット
plt.plot(history.history['val_loss'],
         label='test',
         color='red')
plt.ylim(0, 1)       # y軸の範囲
plt.legend()         # 凡例を表示
plt.grid()           # グリッド表示
plt.xlabel('epoch')  # x軸ラベル
plt.ylabel('loss')   # y軸ラベル

# 1×2のグリッドの右(1,2,21)の領域にプロット
plt.subplot(1, 2, 2)
# 訓練データの正解率をプロット
plt.plot(history.history['acc'],
         label='training',
         color='black')
# テストデータの正解率をプロット
plt.plot(history.history['val_acc'],
         label='test',
         color='red')
plt.ylim(0.5, 1)     # y軸の範囲
plt.legend()         # 凡例を表示
plt.grid()           # グリッド表示
plt.xlabel('epoch')  # x軸ラベル
plt.ylabel('acc')    # y軸ラベル
plt.show()
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • ads3hcgff

    2019/10/27 23:23

    そういうわけではないですね

    キャンセル

  • teefpc

    2019/10/27 23:49

    再帰型ニューラルネットワークは、入力(時刻 t) に対して、出力(時刻 t+1) を予測するというものなのですが、このプログラムは、入力に画像データ、教師データにそのラベルを設定してfit させようとしています。(CNNを理解された上でLSTMモデルを独自に研究されているのであれば、申し訳ありませんが私の理解を超えています)

    キャンセル

  • ads3hcgff

    2019/10/28 00:30

    今回の目的としては厳密なモデル選択をしているのではなくMnistでとりあえずLSTMを適用しようという方針です。その際にピクセル単位で相互に関連性を持ったと仮定しており、その前提のモデルがあっているかどうかということを質問しているという流れです。厳密性にこだわっていないので有識者の人から見ると怒られるかもしれませんがそれはそれこれはこれでお願いします。

    キャンセル

回答 2

checkベストアンサー

0

lstmにおける1ノードは1ピクセルではなく、複数ピクセルを含みます。
イメージ説明

すなわち、画像認識においては、1行28ピクセルを1ステップとして、28ステップの学習をします。
これは、数字描画するときは、黒画素と黒画素とが連結しているのが自然で、縦方向を時間軸とみなせば、
時間軸上になんらかの関連性があるという考えに基づくもので、画像にlstmを使用するのは不自然ではありません。
ただし、cnnよりも精度が出るとはかぎりません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/10/28 16:21 編集

    回答ありがとうございます。
    図のx0(t0)の中に28個のデータ(一行28ピクセル)があるとと思うのですがこちらは
    一行目だと
    ピクセルをp 重みをwとしてh0 = sigmoid([p0,p1....p27] *[[w0,w1...w27](転置)])を
    h1に再入力しているという認識でいいでしょうか
    どうもx0の中のピクセル28個分をどうするかというイメージとその正解ラベルy0のイメージがつきません。
    正解ラベルについては一枚の画像で28個正解ラベルがいるという認識であってますでしょうか。

    キャンセル

  • 2019/10/28 20:18

    その部分については、LSTMなのか、RNNなのか、GRUなのかで異なってきます。
    しかし、基本的にはその認識でまちがいありません。

    キャンセル

  • 2019/10/28 21:06

    正確には、あるステップtのピクセルP(t)={p1,p2,p3,...,p27}とします。
    隠れ層のユニット数を28次元とすれば、一つ前のステップの隠れ層H(t-1)={h1,h2,h3,...,h27}と表せます。

    このとき、ステップtの隠れ層はP×Wih+H(t-1)×Whhと表せます。

    ここで、WihはPの次元数28とHの次元数28の28x28次元の重み行列です。
    WhhはHの次元数28と同じくHの次元数28の28x28の重み行列です。

    では、例えば、28x28の画像から10クラスの分類をしたい場合、出力は10次元ですね。
    このとき、Hの次元数を10次元としてみます。
    そうすると、Pは28次元ベクトル、Hは10次元ベクトルです。
    これを先程の説明に当てはめると、Wihは28x10の重み行列、Whhは10x10の重み行列となります。

    あとは、一ステップずつ計算していくことで、入力の28x28画像を10次元にへんかんできますね。

    ただし、これは先程ものべたように、LSTMの基となるRNNのさらに基本的な部分のみです。

    LSTMではもう少し複雑なことをしていますが、基本的な考え方は同じです。

    キャンセル

0

「28次元のベクトル」が変化していく時系列データを「28ステップ分」記録したもの

だと思ってLSTMは処理しています。


(追記)

質問に貼ってあるソースの動きはこうです。

1層目のLSTMの時刻t0の入力x0は「画像の一番上の28ピクセル」に対応する「28個の数値」を、28次元のベクトルだと見たものです。
LSTMにx0を入れると内部状態(128次元ベクトル)を更新してh0になります。(と同時にこれが出力でもあります。後述)

1層目のLSTMの時刻t1の入力x1は「画像の上から2番目の28ピクセル」に対応する「28個の数値」を、28次元のベクトルだと見たものです。
LSTMは1つ前の内部状態h0と、x1から、内部状態を更新してh1になります。

(略)

1層目のLSTMの時刻t27の入力x27は「画像の一番下の28ピクセル」に対応する「28個の数値」を、28次元のベクトルだと見たものです。
LSTMは1つ前の内部状態h26と、x27から、内部状態を更新してh27になります。

return_sequences=Trueが指定してありますから、1層目のLSTMの出力は、h0からh27の128次元のベクトル28個をconcatenateしたものです。

したがって、2層目のLSTMの入力は128次元のベクトルの28ステップの時系列データとなります。


2層目のLSTMの時刻t0の入力x0は「1層目のLSTMの時刻0の内部状態ベクトル」です。
LSTMにx0を入れると内部状態を更新してh0になります。

2層目のLSTMの時刻t1の入力x1は「1層目のLSTMの時刻1の内部状態ベクトル」です。
LSTMは1つ前の内部状態h0と、x1から、内部状態を更新してh1になります。

(略)

2層目のLSTMの時刻t27の入力x27は「1層目のLSTMの時刻27の内部状態ベクトル」です。
LSTMは1つ前の内部状態h26と、x27から、内部状態を更新してh27になります。

return_sequences=Trueが指定してありますから、2層目のLSTMの出力は、h0からh27の128次元のベクトル28個をconcatenateしたものです。

したがって、3層目のLSTMの入力も2層目と同様、128次元のベクトルの28ステップの時系列データとなります。


3層目のLSTMの時刻t0の入力x0は「2層目のLSTMの時刻0の内部状態ベクトル」です。
LSTMにx0を入れると内部状態を更新してh0になります。
(略)
3層目のLSTMの時刻t27の入力x27は「2層目のLSTMの時刻27の内部状態ベクトル」です。
LSTMは1つ前の内部状態h26と、x27から、内部状態を更新してh27になります。

return_sequences=Falseが指定してありますから、3層目のLSTMの出力は、最後の内部状態ベクトルh27です。つまり128次元のベクトルを出力します。

したがって、最後の全結合層の入力は128次元のベクトルになります。


最後に、128次元の入力から全結合層につながって、10次元のベクトルをsoftmax関数を通して出力することでクラス分類の結果としています。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る