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

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

ただいまの
回答率

88.11%

KerasでのDeep Learningでlossがあまり下がらない

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 2,345

score 9

当方,Pythonも自然言語処理も初心者なため,コードが読みにくかったり,場違いな質問をしてしまっているかもしれませんが,どうかお許しください.

1.タイトルにもある通り,KerasでDeep Learning(名古屋大学会話コーパスをもちいたチャットボットの作成)をしているのですが,出力されるlossの値があまり下がりません.オプティマイザーなどを変えたほうが良いでしょうか?

2.GPUがGTX970のためバッチサイズが頑張っても4くらいしか取れない状態なのですが,それも関係してくるのでしょうか?
また,この特徴ベクトルの次元数と語彙数のままバッチサイズを上げる方法などがあれば是非お教え願いたいです.

import pickle
import numpy as np

import tensorflow as tf
import keras
import keras_transformer
import keras_bert
import keras.backend as K


config_file_path = 'data/config/config.json'
checkpoint_file_path = 'data/checkpoint/bert_model.ckpt'

with open('data/nagoya_corpus/nagoya_encoder_inputs.pickle', 'rb') as f:
    encoder_inputs = pickle.load(f)
with open('data/nagoya_corpus/nagoya_decoder_inputs.pickle', 'rb') as f:
    decoder_inputs = pickle.load(f)
with open('data/nagoya_corpus/nagoya_decoder_outputs.pickle', 'rb') as f:
    decoder_outputs = pickle.load(f)


def get_transformer_on_bert_model(
        token_num: int,
        embed_dim: int,
        encoder_num: int,
        decoder_num: int,
        head_num: int,
        hidden_dim: int,
        embed_weights,
        attention_activation=None,
        feed_forward_activation: str = 'relu',
        dropout_rate: float = 0.0,
        use_same_embed: bool = True,
        embed_trainable=True,
        trainable: bool = True
) -> keras.engine.training.Model:
    """
    Transformerのモデルのinputsを特徴ベクトルにしたモデル.それ以外は特に変わらない.
    inputsのshapeは (None, seq_len, embed_dim) となっている,

    Parameters
    ----------
    token_num
        トークンのサイズ.(vocab_sizeと同じ)
    embed_dim
        特徴ベクトルの次元.inputsの次元数と同じにする.
    encoder_num
        エンコーダの層の数.
    decoder_num
        デコーダの層の数.
    head_num
        Multi-Head Attentionレイヤの分割ヘッド数.
    hidden_dim
        隠し層の次元数.
    embed_weights
        特徴ベクトルの初期化.
    attention_activation
        Attentionレイヤの活性化関数.
    feed_forward_activation
        FFNレイヤの活性化関数.
    dropout_rate
        Dropoutのレート.
    use_same_embed
        エンコーダとデコーダで同じweightsを使用するか.
    embed_trainable
        特徴ベクトルがトレーニング可能かどうか.
    trainable
        モデルがトレーニング可能かどうか.

    Returns
    -------
    model
        日本語学習済みのBERTの特徴ベクトルを用いたTransformerモデル
    """
    return keras_transformer.get_model(
        token_num=token_num,
        embed_dim=embed_dim,
        encoder_num=encoder_num,
        decoder_num=decoder_num,
        head_num=head_num,
        hidden_dim=hidden_dim,
        embed_weights=embed_weights,
        attention_activation=attention_activation,
        feed_forward_activation=feed_forward_activation,
        dropout_rate=dropout_rate,
        use_same_embed=use_same_embed,
        embed_trainable=embed_trainable,
        trainable=trainable
    )


def train(use_checkpoint=True):
    if use_checkpoint:
        transformer_model = keras_transformer.get_model(
            token_num=32006,
            embed_dim=768,
            encoder_num=3,
            decoder_num=3,
            head_num=8,
            hidden_dim=128,
            dropout_rate=0.1,
        )
        transformer_model.load_weights('data/checkpoint/transformer_model.ckpt')
    else:
        bert_model = keras_bert.load_trained_model_from_checkpoint(
            checkpoint_file=checkpoint_file_path,
            config_file=config_file_path
        )
        bert_weights = bert_model.get_layer(name='Embedding-Token').get_weights()[0]
        transformer_model = get_transformer_on_bert_model(
            token_num=32006,
            embed_dim=768,
            encoder_num=3,
            decoder_num=3,
            head_num=8,
            hidden_dim=128,
            dropout_rate=0.1,
            embed_weights=bert_weights,
        )
    transformer_model.compile(
        optimizer=keras.optimizers.Adam(beta_1=0.9, beta_2=0.98),
#        optimizer=keras.optimizers.SGD(),
        loss=keras.losses.sparse_categorical_crossentropy,
        metrics=[keras.metrics.mae, keras.metrics.categorical_accuracy],
    )
    transformer_model.summary()
    transformer_model.fit_generator(
        generator=_generator(),
        steps_per_epoch=100,
        epochs=100,
        validation_data=_generator(),
        validation_steps=20,
        callbacks=[
            keras.callbacks.ModelCheckpoint('./data/checkpoint/transformer_model.ckpt', monitor='val_loss'),
            keras.callbacks.TensorBoard(log_dir='./data/tflog/'),
            keras.callbacks.LearningRateScheduler(_decay),
        ]
    )


def main():
    train(use_checkpoint=False)


def _decay(epochs):
    if epochs == 0:
        step_num = 1
    else:
        step_num = epochs*100
    warmup_steps = 4000
    d = 768
    return (768**-0.5) * min(step_num**-0.5, step_num*(warmup_steps**-1.5))


def _generator():
    i = 0
    data_len = len(encoder_inputs)
    batch_size = 4
    while True:
        if (i + batch_size) >= data_len:
            i = 0
        else:
            i += 1
        yield [encoder_inputs[i:i+batch_size], decoder_inputs[i:i+batch_size]], decoder_outputs[i:i+batch_size]


if __name__ == '__main__':
    main()


ちなみに,コーパスのサイズは約170000文,モデルはTransformerのEmbeddingレイヤにBERTの特徴量を差し込んだものとなっています.

この状態で試しに100ステップ*100エポックほど回してみると,はじめはlossが8,7,6のようになさがっていったのですが,4.1あたりになると,ほぼ下がらなくなってしまいました.これくらいのステップ数とエポック数であれば,そんなものなのでしょうか?また,ある程度長時間回すと最終的にlossはどれくらいまで下がるのが普通なのでしょうか?

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

コードを読んでいないので、一般論で回答します。

4.1あたりになると,ほぼ下がらなくなってしまいました

収束しているような下がり方なら、step/epoch増やしても無駄です。

精度を上げるには。。。
・ハイパーパラメータ変えましょう。
・データの前処理しましょう。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/05/20 17:19

    ご回答有り難うございます.
    お教えいただいた通り,ハイパーパラメータの調整をしてみようと思います.

    キャンセル

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

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

関連した質問

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