Do you know the Fizzbuzz problem? This is a beginner's problem in programming, and you write the following code.
An example of the answer is written in Python as follows.
import numpy as np
num = np.arange(1,101,1)
for i in num:
if i % 15 == 0: print ("fizzbuzz")
elif i % 5 == 0: print ("buzz")
elif i % 3 == 0: print ("fizz")
else: print (i)
There are innumerable ways to write code, but basically it is easy to write by dividing the case into for and if.
However! It is human nature that makes us want to solve these problems with deep learning. Moreover, there are some ancestors who have solved it even in Tensorflow (although it has not been solved (.ŏ﹏ŏ)). http://joelgrus.com/2016/05/23/fizz-buzz-in-tensorflow/
So, let's rewrite the above Tensorflow fizzbuzz with Keras. Mainly only the model part has been migrated to Keras, and the other code is mostly based on the Tensorflow version as it is.
A neural network model is created by supervised learning, and the correct answer rate of the model is evaluated using an integer from 1 to 100 as test data.
Let's write it now.
First, import the required library.
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import np_utils
from keras.layers import Dense
from keras.models import Model
Teacher data is required. This time, we will use integers from 101 to 1024 as teacher data, but we will have the teacher data in binary format. That is, the matrix at (923, 10) is the teacher data.
def binary_encode(i, num_digits):
return np.array([i >> d & 1 for d in range(num_digits)])
NUM_DIGITS = 10
trX = np.array([binary_encode(i, NUM_DIGITS) for i in range(101, 2 ** NUM_DIGITS)])
Now, we also need the fizzbuzz value for the teacher data. This is also made in binary format.
def fizz_buzz_encode(i):
if i % 15 == 0: return np.array([0, 0, 0, 1])
elif i % 5 == 0: return np.array([0, 0, 1, 0])
elif i % 3 == 0: return np.array([0, 1, 0, 0])
else: return np.array([1, 0, 0, 0])
trY = np.array([fizz_buzz_encode(i) for i in range(101, 2 ** NUM_DIGITS)])
You now have an integer (binary format) from 101 to 1024 for teacher data and its fizzbuzz (binary format). Preparations are complete. Now let's write a model.
Generate models sequentially.
model = Sequential()
Add a layer. This time, we will use a 3-layer (fully combined) network.
model.add(Dense(1000, input_dim=10, activation="relu"))
model.add(Dense(1000, activation="relu"))
model.add(Dense(4, activation="softmax"))
The final output is an integer, fizz, buzz, or fizzbuzz, so the last layer will have an output of 4.
The optimization algorithm should be adagrad. The Tensorflow version was SGD, but it didn't converge much when I did it with Keras. Let's compile and train the model.
model.compile(loss='categorical_crossentropy', optimizer='adagrad', metrics=["accuracy"])
model.fit(trX, trY, nb_epoch=100, batch_size=128)
It's a fair rate of convergence. (Slightly overfit?)
Let's evaluate this model. Let's apply the model to integers from 1 to 100.
def fizz_buzz(i, prediction):
return [str(i), "fizz", "buzz", "fizzbuzz"][prediction]
numbers = np.arange(1, 101)
teX = np.transpose(binary_encode(numbers, NUM_DIGITS))
teY = model.predict_classes(teX)
output = np.vectorize(fizz_buzz)(numbers, teY)
print (output)
came out.
By the way, the correct answer is as follows.
answer = np.array([])
for i in numbers:
if i % 15 == 0: answer = np.append(answer, "fizzbuzz")
elif i % 5 == 0: answer = np.append(answer, "buzz")
elif i % 3 == 0: answer = np.append(answer, "fizz")
else: answer = np.append(answer, str(i))
print (answer)
Let's see the accuracy rate of the model.
evaluate = np.array(answer == output)
print (np.count_nonzero(evaluate == True) / 100)
97%!! Is it so good?
You may get a better accuracy rate by increasing the number of layers and units, but that's okay.
The whole code is below.
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import np_utils
from keras.layers import Dense
from keras.models import Model
#Teacher data generation
def binary_encode(i, num_digits):
return np.array([i >> d & 1 for d in range(num_digits)])
NUM_DIGITS = 10
trX = np.array([binary_encode(i, NUM_DIGITS) for i in range(101, 2 ** NUM_DIGITS)])
#Teacher data fizzbuzz
def fizz_buzz_encode(i):
if i % 15 == 0: return np.array([0, 0, 0, 1])
elif i % 5 == 0: return np.array([0, 0, 1, 0])
elif i % 3 == 0: return np.array([0, 1, 0, 0])
else: return np.array([1, 0, 0, 0])
trY = np.array([fizz_buzz_encode(i) for i in range(101, 2 ** NUM_DIGITS)])
#model
model = Sequential()
model.add(Dense(1000, input_dim=10, activation="relu"))
model.add(Dense(1000, activation="relu"))
model.add(Dense(4, activation="softmax"))
model.compile(loss='categorical_crossentropy', optimizer='adagrad', metrics=["accuracy"])
model.fit(trX, trY, nb_epoch=100, batch_size=128)
#Binary fizzbuzz conversion
def fizz_buzz(i, prediction):
return [str(i), "fizz", "buzz", "fizzbuzz"][prediction]
#Try applying the model to integers from 1 to 100
numbers = np.arange(1, 101)
teX = np.transpose(binary_encode(numbers, NUM_DIGITS))
teY = model.predict_classes(teX)
output = np.vectorize(fizz_buzz)(numbers, teY)
print (output)
#Correct answer
answer = np.array([])
for i in numbers:
if i % 15 == 0: answer = np.append(answer, "fizzbuzz")
elif i % 5 == 0: answer = np.append(answer, "buzz")
elif i % 3 == 0: answer = np.append(answer, "fizz")
else: answer = np.append(answer, str(i))
print (answer)
#Correct answer rate
evaluate = np.array(answer == output)
print (np.count_nonzero(evaluate == True) / 100)
Recommended Posts