0

I have a regression neural network with ten input features and three outputs. But all ten features do not have the same importance in loss function calculation (mean square error). So I want to define specific coefficients for each input feature to increase their role in the loss function.

Consider we define coefficients in an array: coeff=[5,20,2,1,4,5,6,2,9,15]. When mean squared error is measuring the distances of input features, for example, if the distance of the second feature is '60', this distance is multiplied by coefficient '20' from coeff array.

I guess I need to define a custom loss function, but how to pass the defined "coeff" array and multiply its elements with input features?

Updated

I guess my idea is similar to this code and this code, but I am not sure. however, I was unable to run the first one and got errors.

from numpy import mean
from numpy import std
from sklearn.datasets import make_regression
from sklearn.model_selection import RepeatedKFold
from keras.models import Sequential
from keras.layers import Dense
 
# get the dataset
def get_dataset():
    X, y = make_regression(n_samples=1000, n_features=10, n_informative=5, n_targets=3, random_state=2)
    return X, y
 
# get the model
def get_model(n_inputs, n_outputs):
    model = Sequential()
    model.add(Dense(20, input_dim=n_inputs, kernel_initializer='he_uniform', activation='relu'))
    model.add(Dense(n_outputs))
    model.compile(loss='mse', optimizer='adam')
    return model
 
# evaluate a model using repeated k-fold cross-validation
def evaluate_model(X, y):
    results = list()
    n_inputs, n_outputs = X.shape[1], y.shape[1]
    # define evaluation procedure
    cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)
    # enumerate folds
    for train_ix, test_ix in cv.split(X):
        # prepare data
        X_train, X_test = X[train_ix], X[test_ix]
        y_train, y_test = y[train_ix], y[test_ix]
        # define model
        model = get_model(n_inputs, n_outputs)
        # fit model
        model.fit(X_train, y_train, verbose=0, epochs=100)
        # evaluate model on test set
        mse = model.evaluate(X_test, y_test, verbose=0)
        # store result
        print('>%.3f' % mse)
        results.append(mse)
    return results
 
# load dataset
X, y = get_dataset()
# evaluate model
results = evaluate_model(X, y)
# summarize performance
print('MSE: %.3f (%.3f)' % (mean(results), std(results)))
Aref Hemati
  • 337
  • 2
  • 14
  • 1
    The loss function is calculated based on the outputs, not the inputs – AndrzejO Nov 14 '22 at 02:59
  • Dear @AndrzejO, thanks for your comment. I updated my question with two samples that implemented my idea. They pass coefficients to loss function and multiply them with mse results for each feature. is there any problem? – Aref Hemati Nov 15 '22 at 20:43

1 Answers1

0

If you use the functional api, then you could add a custom loss function with the model.add_loss function, within the model. Your loss function can then use the model inputs and outputs and anything in your model. The problem with this approach is, that in the model you don't have the 'true' y values. So you would need to add an additional input to your model, and pass the y values to the model – but just for the loss calculation. Something like this:

inputs = Input(shape=(n_inputs))
x = Dense(20, ...)(model_inputs)
outputs = Dense(n_outputs)(x)
y_true = Input(shape=(n_outputs))
modelx = Model(inputs=[inputs, y_true], outputs=outputs)
modelx.add_loss(your_loss_function(y_true=y_true, y_pred=outputs, inputs=inputs)

Since you already added the loss to the model, you compile it without any loss:

modelx.compile(loss=None, optimizer='adam')

When you fit the model, you need to pass the y values to the model inputs.

modelx.fit(x=[X_train, y_train], y=y_train, verbose=0, epochs=100)

When you want a model with just the X values as input, for example for prediction, you can create it like so:

model = Model(modelx.input[0], modelx.output)
AndrzejO
  • 1,502
  • 1
  • 9
  • 12
  • Regarding the following: "So you would need to add an additional input to your model, and pass the y values to the model – but just for the loss calculation." I don't think that is a good practice... The only time one can refer to labels is at the time of calculating loss(y_true, y_pred). Other than that, no information related to output should leak into the model let alone the label itself. The other point here is that, how would one use a model that gets labels as input? – learner Nov 16 '22 at 03:00
  • @learner "I don't think that is a good practice" – I agree, but don't know any other method to get the input into the loss function. That's why I name it `y_true` and define it after the `outputs = ` line. "how would one use a model that gets labels as input?" – see the last line of my answer – AndrzejO Nov 16 '22 at 05:11