任意の長さテキストを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