Source code for preprocessing.unet

"""
====
Unet
====

Este archivo contiene funciones para el cálculo del coeficiente Dice como
métrica y como función de costo, y para la construcción de modelos de red
neuronal U-Net.
"""

import numpy as np
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dropout, Conv2D, concatenate
from tensorflow.keras.layers import Conv2DTranspose, MaxPooling2D
from tensorflow.keras.optimizers import Adam
from tensorflow.keras import backend as K


[docs]class Unet:
[docs] def __new__(self) -> Model: """ Implementación del modelo de red neuronal U-Net. Returns ------- model Modelo de red neuronal U-Net. """ # Etapa de contracción entrada = Input((180, 320, 1)) # Bloque 1 conv1 = Conv2D( 32, (3, 3), activation='relu', padding='same')(entrada) conv1 = Conv2D( 32, (3, 3), activation='relu', padding='same')(conv1) pool1 = MaxPooling2D((2, 2), strides=2, padding='same')(conv1) drop1 = Dropout(0.2)(pool1) # Bloque 2 conv2 = Conv2D( 64, (3, 3), activation='relu', padding='same')(drop1) conv2 = Conv2D( 64, (3, 3), activation='relu', padding='same')(conv2) pool2 = MaxPooling2D((2, 2), strides=2, padding='same')(conv2) drop2 = Dropout(0.2)(pool2) # Bloque 3 conv3 = Conv2D( 128, (3, 3), activation='relu', padding='same')(drop2) conv3 = Conv2D( 128, (3, 3), activation='relu', padding='same')(conv3) pool3 = MaxPooling2D( (2, 2), strides=(5, 2), padding='same')(conv3) drop3 = Dropout(0.2)(pool3) # Bloque 4 conv4 = Conv2D( 256, (3, 3), activation='relu', padding='same')(drop3) conv4 = Conv2D( 256, (3, 3), activation='relu', padding='same')(conv4) pool4 = MaxPooling2D( (2, 2), strides=(3, 2), padding='same')(conv4) drop4 = Dropout(0.2)(pool4) # Enlace o puente conv5 = Conv2D( 512, (3, 3), activation='relu', padding='same')(pool4) conv5 = Conv2D( 512, (3, 3), activation='relu', padding='same')(conv5) # Etapa de expansión # Bloque 5 exp1 = Conv2DTranspose( 256, (2, 2), strides=(3, 2), padding='same', activation='relu')(conv5) cont1 = concatenate([exp1, conv4]) conv6 = Conv2D( 256, (3, 3), activation='relu', padding='same')(cont1) conv6 = Conv2D( 256, (3, 3), activation='relu', padding='same')(conv6) # Bloque 6 exp2 = Conv2DTranspose( 128, (2, 2), strides=(5, 2), padding='same', activation='relu')(conv6) cont2 = concatenate([exp2, conv3]) conv7 = Conv2D( 128, (3, 3), activation='relu', padding='same')(cont2) conv7 = Conv2D( 128, (3, 3), activation='relu', padding='same')(conv7) # Bloque 7 exp3 = Conv2DTranspose( 64, (2, 2), strides=(2, 2), padding='same', activation='relu')(conv7) cont3 = concatenate([exp3, conv2]) conv8 = Conv2D( 64, (3, 3), activation='relu', padding='same')(cont3) conv8 = Conv2D( 64, (3, 3), activation='relu', padding='same')(conv8) # Bloque 8 exp4 = Conv2DTranspose( 32, (2, 2), strides=(2, 2), padding='same', activation='relu')(conv8) cont4 = concatenate([exp4, conv1]) conv9 = Conv2D( 32, (3, 3), activation='relu', padding='same')(cont4) conv9 = Conv2D( 64, (3, 3), activation='relu', padding='same')(conv9) # Etapa de organización. Practicamente no cambia y es obligatoria en casi # todas las redes FCN y por supuesto va siempre al final conv10 = Conv2D(1, (1, 1), activation='sigmoid')(conv9) # Juntamos el modelo. Le estamos diciendo desde donde inicia el modelo # y hasta donde va. model = Model(inputs=[entrada], outputs=[conv10]) # Compilamos el modelo model.compile( optimizer=Adam(learning_rate=1e-5), loss=self.dice_coef_loss, metrics=[self.dice_coef]) # model.compile(optimizer='adam', # loss='binary_crossentropy', # metrics=['accuracy']) return model
[docs] def dice_coef( self, y_true: np.ndarray, y_pred: np.ndarray) -> float: """ Cálculo del coeficiente Dice como métrica. Parameters ---------- y_true Etiquetas. y_pred Predicciones. Returns ------- float Coeficiente dice. """ # Metrica de evalaución 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))
# Función de costo
[docs] def dice_coef_loss( self, y_true: np.ndarray, y_pred: np.ndarray) -> float: """ Cálculo del coeficiente Dice como funcion de costo. Parameters ---------- y_true Etiquetas. y_pred Predicciones. Returns ------- float Coeficiente dice. """ return -self.dice_coef(y_true, y_pred)