0
$\begingroup$

I am working on a regression task where the model has to predict two values at the same time. The idea is that the dataset consists of 16 features, where the first 8 features represent the first value that the model needs to predict and the next 8 features represent the second position. How should I go about doing this and adapt my model? Initially the model predicted just one single value from a dataset of 8 features

This is how one row of the data set looks like for example:

0,003345971 0,003345971 0,003345971 0,003345971 0,003345971 0,003346 0,003346 0,003346 0,003525485 0,00445148 0,00349107 0,00417936 0,00370763 0,00390843 0,00400138 0,00362335

This is how part of the output file looks like, The two columns are the same

First column Second column
0 0
0.002 0.002
0.004 0.004
0.006 0.006
0.008 0.008
0.01 0.01
0.012 0.012

This is how the model architecture for predicting one single value looks like

def build_model(n_steps, n_features):
    model = Sequential()

    model.add(Conv1D(filters=64, kernel_size=3, input_shape=(n_steps, n_features), padding='Same', activation='relu'))
    model.add(Conv1D(filters=64, kernel_size=3, padding='Same', activation='relu'))
    model.add(MaxPooling1D(pool_size=2))

    model.add(Conv1D(filters=128, kernel_size=3, padding='Same', activation='relu'))
    model.add(Conv1D(filters=128, kernel_size=3, padding='Same', activation='relu'))
    model.add(MaxPooling1D(pool_size=2))

    model.add(Conv1D(filters=256, kernel_size=3, padding='Same', activation='relu'))
    model.add(Conv1D(filters=256, kernel_size=3, padding='Same', activation='relu'))
    model.add(Conv1D(filters=256, kernel_size=3, padding='Same', activation='relu'))
    model.add(MaxPooling1D(pool_size=2))


    model.add(Flatten())
    model.add(Dense(1096, activation='relu'))

    model.add(Dense(1))

    optimizer = Adam(learning_rate=0.0005)

    model.compile(optimizer=optimizer, loss='mse', metrics=['mae'])
    return model

This is how I train the model and the callbacks used. Using EarlyStopping does not seem to make the model better


def train_model(model, x_train, y_train, x_val, y_val, batch_size):
    early_stopping = EarlyStopping(monitor='val_loss', patience=100, verbose=1)
    learning_rate_reduction = ReduceLROnPlateau(monitor='val_loss', patience=3, verbose=1, factor=0.5, min_lr=0.00001)

    log_dir = "logs/fit/" + datetime.now().strftime("%Y%m%d-%H%M%S")
    tensorboard_callback = TensorBoard(log_dir=log_dir, histogram_freq=1)

    history = model.fit(
        x_train, y_train, epochs=1000,
        verbose=1,
        validation_data=(x_val, y_val),
        callbacks=[learning_rate_reduction, early_stopping],
        batch_size=batch_size
    )

    avg_mae = np.mean(history.history['mae'])
    print(f"Average MAE: {avg_mae}")

    plot_history(history)

    # return history
    return history, history.history['val_mae'], history.history['val_loss']

This is the function that splits the data

def split_data(idata, odata):
    x = idata.iloc[:, 0:].values
    y = odata.iloc[:, np.r_[0, 1]].values


    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.1, random_state=0)

    return np.asarray(x_train).astype(np.float32), np.asarray(y_train).astype(np.float32), np.asarray(x_test).astype(
        np.float32), np.asarray(y_test).astype(np.float32)
```
$\endgroup$

1 Answer 1

0
$\begingroup$

As far as I know, you can't get multiple outputs from keras.sequential and need as many output layers as outputs, creating branching into your NN. Something like this :

def build_model(n_steps, n_features):

    inputs = tf.keras.Input(shape=(n_steps, n_features))
    x = tf.keras.layers.Conv1D(filters=64, kernel_size=3,padding='Same', activation='relu')(inputs)
    x = tf.keras.layers.Conv1D(filters=64, kernel_size=3, padding='Same', activation='relu')(x)
    x = tf.keras.layers.MaxPooling1D(pool_size=2)(x)

    x = tf.keras.layers.Conv1D(filters=128, kernel_size=3, padding='Same', activation='relu')(x)
    x = tf.keras.layers.Conv1D(filters=128, kernel_size=3, padding='Same', activation='relu')(x)
   x = tf.keras.layers.MaxPooling1D(pool_size=2)(x)

   x = tf.keras.layers.Conv1D(filters=256, kernel_size=3, padding='Same', activation='relu')(x)
    x = tf.keras.layers.Conv1D(filters=256, kernel_size=3, padding='Same', activation='relu')(x)
    x = tf.keras.layers.Conv1D(filters=256, kernel_size=3, padding='Same', activation='relu')(x)
    x = tf.keras.layers.MaxPooling1D(pool_size=2)(x)


    x = tf.keras.layers.Flatten()(x)
    x = tf.keras.layers.Dense(1096, activation='relu')(x)

    outupt_1 = tf.keras.layers.Dense(1)(x)
    outupt_2 = tf.keras.layers.Dense(1)(x)

    model = tf.keras.Model(inputs=inputs, outputs=[outupt_1,outupt_2])

    optimizer = Adam(learning_rate=0.0005)

    model.compile(optimizer=optimizer, loss={'outupt_1': 'mse', 'outupt_1''mse'}, metrics={'outupt_1': 'mae', 'outupt_1''mae'})
    return model
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .