#
# trains a simple neural network to recognize 1D sequences of data
# as one of two classes:  increasing, or decreasing
#
# the output weights can be viewed to understand the learned templates
#

# TensorFlow, keras, numpy
import tensorflow as tf
from tensorflow import keras
import numpy as np

# go step-by-step through the process of file parsing,
# separating data from classes, and normalizing, for tutorial

# open file
f=open('train-data.txt','r')
d=[[int(x) for x in line.split()] for line in f]
f.close()

# copy to classes and data
classes=[]
data=[]

for a in range(0,len(d)):
  classes.append(d[a][0])
  row=[]
  for b in range(1,len(d[a])):
    row.append(d[a][b])
  data.append(row)

#print(classes)
#print(data)

# normalize each row of data
normdata=[]
for a in range(0,len(data)):
  norm=[]
  s=min(data[a])
  t=max(data[a])
  for b in range(0,len(data[a])):
    norm.append((float(data[a][b])-float(s))/(float(t)-float(s)))
  normdata.append(norm)

#print(normdata)

classes=np.array(classes)
data=np.array(normdata)

print("data has shape", data.shape)
print("classes has shape ", classes.shape)

# note this example does not need this, but it's here for tutorial
# convert classes to one hot vectors (each vector position is a class)
# i.e. convert classes like 1 2 3 4 to [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]
# vect_classes = keras.utils.to_categorical(classes, num_classes=None)

model = keras.Sequential([
# cannot have InputLayer() or network will not save/load (bug in early TF)
# instead, specify input_shape in first real layer
#    keras.layers.InputLayer(input_shape=(20,)),
    keras.layers.Dense(2, input_shape=(20,), activation='sigmoid')
    ])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

print("Training")
metrics = model.fit(data, classes, epochs=50, verbose=2,
    validation_split=0.2)
print("Max value: ", max(metrics.history['accuracy']), " at epoch", np.argmax(metrics.history['accuracy']))

print("Testing")
test_loss, test_acc = model.evaluate(data, classes)
print('Test accuracy:', test_acc)

w=model.get_weights()
print(w)

tf.keras.models.save_model(model,'simslope.keras',True,True)

