title: Custom loss function for U-net in keras using class weights: `class_weight` not supported for 3+ dimensional targets
body: <p>Here's the code I'm working with (pulled from Kaggle mostly):</p>
  
  <pre><code>inputs = Input((IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS))
  ...
  outputs = Conv2D(4, (1, 1), activation='sigmoid') (c9)
  
  model = Model(inputs=[inputs], outputs=[outputs])
  model.compile(optimizer='adam', loss='dice', metrics=[mean_iou])
  
  results = model.fit(X_train, Y_train, validation_split=0.1, batch_size=8, epochs=30, class_weight=class_weights)
  </code></pre>
  
  <p>I have 4 classes that are very imbalanced. Class A equals 70%, class B = 15%, class C = 10%, and class D = 5%. However, I care most about class D. So I did the following type of calculations: <code>D_weight = A/D = 70/5 = 14</code> and so on for the weight for class B and A. (if there are better methods to select these weights, then feel free)</p>
  
  <p>In the last line, I'm trying to properly set class_weights and I'm doing it as so: <code>class_weights = {0: 1.0, 1: 6, 2: 7, 3: 14}</code>.</p>
  
  <p>However, when I do this, I get the following error. </p>
  
  <blockquote>
    <p><code>class_weight</code> not supported for 3+ dimensional targets.</p>
  </blockquote>
  
  <p>Is it possible that I add a dense layer after the last layer and just use it as a dummy layer so I can pass the class_weights and then only use the output of the last conv2d layer to do the prediction? </p>
  
  <p>If this is not possible, how would I modify the loss function (I'm aware of this <a href="https://stackoverflow.com/a/46505819/8100895">post</a>, however, just passing in the weights in to the loss function won't cut it, because the loss function is called separately for each class) ? Currently, I'm using the following loss function: </p>
  
  <pre><code>def dice_coef(y_true, y_pred):
      smooth = 1.
      y_true_f = K.flatten(y_true)
      y_pred_f = K.flatten(y_pred)
      intersection = K.sum(y_true_f * y_pred_f)
      return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)
  
  def bce_dice_loss(y_true, y_pred):
      return 0.5 * binary_crossentropy(y_true, y_pred) - dice_coef(y_true, y_pred)
  </code></pre>
  
  <p>But I don't see any way in which I can input class weights. If someone wants the full working code see this <a href="https://www.kaggle.com/mauddib/data-science-bowl-tutorial-using-cnn-tensorflow" rel="noreferrer">post</a>. But remember to change the final conv2d layer's num classes to 4 instead of 1. </p>