import tensorflow.keras as keras
from preprocess import generate_training_sequences, SEQUENCE_LENGTH

OUTPUT_UNITS = 38
NUM_UNITS = [256]
LOSS = "sparse_categorical_crossentropy"
LEARNING_RATE = 0.001
EPOCHS = 90
BATCH_SIZE = 64
SAVE_MODEL_PATH = "model.h5"


def build_model(output_units, num_units, loss, learning_rate):
    """Builds and compiles model

    :param output_units (int): Num output units
    :param num_units (list of int): Num of units in hidden layers
    :param loss (str): Type of loss function to use
    :param learning_rate (float): Learning rate to apply

    :return model (tf model): Where the magic happens :D
    """

    # create the model architecture
    model = keras.Sequential()

    activation_f = 'relu'
    n_of_timesteps = 32
    kernel_size = 3
    # activation_f = 'sigmoid'
    # activation_f = 'tanh'

    # Parameters explanation: https://keras.io/api/layers/core_layers/embedding/
    # model.add(keras.layers.Embedding(num_units[0], output_units, input_length=n_of_timesteps * 2,trainable=True))
    model.add(keras.layers.Input(shape=(None, output_units)))

    # Parameters explanation: https://keras.io/api/layers/convolution_layers/convolution1d/
    model.add(keras.layers.Conv1D(n_of_timesteps*2*2,kernel_size, padding='causal',activation=activation_f))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.MaxPool1D(2))

    model.add(keras.layers.Conv1D(n_of_timesteps*4*2,kernel_size, activation=activation_f,dilation_rate=2,padding='causal'))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.MaxPool1D(2))

    model.add(keras.layers.Conv1D(n_of_timesteps*8*2,kernel_size, activation=activation_f,dilation_rate=4,padding='causal'))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.MaxPool1D(2))

    #model.add(Conv1D(256,5,activation=activation_f))
    model.add(keras.layers.GlobalMaxPool1D())

    # Parameters explanation: https://keras.io/api/layers/core_layers/dense/
    # 256 -> 512
    model.add(keras.layers.Dense(512, activation=activation_f))
    model.add(keras.layers.Dense(output_units, activation='softmax'))

    model.compile(loss='sparse_categorical_crossentropy', optimizer='adam')

    # compile model
    model.compile(loss=loss,
                  optimizer=keras.optimizers.Adam(learning_rate=learning_rate),
                  metrics=["accuracy"])

    model.summary()

    return model


def train(output_units=OUTPUT_UNITS, num_units=NUM_UNITS, loss=LOSS, learning_rate=LEARNING_RATE):
    """Train and save TF model.

    :param output_units (int): Num output units
    :param num_units (list of int): Num of units in hidden layers
    :param loss (str): Type of loss function to use
    :param learning_rate (float): Learning rate to apply
    """

    # generate the training sequences
    inputs, targets = generate_training_sequences(SEQUENCE_LENGTH)

    # build the network
    model = build_model(output_units, num_units, loss, learning_rate)

    # train the model
    model.fit(inputs, targets, epochs=EPOCHS, batch_size=BATCH_SIZE)

    # save the model
    model.save(SAVE_MODEL_PATH)


if __name__ == "__main__":
    train()
import tensorflow.keras as keras
from preprocess import generate_training_sequences, SEQUENCE_LENGTH

OUTPUT_UNITS = 38
NUM_UNITS = [256]
LOSS = "sparse_categorical_crossentropy"
LEARNING_RATE = 0.001
EPOCHS = 90
BATCH_SIZE = 64
SAVE_MODEL_PATH = "model.h5"


def build_model(output_units, num_units, loss, learning_rate):
    """Builds and compiles model

    :param output_units (int): Num output units
    :param num_units (list of int): Num of units in hidden layers
    :param loss (str): Type of loss function to use
    :param learning_rate (float): Learning rate to apply

    :return model (tf model): Where the magic happens :D
    """

    # create the model architecture
    model = keras.Sequential()

    activation_f = 'relu'
    n_of_timesteps = 32
    kernel_size = 3
    # activation_f = 'sigmoid'
    # activation_f = 'tanh'

    # Parameters explanation: https://keras.io/api/layers/core_layers/embedding/
    # model.add(keras.layers.Embedding(num_units[0], output_units, input_length=n_of_timesteps * 2,trainable=True))
    model.add(keras.layers.Input(shape=(None, output_units)))

    # Parameters explanation: https://keras.io/api/layers/convolution_layers/convolution1d/
    model.add(keras.layers.Conv1D(n_of_timesteps*2*2,kernel_size, padding='causal',activation=activation_f))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.MaxPool1D(2))

    model.add(keras.layers.Conv1D(n_of_timesteps*4*2,kernel_size, activation=activation_f,dilation_rate=2,padding='causal'))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.MaxPool1D(2))

    model.add(keras.layers.Conv1D(n_of_timesteps*8*2,kernel_size, activation=activation_f,dilation_rate=4,padding='causal'))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.MaxPool1D(2))

    #model.add(Conv1D(256,5,activation=activation_f))
    model.add(keras.layers.GlobalMaxPool1D())

    # Parameters explanation: https://keras.io/api/layers/core_layers/dense/
    # 256 -> 512
    model.add(keras.layers.Dense(512, activation=activation_f))
    model.add(keras.layers.Dense(output_units, activation='softmax'))

    model.compile(loss='sparse_categorical_crossentropy', optimizer='adam')

    # compile model
    model.compile(loss=loss,
                  optimizer=keras.optimizers.Adam(learning_rate=learning_rate),
                  metrics=["accuracy"])

    model.summary()

    return model


def train(output_units=OUTPUT_UNITS, num_units=NUM_UNITS, loss=LOSS, learning_rate=LEARNING_RATE):
    """Train and save TF model.

    :param output_units (int): Num output units
    :param num_units (list of int): Num of units in hidden layers
    :param loss (str): Type of loss function to use
    :param learning_rate (float): Learning rate to apply
    """

    # generate the training sequences
    inputs, targets = generate_training_sequences(SEQUENCE_LENGTH)

    # build the network
    model = build_model(output_units, num_units, loss, learning_rate)

    # train the model
    model.fit(inputs, targets, epochs=EPOCHS, batch_size=BATCH_SIZE)

    # save the model
    model.save(SAVE_MODEL_PATH)


if __name__ == "__main__":
    train()
Builds and compiles model      :param output_units (int): Num output units     :param num_units (list of int): Num of units in hidden layers     :param loss (str): Type of loss function to use     :param learning_rate (float): Learning rate to apply      :return model (tf model): Where the magic happens :D # create the model architecture # activation_f = 'sigmoid' # activation_f = 'tanh' # Parameters explanation: https://keras.io/api/layers/core_layers/embedding/ # model.add(keras.layers.Embedding(num_units[0], output_units, input_length=n_of_timesteps * 2,trainable=True)) # Parameters explanation: https://keras.io/api/layers/convolution_layers/convolution1d/ #model.add(Conv1D(256,5,activation=activation_f)) # Parameters explanation: https://keras.io/api/layers/core_layers/dense/ # 256 -> 512 # compile model Train and save TF model.      :param output_units (int): Num output units     :param num_units (list of int): Num of units in hidden layers     :param loss (str): Type of loss function to use     :param learning_rate (float): Learning rate to apply # generate the training sequences # build the network # train the model # save the model