#https://orangesrv.dip.jp/wordpress/archives/1063
#上記記事のコードを実行してみる
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from keras.layers.core import RepeatVector
from keras.layers.wrappers import TimeDistributed
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Dense, Activation, LSTM,Input
from tensorflow.keras.initializers import glorot_uniform, orthogonal
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.utils import plot_model
# 3桁のランダムな整数を返す
def n(digits=3):
number = ''
for i in range(np.random.randint(1, digits + 1)):
number += np.random.choice(list('0123456789'))
return int(number)
def padding(chars, maxlen):
return chars + ' ' * (maxlen - len(chars))
def make_question(a, b, input_digits):
question = '{}+{}'.format(a, b)
question = padding(question, input_digits)
return question
def make_answer(a, b, output_digits):
answer = str(a + b)
answer = padding(answer, output_digits)
return answer
np.random.seed(seed=32)
digits = 3
N = 40000
N_train = 0.9
input_digits = digits * 2 + 1
output_digits = digits + 1
added = set()
questions = []
answers = []
while len(questions) < N:
a, b = n(), n()
pair = tuple(sorted((a, b)))
if pair in added:
continue
question = make_question(a, b, input_digits)
answer = make_answer(a, b, output_digits)
added.add(pair)
questions.append(question)
answers.append(answer)
def translate_onehot(seqs, char_indices, n_chars, n_digits):
V = np.zeros((len(seqs), n_digits, n_chars), dtype = np.integer)
for i in range(len(seqs)):
for t, char in enumerate(seqs[i]):
V[i, t, char_indices[char]] = 1
return V
chars = '0123456789+ '
char_indices = dict((c, i) for i, c in enumerate(chars))
indices_char = dict((i, c) for i, c in enumerate(chars))
n_in = len(chars)
n_out = len(chars)
X = translate_onehot(questions, char_indices, n_in, input_digits)
Y = translate_onehot(answers, char_indices, n_out, output_digits)
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, train_size = N_train)
n_hidden = 128
def create_model_sequential(seed=10719173):
model = Sequential()
# Encoder
model.add(LSTM(
n_hidden,
input_shape = (input_digits, n_in),
kernel_initializer=glorot_uniform(seed=seed),
recurrent_initializer=orthogonal(gain=1.0, seed=seed)
))
# Decoder
model.add(RepeatVector(output_digits))
model.add(LSTM(
n_hidden,
return_sequences = True,
kernel_initializer=glorot_uniform(seed=seed),
recurrent_initializer=orthogonal(gain=1.0, seed=seed)
))
model.add(TimeDistributed(Dense(n_out,kernel_initializer=glorot_uniform(seed=seed))))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer=Adam(lr=0.001, beta_1=0.9, beta_2=0.999), metrics=['accuracy'])
return model
def compare_TV(history):
# Setting Parameters
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
epochs = range(len(acc))
plt.plot(epochs, acc, 'bo' ,label = 'training acc')
plt.plot(epochs, val_acc, 'b' , label= 'validation acc')
plt.title('Training and Validation acc')
plt.legend()
plt.figure()
plt.show()
def show_acc(model, batch_size = 300, epochs = 40, verbose = 0, shuffle = False):
hist = model.fit(X_train, Y_train,
batch_size=batch_size,
epochs=epochs,
validation_split=0.1,
verbose=verbose,
shuffle=shuffle
)
compare_TV(hist)
model_sequential = create_model_sequential()
plot_model(model_sequential, show_shapes=True,to_file='sequential_training.png')
show_acc(model_sequential)
# 予測してみる
def predict(model, a, b): # 学習済みのmodelを使ってa+bを予測
sample_question = make_question(a, b, input_digits)
sample_X = translate_onehot([sample_question], char_indices, n_in, input_digits)
out = model.predict(sample_X)
return ''.join([indices_char[np.argmax(v)] for v in out[0]])
predict(model_sequential, 10, 21)
predict(model_sequential, 31, 52)