In [47]:
import numpy as np
from random import seed, randint
from math import ceil, log10
def random_sum_pairs(n_examples, n_numbers, largest):
X, y = list(), list()
for i in range(n_examples):
in_pattern = [randint(1, largest) for _ in range(n_numbers)]
out_pattern = sum(in_pattern)
X.append(in_pattern)
y.append(out_pattern)
return X, y
In [11]:
seed(1)
n_samples = 1
n_numbers = 2
largest = 10
# generate pairs
X, y = random_sum_pairs(n_samples, n_numbers, largest)
print(X, y)
In [19]:
# convert data to strings
def to_string(X, y, n_numbers, largest):
max_length = int(n_numbers * ceil(log10(largest + 1)) + n_numbers - 1)
Xstr = list()
for pattern in X:
strp = '+'.join([str(n) for n in pattern])
strp = ''.join([' ' for _ in range(max_length - len(strp))]) + strp
Xstr.append(strp)
max_length = int(ceil(log10(n_numbers * (largest + 1))))
ystr = list()
for pattern in y:
strp = str(pattern)
strp = ''.join([' ' for _ in range(max_length - len(strp))]) + strp
ystr.append(strp)
return Xstr, ystr
In [33]:
n_samples = 1
n_numbers = 2
largest = 10
# generate pairs
X, y = random_sum_pairs(n_samples, n_numbers, largest)
print(X, y)
X, y = to_string(X, y, n_numbers, largest)
print(X, y)
In [34]:
def integer_encode(X, y, alphabet):
char_to_int = dict((c, i) for i, c in enumerate(alphabet))
Xenc = list()
for pattern in X:
integer_encoded = [char_to_int[char] for char in pattern]
Xenc.append(integer_encoded)
yenc = list()
for pattern in y:
integer_encoded = [char_to_int[char] for char in pattern]
yenc.append(integer_encoded)
return Xenc, yenc
seed(1)
n_samples = 1
n_numbers = 2
largest = 10
X, y = random_sum_pairs(n_samples, n_numbers, largest)
print(X, y)
X, y = to_string(X, y, n_numbers, largest)
print(X, y)
alphabet = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', ' ']
X, y = integer_encode(X, y, alphabet)
print(X, y)
In [36]:
def one_hot_encode(X, y, max_int):
Xenc = list()
for seq in X:
pattern = list()
for index in seq:
vector = [0 for _ in range(max_int)]
vector[index] = 1
pattern.append(vector)
Xenc.append(pattern)
yenc = list()
for seq in y:
pattern = list()
for index in seq:
vector = [0 for _ in range(max_int)]
vector[index] = 1
pattern.append(vector)
yenc.append(pattern)
return Xenc, yenc
In [38]:
print(X, y)
X, y = one_hot_encode(X, y, len(alphabet))
print(X, y)
In [39]:
def generate_data(n_samples, n_numbers, largest, alphabet):
X, y = random_sum_pairs(n_samples, n_numbers, largest)
X, y = to_string(X, y, n_numbers, largest)
X, y = integer_encode(X, y, alphabet)
X, y = one_hot_encode(X, y, len(alphabet))
X, y = np.array(X), np.array(y)
return X, y
In [53]:
def invert(seq, alphabet):
int_to_char = dict((i, c) for i, c in enumerate(alphabet))
strings = list()
for pattern in seq:
string = int_to_char[np.argmax(pattern)]
strings.append(string)
return ''.join(strings)
In [41]:
# configulation
n_terms = 3
largest = 10
alphabet = [str(x) for x in range(10)] + ['+', ' ']
In [42]:
n_chars = len(alphabet)
n_in_seq_length = int(n_terms * ceil(log10(largest + 1)) + n_terms - 1)
n_out_seq_length = int(ceil(log10(n_terms * (largest + 1))))
In [49]:
from keras.models import Sequential
from keras.layers import LSTM, Dense, TimeDistributed, RepeatVector
model = Sequential()
# (timesteps, features)
model.add(LSTM(75, input_shape=(n_in_seq_length, n_chars)))
model.add(RepeatVector(n_out_seq_length)) # Decoderへの入力のため出力系列長と同じ長さだけコピー
model.add(LSTM(50, return_sequences=True))
model.add(TimeDistributed(Dense(n_chars, activation='softmax')))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()
In [50]:
# fit LSTM
X, y = generate_data(75000, n_terms, largest, alphabet)
model.fit(X, y, epochs=1, batch_size=32)
Out[50]:
In [51]:
# evaluate LSTM
X, y = generate_data(100, n_terms, largest, alphabet)
loss, acc = model.evaluate(X, y, verbose=0)
print('Loss: %f, Accuracy: %f' % (loss, acc * 100))
In [54]:
# predict
for _ in range(10):
X, y = generate_data(1, n_terms, largest, alphabet)
yhat = model.predict(X, verbose=0)
in_seq = invert(X[0], alphabet)
out_seq = invert(y[0], alphabet)
predicted = invert(yhat[0], alphabet)
print('%s = %s (expect %s)' % (in_seq, predicted, out_seq))