====== Finding patterns of shallow organization ======
or
====== The application of a trained machine learning model by means of an example ======
This is a very specific analysis and probably need to be adapted vastly for other machine learning applications.
During an effort of the atmospheric department at MPI and LMD, patterns/forms of organization of shallow convection were labeled in 10.000 satellite images (https://arxiv.org/abs/1906.01906). These labels have been used to train a machine learning model to identify these patterns autonomously. In the following, the application of this trained model is shown.
===== Step-by-step =====
**1. Login to mistral **
ssh -L :localhost: user_name@mistral.dkrz.de
Choose a ''port'' for forwarding, like 8888 and use the same throughout this tutorial.
**2. Allocate GPU node **
see also [[https://www.dkrz.de/up/services/analysis/visualization/visualization-on-mistral]]
salloc -N 1 -n 6 --mem=128000 -p gpu -A -t10:00:00 -- /bin/bash -c 'ssh -L :localhost: -X $SLURM_JOB_NODELIST'
After the allocation of the GPU your prompt should indicate that you are now on an GPU node, like ''mg101''.
**3. Activate the appropriate conda environment **
source activate environment_with_keras_installed
**4. Open ''jupyter lab'' to interactively run the following commands on the GPU node. **
jupyter-lab --port= --no-browser
**5. Load the necessary packages **
%load_ext autoreload
%autoreload 2
%matplotlib inline
from pyclouds.imports import *
from pyclouds.helpers import *
from pyclouds.zooniverse import *
from pyclouds.plot import *
from PIL import Image
from tqdm import tqdm_notebook as tqdm
import pickle
from itertools import combinations
import imghdr
import keras_retinanet
import keras
from keras_retinanet import models
from keras_retinanet.utils.image import read_image_bgr, preprocess_image, resize_image
from keras_retinanet.utils.visualization import draw_box, draw_caption
from keras_retinanet.utils.colors import label_color
# import miscellaneous modules
import matplotlib.pyplot as plt
import cv2
import os
import numpy as np
import time
import pandas as pd
import glob
import tensorflow as tf
Most of these modules should be installed with
conda install --file requirements.txt
{{ :analysis:data:requirements.txt |}}
and the additional modules that we have written for this specific case you need to clone from [[https://github.com/raspstephan/sugar-flower-fish-or-gravel| github]] and install with:
python setup.py install
**6. Configure the paths to the input images, the output images and the trained model **
img_input_format = './InputImageFolder/*.png'
model_path = './exp5_resnet50_csv_20_inference.h5'
classification_file = 'Classifications.pkl'
You can download pretrained models at [[https://zenodo.org/record/2565146]] (currently deactivated due to our Kaggle competition).
def get_session():
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
return tf.Session(config=config)
# use this environment flag to change which GPU to use
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
# set the modified tf session as backend in keras
keras.backend.tensorflow_backend.set_session(get_session())
**7. Load the machine learning model**
If you download the model from [[https://zenodo.org/record/2565146]] you need to convert it to an inference model first with
keras_retinanet/bin/convert_model.py /path/to/training/model.h5 /path/to/save/inference/model.h5
The training model is in this case the one downloaded from the archive.
Please have a look at [[https://github.com/fizyr/keras-retinanet#converting-a-training-model-to-inference-model]] as well.
Otherwise, you can directly use
model = models.load_model(model_path, backbone_name='resnet50')
** 8. Load label to names mapping for visualization purposes**
labels_to_names = {i: l for i, l in enumerate(['Flower', 'Fish', 'Gravel', 'Sugar'])}
** 9. Load the file listing**
files = sorted(glob.glob(img_input_format))
** 10.Define main function**
that loads the image, applies the algorithm and returns for each identified cloud pattern a score together with the bounding box.
def get_retinanet_preds(model, fn, thresh=0.3, min_side=800, max_side=1050):
image = read_image_bgr(fn)
image = preprocess_image(image)
image, scale = resize_image(image, min_side, max_side)
boxes, scores, labels = [o[0] for o in model.predict_on_batch(np.expand_dims(image, axis=0))]
boxes /= scale
boxes = boxes[scores > thresh]
boxes = [xy2wh(*b) for b in boxes]
labels = labels[scores > thresh]
labels = [labels_to_names[i] for i in labels]
scores = scores[scores > thresh]
return np.array(boxes), labels, scores
**11. Create function for visualization purposes only**
def plot_img_from_fn_and_boxes(fn, boxes, labels, scores, figsize=(18, 15), show_labels=True):
fig, ax = plt.subplots(1, 1, figsize=figsize)
img = Image.open(fn)
ax.imshow(img)
ax.set_xticks([])
ax.set_yticks([])
for i in range(boxes.shape[0]):
rect = patches.Rectangle((boxes[i, 0], boxes[i, 1]), boxes[i, 2], boxes[i, 3],
facecolor='none',
edgecolor=np.array(l2c[labels[i]]) / 255, lw=2)
ax.add_patch(rect)
if show_labels:
s = labels[i] + ' - Retinanet - ' + str(scores[i])[:4]
txt = ax.text(boxes[i, 0], boxes[i, 1], s, color='white', fontsize=15, va='top')
txt.set_path_effects([PathEffects.withStroke(linewidth=5, foreground='k')])
return fig
def plot_retinanet(model, fn, thresh=0.5):
boxes, labels, scores = get_retinanet_preds(model, fn, thresh)
fig=plot_img_from_fn_and_boxes(fn, boxes, labels, scores)
return fig
**12. Apply algorithm on your first image**
fig=plot_retinanet(model, files[0], 0.4)
The result hopefully looks similar to:
{{observations:cloudpatternclassificationexample.png?600|}}
This is of course only one image and can easily be applied to further images
result_dict ={}
c = 0
for file in tqdm(files[:]):
boxes, labels, score = get_retinanet_preds(model, file, thresh=0.4)
for b,box in enumerate(boxes):
x,y,w,h = box
result_dict[c] = {'labels':labels[b], 'x':x, 'y':y, 'w':w, 'h':h,
'score':score[b],'file':file}
c+=1
df=pd.DataFrame.from_dict(result_dict,orient='index')
df.to_pickle(classification_file)