Skip to main content
2 of 2
added 119 characters in body
Kodiologist
  • 20.6k
  • 2
  • 44
  • 78

Bridgeburners's comment is correct: in this model, softmax always predicts 1 (because there's only one output node). I changed to sigmoid activation as I had used originally, then found another problem: under sigmoid, model.predict returns probabilities, not classes, so the predictions need to thresholded first. With these bugs fixed, and epochs cranked up to 300, I'm now getting 99% accuracy.

import numpy as np

X = np.array([[c == '1' for c in line] for line in [
    '1101111111011111111111111111111100011010111110010011111111111111011111110111111111111101111111111110',
    '0011111001000001011010001011000100010001110011011101111111110000111111001001001001110011011101111000',
    '0111101111010000000000111110001101000010110000101111010111100110010110000110011000001010000000000110']])
X = X.T
n_cases = X.shape[0]

y = np.sum(X, axis = 1) > 1

np.random.seed(123)
n_folds = 10
folds = np.repeat(range(n_folds), np.ceil(n_cases / n_folds))[
    range(n_cases)]
np.random.shuffle(folds)

y_pred = np.zeros_like(y)

for fold_i in range(n_folds):
    print("Fold", fold_i)

    import os; os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Dense, Activation

    model = Sequential([
        Dense(10, activation = "relu"),
        Dense(1, activation = "sigmoid")])
    model.compile(
        optimizer = "rmsprop",
        loss = "binary_crossentropy")
    model.fit(
        X[folds != fold_i],
        y[folds != fold_i],
        verbose = False,
        epochs = 300,
        batch_size = np.sum(folds != fold_i) // 5 + 1)

    print("Training accuracy:", np.mean(
       y[folds != fold_i] == (model.predict(X[folds != fold_i])[:,0] > .5)))

    y_pred[folds == fold_i] = (model.predict(X[folds == fold_i])[:,0] > .5)

print(np.mean(y_pred == y))
Kodiologist
  • 20.6k
  • 2
  • 44
  • 78