title: Implementing custom objective function in keras
body: <p>I am trying to implement my own cost function, specifically the one below:</p>
  
  <p><a href="https://i.stack.imgur.com/fFxJ5.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/fFxJ5.jpg" alt="enter image description here"></a></p>
  
  <p>Now I know this question has been asked several times on this site and the answers I read are typically something like below:</p>
  
  <pre><code>def custom_objective(y_true, y_pred):
  ....
  return L
  </code></pre>
  
  <p>where people always seem to use <code>y_true</code> and <code>y_pred</code> and then say that you just have to compile the model <code>model.compile(loss=custom_objective)</code> and go from there. No one really mentions that somewhere in the code that <code>y_true=something</code> and <code>y_pred=something</code>. Is that something I have to specify in my model?</p>
  
  <h1>My code</h1>
  
  <p>Not sure if I am using <code>.predict()</code> correctly to get the running predictions from the model as it is training:</p>
  
  <pre><code>params = {'lr': 0.0001,
   'batch_size': 30,
   'epochs': 400,
   'dropout': 0.2,
   'optimizer': 'adam',
   'losses': 'avg_partial_likelihood',
   'activation':'relu',
   'last_activation': 'linear'}
  
  def model(x_train, y_train, x_val, y_val):
  
      l2_reg = 0.4
      kernel_init ='he_uniform' 
      bias_init ='he_uniform'
      layers=[20, 20, 1]
  
      model = Sequential()
  
      # layer 1
      model.add(Dense(layers[0], input_dim=x_train.shape[1],
                      W_regularizer=l2(l2_reg),
                      kernel_initializer=kernel_init,
                      bias_initializer=bias_init))
  
  
      model.add(BatchNormalization(axis=-1, momentum=momentum, center=True))
  
      model.add(Activation(params['activation']))
  
      model.add(Dropout(params['dropout']))
  
      # layer 2+    
      for layer in range(0, len(layers)-1):
  
          model.add(Dense(layers[layer+1], W_regularizer=l2(l2_reg),
                          kernel_initializer=kernel_init,
                          bias_initializer=bias_init))
  
  
          model.add(BatchNormalization(axis=-1, momentum=momentum, center=True))
  
          model.add(Activation(params['activation']))
  
          model.add(Dropout(params['dropout']))
  
      # Last layer
      model.add(Dense(layers[-1], activation=params['last_activation'],
                      kernel_initializer=kernel_init,
                      bias_initializer=bias_init))
  
      model.compile(loss=params['losses'],
                    optimizer=keras.optimizers.adam(lr=params['lr']),
                    metrics=['accuracy'])
  
      history = model.fit(x_train, y_train, 
                          validation_data=[x_val, y_val],
                          batch_size=params['batch_size'],
                          epochs=params['epochs'],
                          verbose=1)
  
      y_pred = model.predict(x_train, batch_size=params['batch_size'])
  
      history_dict = history.history
  
      model_output = {'model':model, 
                      'history_dict':history_dict,
                      'log_risk':y_pred}
  
      return model_output
  </code></pre>
  
  <p>then create the model:</p>
  
  <pre><code>model(x_train, y_train, x_val, y_val)
  </code></pre>
  
  <h1>My objective function thus far</h1>
  
  <p>'log_risk' would be <code>y_true</code> and <code>x_train</code> would be used to calculate <code>y_pred</code>:</p>
  
  <pre><code>def avg_partial_likelihood(x_train, log_risk):
  
  
  
      from lifelines import CoxPHFitter
  
      cph = CoxPHFitter()
  
      cph.fit(x_train, duration_col='survival_fu_combine', event_col='death',
             show_progress=False)
  
      # obtain exp(hx)
  
      cph_output = pd.DataFrame(cph.summary).T
  
      # summing hazard ratio
  
      hazard_ratio_sum = cph_output.iloc[1,].sum()
  
      # -log(sum(exp(hxj)))
  
      neg_log_sum = -np.log(hazard_ratio_sum)
  
      # sum of positive events (death==1)
  
      sum_noncensored_events = (x_train.death==1).sum()
  
      # neg_likelihood
  
      neg_likelihood = -(log_risk + neg_log_sum)/sum_noncensored_events
  
      return neg_likelihood
  </code></pre>
  
  <h1>Error if I try to run</h1>
  
  <pre><code>  AttributeError                            Traceback (most recent call last)
  &lt;ipython-input-26-cf0236299ad5&gt; in &lt;module&gt;()
  ----&gt; 1 model(x_train, y_train, x_val, y_val)
  
  &lt;ipython-input-25-d0f9409c831a&gt; in model(x_train, y_train, x_val, y_val)
       45     model.compile(loss=avg_partial_likelihood,
       46                   optimizer=keras.optimizers.adam(lr=params['lr']),
  ---&gt; 47                   metrics=['accuracy'])
       48 
       49     history = model.fit(x_train, y_train, 
  
  ~\Anaconda3\lib\site-packages\keras\engine\training.py in compile(self, optimizer, loss, metrics, loss_weights, sample_weight_mode, weighted_metrics, target_tensors, **kwargs)
      331                 with K.name_scope(self.output_names[i] + '_loss'):
      332                     output_loss = weighted_loss(y_true, y_pred,
  --&gt; 333                                                 sample_weight, mask)
      334                 if len(self.outputs) &gt; 1:
      335                     self.metrics_tensors.append(output_loss)
  
  ~\Anaconda3\lib\site-packages\keras\engine\training_utils.py in weighted(y_true, y_pred, weights, mask)
      401         """
      402         # score_array has ndim &gt;= 2
  --&gt; 403         score_array = fn(y_true, y_pred)
      404         if mask is not None:
      405             # Cast the mask to floatX to avoid float64 upcasting in Theano
  
  &lt;ipython-input-23-ed57799a1f9d&gt; in avg_partial_likelihood(x_train, log_risk)
       27 
       28     cph.fit(x_train, duration_col='survival_fu_combine', event_col='death',
  ---&gt; 29            show_progress=False)
       30 
       31     # obtain exp(hx)
  
  ~\Anaconda3\lib\site-packages\lifelines\fitters\coxph_fitter.py in fit(self, df, duration_col, event_col, show_progress, initial_beta, strata, step_size, weights_col)
       90         """
       91 
  ---&gt; 92         df = df.copy()
       93 
       94         # Sort on time
  
  AttributeError: 'Tensor' object has no attribute 'copy'
  </code></pre>