Reputation: 31
I wanted to create a simple neural network to classify whole numbers as even or odd.
I wrote this code :
# -*- coding: utf-8 -*-
import numpy as np
import keras
from keras.models import Sequential
from keras.layers import Dense
X = np.zeros(1000, dtype=int)
y = np.zeros(1000, dtype=int)
for number in range(1000):
X[number] = number
y[number] = (number+1) % 2
classifier = Sequential()
classifier.add(Dense(units = 3, activation = 'relu', input_dim = 1))
classifier.add(Dense(units = 1, activation = 'sigmoid'))
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy',metrics = ['accuracy'])
classifier.fit(X, y, epochs = 100, batch_size = 50)
But I can only achieve an accuracy of 0.5. Can someone please help me to find what am I doing wrong ?
Upvotes: 2
Views: 352
Reputation: 10819
One way to make such a classifier work is by changing the representation of your inputs. Simple integers, in this case, won't work. One way would be to convert the integers in their binary equivalent and then encode it into a list of bits.
import numpy as np
import keras
from keras.models import Sequential
from keras.layers import Dense
X = np.zeros(1000, dtype=int)
y = np.zeros(1000, dtype=int)
for number in range(1000):
X[number] = number
y[number] = (number+1) % 2
binaries = ["{0:b}".format(x) for x in X] #convert integers in binary
max_len = max([len(x) for x in binaries])
same_len_bin = ['0'*(max_len-len(x))+x for x in binaries] #all inputs must have same len
X = np.array([[int(n) for n in x] for x in same_len_bin]) #list of bits
classifier = Sequential()
classifier.add(Dense(units = 3, activation = 'relu', input_dim = 10))
classifier.add(Dense(units = 1, activation = 'sigmoid'))
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy',metrics = ['accuracy'])
classifier.fit(X, y, epochs = 100, batch_size = 50)
Note that I have used string formatting to generate the binary counterpart of each integer. Then I have added enough 0
s in front of each string to ensure the length of all inputs is the same. At this point the inputs are strings, so the last conversion step makes a list of integers out of each string.
Of course, the input dimension of the network needs to be changed from 1
to 10
, since now your input is an array of 10 integers.
Here is how the numbers look after the conversion:
for n in X[:5]:
print(n)
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 1]
[0 0 0 0 0 0 0 0 1 0]
[0 0 0 0 0 0 0 0 1 1]
[0 0 0 0 0 0 0 1 0 0]
The output of the training will be:
Epoch 1/100
1000/1000 [==============================] - 0s 320us/step - loss: 0.6780 - acc: 0.5500
Epoch 2/100
1000/1000 [==============================] - 0s 22us/step - loss: 0.6712 - acc: 0.5680
...
...
Epoch 100/100
1000/1000 [==============================] - 0s 24us/step - loss: 0.0294 - acc: 1.0000
Upvotes: 2
Reputation: 3588
The problem is that the representation of your input is not suitable for this problem. You can find a discussion about this here
Upvotes: 2