title: How to iterate through tensors in custom loss function?
body: <p>I'm using keras with tensorflow backend. My goal is to query the <code>batchsize</code> of the current batch in a <strong>custom loss</strong> function. This is needed to compute values of the custom loss functions which depend on the index of particular observations. I like to make this clearer given the minimum reproducible examples below.</p>
  
  <p>(BTW: Of course I could use the batch size defined for the training procedure and plugin it's value when defining the custom loss function, but there are some reasons why this can vary, especially if <code>epochsize % batchsize</code> (epochsize modulo batchsize) is unequal zero, then the last batch of an epoch has different size. I didn't found a suitable approach in stackoverflow, especially e. g.
  <a href="https://stackoverflow.com/q/46200080/10099959">Tensor indexing in custom loss function</a> and   <a href="https://stackoverflow.com/q/48524836/10099959">Tensorflow custom loss function in Keras - loop over tensor</a> and <a href="https://stackoverflow.com/q/43327668/10099959">Looping over a tensor</a> because obviously the shape of any tensor can't be inferred when building the graph which is the case for a loss function - shape inference is only possible when evaluating given the data, which is only possible given the graph. Hence I need to tell the custom loss function to do something with particular elements along a certain dimension without knowing the length of the dimension.</p>
  
  <h1>(this is the same in all examples)</h1>
  
  <pre><code>from keras.models import Sequential
  from keras.layers import Dense, Activation
  
  # Generate dummy data
  import numpy as np
  data = np.random.random((1000, 100))
  labels = np.random.randint(2, size=(1000, 1))
  
  model = Sequential()
  model.add(Dense(32, activation='relu', input_dim=100))
  model.add(Dense(1, activation='sigmoid'))
  </code></pre>
  
  <h1>example 1: nothing special without issue, no custom loss</h1>
  
  <pre><code>model.compile(optimizer='rmsprop',
                loss='binary_crossentropy',
                metrics=['accuracy'])    
  
  # Train the model, iterating on the data in batches of 32 samples
  model.fit(data, labels, epochs=10, batch_size=32)
  </code></pre>
  
  <p><em>(Output omitted, this runs perfectily fine)</em></p>
  
  <h1>example 2: nothing special, with a fairly simple custom loss</h1>
  
  <pre><code>def custom_loss(yTrue, yPred):
      loss = np.abs(yTrue-yPred)
      return loss
  
  model.compile(optimizer='rmsprop',
                loss=custom_loss,
                metrics=['accuracy'])
  
  # Train the model, iterating on the data in batches of 32 samples
  model.fit(data, labels, epochs=10, batch_size=32)
  </code></pre>
  
  <p><em>(Output omitted, this runs perfectily fine)</em></p>
  
  <h1>example 3: the issue</h1>
  
  <pre><code>def custom_loss(yTrue, yPred):
      print(yPred) # Output: Tensor("dense_2/Sigmoid:0", shape=(?, 1), dtype=float32)
      n = yPred.shape[0]
      for i in range(n): # TypeError: __index__ returned non-int (type NoneType)
          loss = np.abs(yTrue[i]-yPred[int(i/2)])
      return loss
  
  model.compile(optimizer='rmsprop',
                loss=custom_loss,
                metrics=['accuracy'])
  
  # Train the model, iterating on the data in batches of 32 samples
  model.fit(data, labels, epochs=10, batch_size=32)
  </code></pre>
  
  <p>Of course the tensor has not shape info yet which can't be inferred when building the graph, only at training time. Hence <code>for i in range(n)</code> rises an error. Is there any way to perform this?</p>
  
  <p><strong>The traceback of the output:</strong>
  <a href="https://i.stack.imgur.com/b9eCa.png" rel="noreferrer"><img src="https://i.stack.imgur.com/b9eCa.png" alt="enter image description here"></a></p>
  
  <h1>-------</h1>
  
  <p>BTW here's my true custom loss function in case of any questions. I skipped it above for clarity and simplicity.</p>
  
  <pre><code>def neg_log_likelihood(yTrue,yPred):
      yStatus = yTrue[:,0]
      yTime = yTrue[:,1]    
      n = yTrue.shape[0]    
      for i in range(n):
          s1 = K.greater_equal(yTime, yTime[i])
          s2 = K.exp(yPred[s1])
          s3 = K.sum(s2)
          logsum = K.log(y3)
          loss = K.sum(yStatus[i] * yPred[i] - logsum)
      return loss
  </code></pre>
  
  <p>Here's an image of the partial negative log-likelihood of the cox proportional harzards model. </p>
  
  <p><a href="https://i.stack.imgur.com/jxmXd.png" rel="noreferrer"><img src="https://i.stack.imgur.com/jxmXd.png" alt="enter image description here"></a></p>
  
  <p>This is to clarify a question in the comments to avoid confusion. I don't think it is necessary to understand this in detail to answer the question. </p>