mirror of
https://github.com/sbrl/research-rainfallradar
synced 2024-11-22 09:13:01 +00:00
dlr CHANGE: Add optional log(cosh(dice_loss))
Ref https://doi.org/10.1109/cibcb48159.2020.9277638
This commit is contained in:
parent
f25d1b5b1a
commit
c5fc62c411
3 changed files with 14 additions and 6 deletions
|
@ -37,6 +37,7 @@ show_help() {
|
||||||
echo -e " NO_REMOVE_ISOLATED_PIXELS Set to any value to avoid the engine from removing isolated pixels - that is, water pixels with no other surrounding pixels, either side to side to diagonally." >&2;
|
echo -e " NO_REMOVE_ISOLATED_PIXELS Set to any value to avoid the engine from removing isolated pixels - that is, water pixels with no other surrounding pixels, either side to side to diagonally." >&2;
|
||||||
echo -e " EPOCHS The number of epochs to train for." >&2;
|
echo -e " EPOCHS The number of epochs to train for." >&2;
|
||||||
echo -e " LOSS The loss function to use. Default: cross-entropy (possible values: cross-entropy, cross-entropy-dice)." >&2;
|
echo -e " LOSS The loss function to use. Default: cross-entropy (possible values: cross-entropy, cross-entropy-dice)." >&2;
|
||||||
|
echo -e " DICE_LOG_COSH When in cross-entropy-dice mode, in addition do loss = cel + log(cosh(dice_loss)) instead of just loss = cel + dice_loss." >&2;
|
||||||
echo -e " PATH_CHECKPOINT The path to a checkcpoint to load. If specified, a model will be loaded instead of being trained." >&2;
|
echo -e " PATH_CHECKPOINT The path to a checkcpoint to load. If specified, a model will be loaded instead of being trained." >&2;
|
||||||
echo -e " LEARNING_RATE The learning rate to use. Default: 0.001." >&2;
|
echo -e " LEARNING_RATE The learning rate to use. Default: 0.001." >&2;
|
||||||
echo -e " PREDICT_COUNT The number of items from the (SCRAMBLED) dataset to make a prediction for." >&2;
|
echo -e " PREDICT_COUNT The number of items from the (SCRAMBLED) dataset to make a prediction for." >&2;
|
||||||
|
@ -69,7 +70,7 @@ echo -e ">>> DIR_OUTPUT: ${DIR_OUTPUT}";
|
||||||
echo -e ">>> Additional args: ${ARGS}";
|
echo -e ">>> Additional args: ${ARGS}";
|
||||||
|
|
||||||
export PATH=$HOME/software/bin:$PATH;
|
export PATH=$HOME/software/bin:$PATH;
|
||||||
export IMAGE_SIZE BATCH_SIZE DIR_RAINFALLWATER PATH_HEIGHTMAP PATH_COLOURMAP STEPS_PER_EPOCH DIR_OUTPUT PATH_CHECKPOINT EPOCHS PREDICT_COUNT NO_REMOVE_ISOLATED_PIXELS LOSS LEARNING_RATE;
|
export IMAGE_SIZE BATCH_SIZE DIR_RAINFALLWATER PATH_HEIGHTMAP PATH_COLOURMAP STEPS_PER_EPOCH DIR_OUTPUT PATH_CHECKPOINT EPOCHS PREDICT_COUNT NO_REMOVE_ISOLATED_PIXELS LOSS LEARNING_RATE DICE_LOG_COSH;
|
||||||
|
|
||||||
echo ">>> Installing requirements";
|
echo ">>> Installing requirements";
|
||||||
conda run -n py38 pip install -q -r requirements.txt;
|
conda run -n py38 pip install -q -r requirements.txt;
|
||||||
|
|
|
@ -47,6 +47,7 @@ STEPS_PER_EPOCH = int(os.environ["STEPS_PER_EPOCH"]) if "STEPS_PER_EPOCH" in os.
|
||||||
REMOVE_ISOLATED_PIXELS = False if "NO_REMOVE_ISOLATED_PIXELS" in os.environ else True
|
REMOVE_ISOLATED_PIXELS = False if "NO_REMOVE_ISOLATED_PIXELS" in os.environ else True
|
||||||
EPOCHS = int(os.environ["EPOCHS"]) if "EPOCHS" in os.environ else 50
|
EPOCHS = int(os.environ["EPOCHS"]) if "EPOCHS" in os.environ else 50
|
||||||
LOSS = os.environ["LOSS"] if "LOSS" in os.environ else "cross-entropy-dice"
|
LOSS = os.environ["LOSS"] if "LOSS" in os.environ else "cross-entropy-dice"
|
||||||
|
DICE_LOG_COSH = True if "DICE_LOG_COSH" in os.environ else False
|
||||||
LEARNING_RATE = float(os.environ["LEARNING_RATE"]) if "LEARNING_RATE" in os.environ else 0.001
|
LEARNING_RATE = float(os.environ["LEARNING_RATE"]) if "LEARNING_RATE" in os.environ else 0.001
|
||||||
|
|
||||||
DIR_OUTPUT=os.environ["DIR_OUTPUT"] if "DIR_OUTPUT" in os.environ else f"output/{datetime.utcnow().date().isoformat()}_deeplabv3plus_rainfall_TEST"
|
DIR_OUTPUT=os.environ["DIR_OUTPUT"] if "DIR_OUTPUT" in os.environ else f"output/{datetime.utcnow().date().isoformat()}_deeplabv3plus_rainfall_TEST"
|
||||||
|
@ -184,7 +185,7 @@ else:
|
||||||
if PATH_CHECKPOINT is None:
|
if PATH_CHECKPOINT is None:
|
||||||
loss_fn = None
|
loss_fn = None
|
||||||
if LOSS == "cross-entropy-dice":
|
if LOSS == "cross-entropy-dice":
|
||||||
loss_fn = LossCrossEntropyDice()
|
loss_fn = LossCrossEntropyDice(log_cosh=DICE_LOG_COSH)
|
||||||
elif LOSS == "cross-entropy":
|
elif LOSS == "cross-entropy":
|
||||||
loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
|
loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -16,7 +16,6 @@ def dice_loss(y_true, y_pred):
|
||||||
y_pred = tf.math.sigmoid(y_pred)
|
y_pred = tf.math.sigmoid(y_pred)
|
||||||
numerator = 2 * tf.reduce_sum(y_true * y_pred)
|
numerator = 2 * tf.reduce_sum(y_true * y_pred)
|
||||||
denominator = tf.reduce_sum(y_true + y_pred)
|
denominator = tf.reduce_sum(y_true + y_pred)
|
||||||
|
|
||||||
return 1 - numerator / denominator
|
return 1 - numerator / denominator
|
||||||
|
|
||||||
class LossCrossEntropyDice(tf.keras.losses.Loss):
|
class LossCrossEntropyDice(tf.keras.losses.Loss):
|
||||||
|
@ -24,20 +23,27 @@ class LossCrossEntropyDice(tf.keras.losses.Loss):
|
||||||
Combines the two with mean.
|
Combines the two with mean.
|
||||||
The ground truth labels should sparse, NOT one-hot. The predictions should be one-hot, NOT sparse.
|
The ground truth labels should sparse, NOT one-hot. The predictions should be one-hot, NOT sparse.
|
||||||
@source https://lars76.github.io/2018/09/27/loss-functions-for-segmentation.html#9
|
@source https://lars76.github.io/2018/09/27/loss-functions-for-segmentation.html#9
|
||||||
|
log_cosh (bool): Whether to do log(cosh(dice_loss)) instead of just dice_loss on its own. Ref https://doi.org/10.1109/cibcb48159.2020.9277638
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, log_cosh=True, **kwargs):
|
||||||
super(LossCrossEntropyDice, self).__init__(**kwargs)
|
super(LossCrossEntropyDice, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
self.param_log_cosh = log_cosh
|
||||||
|
|
||||||
def call(self, y_true, y_pred):
|
def call(self, y_true, y_pred):
|
||||||
y_true = tf.cast(y_true, tf.float32)
|
y_true = tf.cast(y_true, tf.float32)
|
||||||
y_true = tf.one_hot(tf.cast(y_true, dtype=tf.int32), 2) # Input is sparse
|
y_true = tf.one_hot(tf.cast(y_true, dtype=tf.int32), 2) # Input is sparse
|
||||||
o = tf.nn.sigmoid_cross_entropy_with_logits(y_true, y_pred) + dice_loss(y_true, y_pred)
|
|
||||||
|
cel = tf.nn.sigmoid_cross_entropy_with_logits(y_true, y_pred)
|
||||||
|
dice = dice_loss(y_true, y_pred)
|
||||||
|
|
||||||
|
o = cel + dice
|
||||||
return tf.reduce_mean(o)
|
return tf.reduce_mean(o)
|
||||||
|
|
||||||
def get_config(self):
|
def get_config(self):
|
||||||
config = super(LossCrossEntropyDice, self).get_config()
|
config = super(LossCrossEntropyDice, self).get_config()
|
||||||
config.update({
|
config.update({
|
||||||
|
"log_cosh": self.param_log_cosh
|
||||||
})
|
})
|
||||||
return config
|
return config
|
||||||
|
|
Loading…
Reference in a new issue