import pandas as pd
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.wrappers.scikit_learn import KerasClassifier
from tensorflow.keras.utils import plot_model
from tensorflow.keras import optimizers
from tensorflow.keras import regularizers
from sklearn.model_selection import cross_val_score,train_test_split,KFold
from tensorflow.keras.layers import Dense, Dropout, Flatten, Activation, Conv1D, MaxPooling1D
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix
import itertools
from tensorflow.keras.callbacks import ReduceLROnPlateau
from tensorflow.keras.utils import to_categorical

# prepare the data
all_df = pd.read_excel('C:/Users/admin/Desktop/1-41to94 T7F4ILS 5out.xlsx')
all_df[:2]
cols=['TUAB','TCG','TLCC','TEXGHE','TENGHE','TCAL','TEGKT','FUCCG','FLCCG','FCU','FDF','ILS','output']
all_df=all_df[cols]
ndarray = all_df.values
ndarray.shape
ndarray[:2]

from sklearn import preprocessing
minmax_scale = preprocessing.MinMaxScaler(feature_range=[0,1])
scaledndarray=minmax_scale.fit_transform(ndarray)
scaledndarray[:2]
Label = scaledndarray[:,12]
Features = scaledndarray[:,0:12]

# Complement the dimensions. The added dimensions are in the third dimension
Features = np.expand_dims(Features, axis=2)

# Divide the training set, the test set
Features_train, Features_test, Label_train, Label_test = train_test_split(Features, Label, test_size=0.25, random_state=0)

# create conv1d
model = Sequential()
model.add(Conv1D(128, kernel_size=2, strides=1, padding='same',
                 input_shape=(12,1), kernel_regularizer=regularizers.l2(0.001),
                 activation='relu'))
model.add(Conv1D(128, kernel_size=2, strides=1, padding='same',
                 kernel_regularizer=regularizers.l2(0.001),activation='relu'))
model.add(MaxPooling1D(pool_size=2, strides=1))
model.add(Conv1D(32, kernel_size=2, strides=1, padding='same', 
                 kernel_regularizer=regularizers.l2(0.001),activation='relu'))
model.add(Conv1D(32, kernel_size=2, strides=1, padding='same', 
                 kernel_regularizer=regularizers.l2(0.001),activation='relu'))
model.add(MaxPooling1D(pool_size=2, strides=1))
model.add(Conv1D(8, kernel_size=2, strides=1, padding='same', 
                 kernel_regularizer=regularizers.l2(0.001),activation='relu'))
model.add(Conv1D(8, kernel_size=2, strides=1, padding='same', 
                 kernel_regularizer=regularizers.l2(0.001),activation='relu'))
model.add(MaxPooling1D(pool_size=2, strides=1))
model.add(Flatten())
model.add(Dense(units=320,kernel_initializer='uniform',activation='relu'))
model.add(Dropout(0.15))
model.add(Dense(units=80,kernel_initializer='uniform',activation='relu'))
model.add(Dropout(0.15))
model.add(Dense(units=20,kernel_initializer='uniform',activation='relu'))
model.add(Dropout(0.15))
model.add(Dense(5, activation='softmax'))
plot_model(model, to_file='./model_classifier.png', show_shapes=True) 
# Save the network structure as a picture
print(model.summary()) # Display network structure
model.compile(loss='sparse_categorical_crossentropy',optimizer='adam', 
              metrics=['accuracy'])# Define training mode
    
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2,patience=5, min_lr=0.001)
    
train_history =model.fit(x=Features_train,y=Label_train, batch_size=32, 
                         epochs=300, validation_split=0.2, verbose=2, 
                         callbacks=[reduce_lr])
 
def show_train_history(train_history,train,validation):
    plt.plot(train_history.history[train], '^',  color='deepskyblue')
    plt.plot(train_history.history[validation], '-',  linewidth=2.5, color='crimson')
    plt.title('Train History', fontsize=14)
    plt.ylabel(train, fontsize=14)
    plt.xlabel('Epoch', fontsize=14)
    plt.legend(['Train(CNN-MLP)','Validation(CNN-MLP)'], fontsize=14, loc='center right')
    plt.show()
show_train_history(train_history,'accuracy','val_accuracy')
show_train_history(train_history,'loss','val_loss')
scores= model.evaluate(x=Features_test,y=Label_test)
print()
print('accuracy=',scores[1])
prediction = model.predict(Features_test)
prediction[:10]
print(model.summary())