Deep Learning Tutorial for Kaggle Ultrasound Nerve Segmentation competition, using Keras

Overview

Deep Learning Tutorial for Kaggle Ultrasound Nerve Segmentation competition, using Keras

This tutorial shows how to use Keras library to build deep neural network for ultrasound image nerve segmentation. More info on this Kaggle competition can be found on https://www.kaggle.com/c/ultrasound-nerve-segmentation.

This deep neural network achieves ~0.57 score on the leaderboard based on test images, and can be a good staring point for further, more serious approaches.

The architecture was inspired by U-Net: Convolutional Networks for Biomedical Image Segmentation.


Update 02.04.2017.

Changes:

  • using Keras 2
  • using TF backend instead of Theano
  • using scikit-image instead of cv2
  • added code for saving predicted images to disk
  • training data is now split into train/validation data (80%/20%)

Overview

Data

Provided data is processed by data.py script. This script just loads the images and saves them into NumPy binary format files .npy for faster loading later.

Pre-processing

The images are not pre-processed in any way, except resizing to 96 x 96. Since the images are pretty noisy, I expect that some thoughtful pre-processing could yield better performance of the model.

Output images (masks) are scaled to [0, 1] interval.

Model

The provided model is basically a convolutional auto-encoder, but with a twist - it has skip connections from encoder layers to decoder layers that are on the same "level". See picture below (note that image size and numbers of convolutional filters in this tutorial differs from the original U-Net architecture).

img/u-net-architecture.png

This deep neural network is implemented with Keras functional API, which makes it extremely easy to experiment with different interesting architectures.

Output from the network is a 96 x 96 which represents mask that should be learned. Sigmoid activation function makes sure that mask pixels are in [0, 1] range.

Training

The model is trained for 20 epochs, where each epoch took ~30 seconds on Titan X. Memory footprint of the model is ~800MB.

After 20 epochs, calculated Dice coefficient is ~0.68, which yielded ~0.57 score on leaderboard, so obviously this model overfits (cross-validation pull requests anyone? ;)).

Loss function for the training is basically just a negative of Dice coefficient (which is used as evaluation metric on the competition), and this is implemented as custom loss function using Keras backend - check dice_coef() and dice_coef_loss() functions in train.py for more detail. Also, for making the loss function smooth, a factor smooth = 1 factor is added.

The weights are updated by Adam optimizer, with a 1e-5 learning rate. During training, model's weights are saved in HDF5 format.


How to use

Dependencies

This tutorial depends on the following libraries:

  • scikit-image
  • Tensorflow
  • Keras >= 2.0

Also, this code should be compatible with Python versions 2.7-3.5.

Prepare the data

In order to extract raw images and save them to .npy files, you should first prepare its structure. Make sure that raw dir is located in the root of this project. Also, the tree of raw dir must be like:

-raw
 |
 ---- train
 |    |
 |    ---- 1_1.tif
 |    |
 |    ---- …
 |
 ---- test
      |
      ---- 1.tif
      |
      ---- …
  • Now run python data.py.

Running this script will create train and test images and save them to .npy files.

Define the model

  • Check out get_unet() in train.py to modify the model, optimizer and loss function.

Train the model and generate masks for test images

  • Run python train.py to train the model.

Check out train_predict() to modify the number of iterations (epochs), batch size, etc.

After this script finishes, in imgs_mask_test.npy masks for corresponding images in imgs_test.npy should be generated. I suggest you examine these masks for getting further insight of your model's performance.

Generate submission

  • Run python submission.py to generate the submission file submission.csv for the generated masks.

Check out function submission() and run_length_enc() (thanks woshialex) for details.

About Keras

Keras is a minimalist, highly modular neural networks library, written in Python and capable of running on top of either TensorFlow or Theano. It was developed with a focus on enabling fast experimentation. Being able to go from idea to result with the least possible delay is key to doing good research.

Use Keras if you need a deep learning library that:

allows for easy and fast prototyping (through total modularity, minimalism, and extensibility). supports both convolutional networks and recurrent networks, as well as combinations of the two. supports arbitrary connectivity schemes (including multi-input and multi-output training). runs seamlessly on CPU and GPU. Read the documentation Keras.io

Keras is compatible with: Python 2.7-3.5.

Comments
  • Converting

    Converting "imgs_mask_test.npy" into image format

    Hi Marko,

    First of all, thanks for sharing your code in this repository. It has been really useful for the project I am doing: segmentation of skin lesions.

    I have run all your code, and I already have the "imgs_mask_test.npy" file but I would like to convert this numpy array file into tiff/png/jpeg images. Do you have a code for doing that?

    Thanks in advance.

    opened by adriaromero 13
  • let u-net predict images having different size with training images

    let u-net predict images having different size with training images

    Hi Marko,

    I have limited number (around 500~700) images with large size (10241024). I constructed large amount of training set based on sampling from original images. The sampled size is 128128. I trained a model, and then tried to predict over the test images (1024*1024). Previously, I just make prediction over the sub-frame of the test images, and then stitch these predicted masked together.

    I heard that there is a way to let trained network can predict any size of images. The trick is replacing inputs = Input((1, img_rows, img_cols)) to inputs = Input((1, None, None)). I tried, but i have error messages as. Do you have any thoughts on this? Or is it possible to let U-net predict images having different size with trained images.

    Traceback (most recent call last):
      File "train-unet-v3b.py", line 113, in <module>
        train_and_predict()
      File "train-unet-v3b.py", line 96, in train_and_predict
        model = get_unet()
      File "train-unet-v3b.py", line 54, in get_unet
        up6 = merge([UpSampling2D(size=(2, 2))(conv5), conv4], mode='concat', concat_axis=1)
      File "/development/gtfw/lib/python3.4/site-packages/Keras-1.0.3-py3.4.egg/keras/engine/topology.py", line 485, in __call__
        self.add_inbound_node(inbound_layers, node_indices, tensor_indices)
      File "/development/gtfw/lib/python3.4/site-packages/Keras-1.0.3-py3.4.egg/keras/engine/topology.py", line 543, in add_inbound_node
        Node.create_node(self, inbound_layers, node_indices, tensor_indices)
      File "/development/gtfw/lib/python3.4/site-packages/Keras-1.0.3-py3.4.egg/keras/engine/topology.py", line 148, in create_node
        output_tensors = to_list(outbound_layer.call(input_tensors[0], mask=input_masks[0]))
      File "/development/gtfw/lib/python3.4/site-packages/Keras-1.0.3-py3.4.egg/keras/layers/convolutional.py", line 1043, in call
        self.dim_ordering)
      File "/development/gtfw/lib/python3.4/site-packages/Keras-1.0.3-py3.4.egg/keras/backend/tensorflow_backend.py", line 508, in resize_images
        X.set_shape((None, None, original_shape[2] * height_factor, original_shape[3] * width_factor))
    TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'
    
    
    opened by wenouyang 7
  • UpSampling

    UpSampling

    Hi,

    I think in the paper, we are required to performed a "learned upsampling" or a "convolution transpose".

    However, the implementation here uses UpSampling2D. https://github.com/jocicmarko/ultrasound-nerve-segmentation/blob/master/train.py#L51

    Any comments on this?

    Rahul.V.

    opened by gravity1989 6
  • Dice over all samples

    Dice over all samples

    I am new in Keras. I am trying to use your code in brain tumor segmentation but I confused about the dice metric. I don't know actually this code measures the dice for each image and then measures the mean value over all samples or it just measures the dice over all sample once. What I mean, consider that I have an input like (3000,218,218) includes 3000 samples. is it calculate the dice for each 218*218 image and then measure the mean over all 3000 samples or it convert this huge matrix to a vector and the measure the dice for all samples once. Thanks

    opened by ghost 5
  • how to increase the contrast of the predicted masks -nothing is visible  in masks

    how to increase the contrast of the predicted masks -nothing is visible in masks

    hi i tried your code , everything goes well but the predicted masks generated are of low contrast.how to increase the contrast so that i can see the clear prediction here is the sample prediction 2_pred

    opened by rddvsr 5
  • Exception concat mode

    Exception concat mode

    Hi Marko, I'am trying to use your code. My images are .png files. data.py runs without exceptions. but train.py fails in that line 51 up6 = merge([UpSampling2D(size=(2, 2))(conv5), conv4], mode='concat', concat_axis=1) with that exception message: Exception: "concat" mode can only merge layers with matching output shapes except for the concat axis. Layer shapes: [(None, 512, 42, 78), (None, 256, 43, 79)] I know the shapes doesn't match, but why? during competion your code runs well with original ultrasound images(.tiff). Could you help me please to customize your code that i can train your model on my own images?

    opened by AlexunderMicrocontrol 5
  • Question about Dice function

    Question about Dice function

    Your code works very well, and I have been using and also modified for many projects. However i just realized today that Dice and IOU are both non-differentiable function. Then my question is, why it works in your code? Thanks!

    opened by qinxi117 4
  • Help me solve this error

    Help me solve this error

    Exception Traceback (most recent call last) in () ----> 1 up6 = merge([UpSampling2D(size=(2, 2, 2), dim_ordering='default')(conv5), conv4], mode='concat', concat_axis=1)

    /usr/local/lib/python2.7/dist-packages/keras/engine/topology.pyc in merge(inputs, mode, concat_axis, dot_axes, output_shape, output_mask, name) 1526 node_indices=node_indices, 1527 tensor_indices=tensor_indices, -> 1528 name=name) 1529 return merge_layer.inbound_nodes[0].output_tensors[0] 1530 else:

    /usr/local/lib/python2.7/dist-packages/keras/engine/topology.pyc in init(self, layers, mode, concat_axis, dot_axes, output_shape, output_mask, node_indices, tensor_indices, name) 1184 self._arguments_validation(layers, mode, 1185 concat_axis, dot_axes, -> 1186 node_indices, tensor_indices) 1187 self.built = True 1188 self.add_inbound_node(layers, node_indices, tensor_indices)

    /usr/local/lib/python2.7/dist-packages/keras/engine/topology.pyc in _arguments_validation(self, layers, mode, concat_axis, dot_axes, node_indices, tensor_indices) 1251 raise Exception('"concat" mode can only merge layers with matching ' + 1252 'output shapes except for the concat axis. ' + -> 1253 'Layer shapes: %s' % (input_shapes)) 1254 1255 def call(self, inputs, mask=None):

    Exception: "concat" mode can only merge layers with matching output shapes except for the concat axis. Layer shapes: [(None, 0, 8, 512), (None, 0, 8, 256)]

    opened by AlexandruHodorogea 4
  • Normalizing data and its affect on validation data

    Normalizing data and its affect on validation data

    Hi There, Thank you so much for sharing your code. I have a question regarding the normalization of data. You gather all of the training data into an array (imgs_train). Then calculate the mean and std, normalize whole of the imgs_train and feed it to the network. actually, this imgs_train is split into 2 parts: training and validation sets. I think when you wanna normalize your data, you shouldn't include validation data in it. You have to set the validation data apart, normalize the rest (let's call it subtraining = training - validation), then before feeding the network with the validation data, normalize it with mean and std of subtraining. It's not fair to validate the network progress over data which had already been affected by training--your validation data is biased and not fair.

    I'd like to know your opinion about this issue and thank you again for this valuable code.

    opened by SorourMo 3
  • y_true and y_pred

    y_true and y_pred

    y_true : 1d array-like, or label indicator array / sparse matrix Ground truth (correct) target values. y_pred : 1d array-like, or label indicator array / sparse matrix Estimated targets as returned by a classifier.

    what is y_true and y_pred in this code ? in this code , how is he reading y_true and y_pred . Where is he defining y_true, y_pred ? I dint find any.

    https://github.com/jocicmarko/ultrasound-nerve-segmentation/blob/master/train.py#L19

    I tried to print y_true and y_pred , but it says it is not defined. Can anyone say , where he is defining y_true and y_pred ? !!

    opened by pratikgorji 3
  • Dice Coefficient

    Dice Coefficient

    Hi there,

    Thanks for posting the code. I noticed in your calculation of the DICE coefficient, you smoothed the result by 1 i.e.

    def dice_coef(y_true, y_pred):
        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 dice_coef_loss(y_true, y_pred):
        return -dice_coef(y_true, y_pred)
    

    My understanding is that

    Sorensen's original formula =  2 * |X n Y| / (  |X| + |Y| )
    

    My questions: 1) why did you add the smoothing value? How does it help during training?

    2.) why did you take the negative of the coefficient in Line 19?

    Pardon my questions if the answer seems self-evident as I am not a user of Keras at all but it seems to me that you computed something different from the original dice coefficient. I might be wrong so I would appreciate your explanation. Thank you!

    opened by robotsorcerer 3
  • NameError: name 'dump' is not defined

    NameError: name 'dump' is not defined

    File "C:\Users\virkt\Anaconda3\envs\unet\lib\multiprocessing\reduction.py", line 249, in AbstractReducer dump = dump NameError: name 'dump' is not defined

    i m getting this error. plz help

    opened by manvirvirk 0
  • Dice loss implementation

    Dice loss implementation

    I wonder why in dice loss implementation union is just sum and not sum - intersection, i.e. in case of sum seems mask itersection area is calculated twice?

    https://github.com/jocicmarko/ultrasound-nerve-segmentation/blob/master/train.py#L27 https://github.com/keras-team/keras-contrib/blob/master/keras_contrib/losses/jaccard.py#L33

    opened by mrgloom 2
  • create_train_data()

    create_train_data()

    @jocicmarko and other guys, Can someone add comments in the create_train_data() function in data.py file? It's somewhat hard to get what going on in this function. After implementing this function I am getting an error of [Errno 2] No such file or directory: 'drive/Colab_Notebooks/Train/train/image/35_mask.tif' Using this file in google Colab I **

    am using different data which is generated by me with labels but didn't know how much to use in data.py file. I have an image and mask in a different folder and split them randomly into the train and test folder(named as an image for "images" and mask for "mask" in train and test both folder).

    ** Need help with this. Have mounted drive so no worries with that.

    opened by matsujju 0
  • wrong index?

    wrong index?

    https://github.com/jocicmarko/ultrasound-nerve-segmentation/blob/df9eb77f0ac3b84ae125b6b177ef2e4429818d66/submission.py#L43 Should it be imgs_test[i,:,:,0]?

    opened by zihaozhihao 1
Owner
Marko Jocić
ML Engineer @ Apple
Marko Jocić
My published benchmark for a Kaggle Simulations Competition

Lux AI Working Title Bot Please refer to the Kaggle notebook for the comment section. The comment section contains my explanation on my code structure

Tong Hui Kang 29 Aug 22, 2022
Data visualization app for H&M competition in kaggle

handm_data_visualize_app Data visualization app by streamlit for H&M competition in kaggle. competition page: https://www.kaggle.com/competitions/h-an

Kyohei Uto 12 Apr 30, 2022
This is the solution for 2nd rank in Kaggle competition: Feedback Prize - Evaluating Student Writing.

Feedback Prize - Evaluating Student Writing This is the solution for 2nd rank in Kaggle competition: Feedback Prize - Evaluating Student Writing. The

Udbhav Bamba 41 Dec 14, 2022
This repository is related to an Arabic tutorial, within the tutorial we discuss the common data structure and algorithms and their worst and best case for each, then implement the code using Python.

Data Structure and Algorithms with Python This repository is related to the Arabic tutorial here, within the tutorial we discuss the common data struc

Mohamed Ayman 33 Dec 2, 2022
Automatic detection and classification of Covid severity degree in LUS (lung ultrasound) scans

Final-Project Final project in the Technion, Biomedical faculty, by Mor Ventura, Dekel Brav & Omri Magen. Subproject 1: Automatic Detection of LUS Cha

Mor Ventura 1 Dec 18, 2021
Western-3DSlicer-Modules - Point-Set Registrations for Ultrasound Probe Calibrations

Point-Set Registrations for Ultrasound Probe Calibrations -Undergraduate Thesis-

Matteo Tanzi 0 May 4, 2022
SweiNet is an uncertainty-quantifying shear wave speed (SWS) estimator for ultrasound shear wave elasticity (SWE) imaging.

SweiNet SweiNet is an uncertainty-quantifying shear wave speed (SWS) estimator for ultrasound shear wave elasticity (SWE) imaging. SweiNet takes as in

Felix Jin 3 Mar 31, 2022
Keras udrl - Keras implementation of Upside Down Reinforcement Learning

keras_udrl Keras implementation of Upside Down Reinforcement Learning This is me

Eder Santana 7 Jan 24, 2022
Kaggle: Cell Instance Segmentation

Kaggle: Cell Instance Segmentation The goal of this challenge is to detect cells in microscope images. with simple view on how many cels have been ann

Jirka Borovec 9 Aug 12, 2022
This source code is implemented using keras library based on "Automatic ocular artifacts removal in EEG using deep learning"

CSP_Deep_EEG This source code is implemented using keras library based on "Automatic ocular artifacts removal in EEG using deep learning" {https://www

Seyed Mahdi Roostaiyan 2 Nov 8, 2022
This is an implementation of Googles Yogi-Optimizer in Keras (tf.keras)

Yogi-Optimizer_Keras This is an implementation of Googles Yogi-Optimizer in Keras (tf.keras) The NeurIPS-Paper can be found here: http://papers.nips.c

null 14 Sep 13, 2022
Example-custom-ml-block-keras - Custom Keras ML block example for Edge Impulse

Custom Keras ML block example for Edge Impulse This repository is an example on

Edge Impulse 8 Nov 2, 2022
Classification models 1D Zoo - Keras and TF.Keras

Classification models 1D Zoo - Keras and TF.Keras This repository contains 1D variants of popular CNN models for classification like ResNets, DenseNet

Roman Solovyev 12 Jan 6, 2023
Keras like implementation of Deep Learning architectures from scratch using numpy.

Mini-Keras Keras like implementation of Deep Learning architectures from scratch using numpy. How to contribute? The project contains implementations

MANU S PILLAI 5 Oct 10, 2021
Realtime Face Anti Spoofing with Face Detector based on Deep Learning using Tensorflow/Keras and OpenCV

Realtime Face Anti-Spoofing Detection ?? Realtime Face Anti Spoofing Detection with Face Detector to detect real and fake faces Please star this repo

Prem Kumar 86 Aug 3, 2022
Vision Deep-Learning using Tensorflow, Keras.

Welcome! I am a computer vision deep learning developer working in Korea. This is my blog, and you can see everything I've studied here. https://www.n

kimminjun 6 Dec 14, 2022
Tutorial on active learning with the Nvidia Transfer Learning Toolkit (TLT).

Active Learning with the Nvidia TLT Tutorial on active learning with the Nvidia Transfer Learning Toolkit (TLT). In this tutorial, we will show you ho

Lightly 25 Dec 3, 2022
Distributed Deep learning with Keras & Spark

Elephas: Distributed Deep Learning with Keras & Spark Elephas is an extension of Keras, which allows you to run distributed deep learning models at sc

Max Pumperla 1.6k Jan 5, 2023
QKeras: a quantization deep learning library for Tensorflow Keras

QKeras github.com/google/qkeras QKeras 0.8 highlights: Automatic quantization using QKeras; Stochastic behavior (including stochastic rouding) is disa

Google 437 Jan 3, 2023