title: Why is my Keras model performing so poorly on the Iris dataset?
body: <p>I'm working through <a href="http://blog.fastforwardlabs.com/post/139921712388/hello-world-in-keras-or-scikit-learn-versus" rel="nofollow noreferrer">this Keras tutorial</a> and I'm finding something interesting.</p>
  
  <p>I've trained my logistic regression model using the sklearn, and it performs fairly well:</p>
  
  <pre><code>import seaborn as sns
  import numpy as np
  from sklearn.cross_validation import train_test_split
  from sklearn.linear_model import LogisticRegressionCV
  from keras.models import Sequential
  from keras.layers.core import Dense, Activation
  from keras.utils import np_utils
  
  # Load the iris dataset from seaborn.
  iris = sns.load_dataset("iris")
  
  # Use the first 4 variables to predict the species.
  X, y = iris.values[:, 0:4], iris.values[:, 4]
  
  # Split both independent and dependent variables in half
  # for cross-validation
  train_X, test_X, train_y, test_y = train_test_split(X, y, train_size=0.5, random_state=0)
  
  # Train a scikit-learn log-regression model
  lr = LogisticRegressionCV()
  lr.fit(train_X, train_y)
  
  # Test the model. Print the accuracy on the test data
  pred_y = lr.predict(test_X)
  print("Accuracy is {:.2f}".format(lr.score(test_X, test_y))) # Accuracy is 0.83
  </code></pre>
  
  <p>83% is quite good, but using deep learning we should be able to do better. I train a Keras model...</p>
  
  <pre><code># Define a one-hot encoding of variables in an array.
  def one_hot_encode_object_array(arr):
      '''One hot encode a numpy array of objects (e.g. strings)'''
      uniques, ids = np.unique(arr, return_inverse=True)
      return np_utils.to_categorical(ids, len(uniques))
  
  # One-hot encode the train and test y's
  train_y_ohe = one_hot_encode_object_array(train_y)
  test_y_ohe = one_hot_encode_object_array(test_y)
  
  # Build the keras model
  
  model = Sequential()
  # 4 features in the input layer (the four flower measurements)
  # 16 hidden units
  model.add(Dense(16, input_shape=(4,)))
  model.add(Activation('sigmoid'))
  # 3 classes in the ouput layer (corresponding to the 3 species)
  model.add(Dense(3))
  model.add(Activation('softmax'))
  model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
  
  # Train the keras model
  model.fit(train_X, train_y_ohe, verbose=0, batch_size=1)
  
  # Test the model. Print the accuracy on the test data
  loss, accuracy = model.evaluate(test_X, test_y_ohe, verbose=0)
  print("Accuracy is {:.2f}".format(accuracy)) # Accuracy is 0.60????
  </code></pre>
  
  <p>When I train a Keras model, my accuracy is actually worse than my logistic regression model.</p>
  
  <p>While this makes sense for some data, incredibly linearly separable data (like iris) should be very learnable for a Keras sequential model. I have tried increasing the number of hidden layers to 32, 64, and 128 and there was no improvement on the accuracy.</p>
  
  <p>Below shows the Iris data (specifically the independent variables) as a function of the species (the dependent variable):</p>
  
  <p><a href="https://i.stack.imgur.com/k3NwV.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/k3NwV.png" alt="Iris data"></a></p>
  
  <p>Why is my model performing so poorly?</p>