A-2.RNN(LSTM)による文章生成

任意の長さテキストをRNN(LSTM)に学習させるためのKerasのサンプルコード。 学習済みのモデルは文章のエッセンスを記録しているため、入力文に似た文字列を出力するが、文章の質は良くない。
下記はコードでは学習及び正解データの準備と、学習モデルの保存までが可能。

サンプルデータ(要解凍)
https://aiandstory.net/sample.zip

# -*- coding: utf-8 -*-

from __future__ import print_function
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Dense, LSTM, Embedding
from tensorflow.keras.layers import Reshape, RepeatVector, TimeDistributed, Activation
from tensorflow.keras.optimizers import Adamax
from tensorflow.keras import Input

import numpy as np
import random
import sys
import warnings
warnings.filterwarnings('ignore')

#utf-8のテキストを準備
path="sample.txt"

#一括で読み込み
with open(path, encoding='utf-8') as f:
    text = f.read()
print('corpus length:', len(text))

#空白を除去
tokens = text.split()
text = ''.join(tokens)

#文字のインデックスを作成するためにソート
chars = sorted(list(set(text)))
print('total chars:', len(chars))

#文字<->インデックスの辞書を準備
char_indices = dict((c, i) for i, c in enumerate(chars))
indices_char = dict((i, c) for i, c in enumerate(chars))

#学習及び正解データの準備
maxlen = 30#入力データの文字数。元の文章をこの文字数で分割する
gen_charlen = 1#出力(正解)データの文字数
step = 1
sentences = []#入力データのリスト
next_chars = []#出力(正解)データのリスト
for i in range(0, len(text) - maxlen - gen_charlen, step):
    sentences.append([char_indices[char] for char in text[i: i + maxlen]])
    next_chars.append([char_indices[char] for char in text[i + maxlen: i + maxlen + gen_charlen]])
print('input data sequences:', len(sentences))

# build the model: 

print('Build model...')

#語彙数がEmbedding層の入力次元になる
vcab_size = len(chars)

#他のファイルでimportする場合、以降は実行しない。
if __name__ == "__main__":

    #文字のインデックスが入力データなのでint32を指定,shapeにはサンプル数の次元の軸は含まない
    #この指定ではmaxlen次元のベクトルが入力となる
    text_input = Input(shape=(maxlen,), dtype='int32', name='text')
    #埋め込み層。output_dim次元のベクトルシーケンスに埋め込む
    embedded_text = Embedding(input_dim=vcab_size ,output_dim=128)(text_input)
    
    hidden_unit = 128#LSTMの隠れユニット数    
    output = embedded_text

    #RNN(LSTM)層
    output_enc = LSTM(hidden_unit, dropout=0.2, recurrent_dropout=0.5)(output)

    #出力層
    output_dec = Dense(vcab_size, activation='softmax')(output_enc)

    #モデルのインスタンス化
    model = Model(text_input, output_dec)
    
    optimizer = Adamax(lr=0.01)
    #softmaxで数値(one-hot表現ではなく数値の配列)のターゲットを処理する場合はspasparse_categorical_crossentropyを指定する。この指定は、入力データごとに確率スコアを出力するため、モデルの最終的な出力形状には影響しない
    model.compile(loss='sparse_categorical_crossentropy', optimizer=optimizer,  metrics=['accuracy'])
    model.summary()
    
    #model.fit()用にNumPy配列を生成する。
    x = np.array(sentences)
    y = np.array(next_chars)

    #xは入力データ、yは出力(正解)データ、epochs(試行回数)は任意(10)
    model.fit(x, y,
              batch_size=128,
              epochs=10)

    #学習済みモデルを保存
    model.save('text_generation_for_aiandstory')
 

参考文献
https://github.com/keras-team/keras/tree/master/examples


投稿日

カテゴリー:

,

投稿者: