Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/subpic/ku
Browse files Browse the repository at this point in the history
  • Loading branch information
subpic committed Mar 23, 2020
2 parents be090b7 + 990c24c commit ca6aee3
Show file tree
Hide file tree
Showing 2 changed files with 221 additions and 9 deletions.
127 changes: 127 additions & 0 deletions ensembles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import numpy as np, pandas as pd
import multiprocessing as mp
import os, scipy, h5py, time, sys
from munch import Munch
from sklearn.model_selection import train_test_split
from scipy import stats
from .model_helper import *
from .applications import *
from .tensor_ops import *
from .generic import *
from .image_utils import *
import matplotlib.pyplot as plt

from keras.layers import Input, Dropout
from keras.models import Model

from keras import backend as K

class Ensemble(object):
"""
Whatever
"""
def __init__(self, ids, get_helper, ensemble_size, num_epochs=50, verbose=True, statistic='var', splits = (.95,.05), mc_dropout=False):
"""
description tbd
"""
self.ids = ids
self.helper = get_helper()
self.ensemble_size = ensemble_size
self.num_epochs = num_epochs
self.verbose = verbose
self.statistic = statistic
self.splits = splits
self.mc_dropout = mc_dropout

if self.verbose:
print("Ensemble of size " + str(self.ensemble_size) + " initiated. Training for " + str(self.num_epochs) + " epochs scheduled.")

def train(self, lr=1e-4, valid_in_memory=False,
recompile=True, verbose=True):
"""
description tbd
"""
ids = self.ids
ids = ids[ids.set!='test']
for ens in range(self.ensemble_size):
helper = self.helper
helper.model_name.update(ens_n=ens)
helper.model_name.update(stat=self.statistic)
helper.model_name.update(splits=self.splits)

train_valid_gen = helper.make_generator(ids, batch_size=len(ids), shuffle=False)

X, y = train_valid_gen[0]
X, y = X[0],y[0]

itrain, ivalid = train_test_split(list(range(X.shape[0])),
train_size=self.splits[0], test_size=self.splits[1], random_state=42+ens)
X_train, y_train = X[itrain, ...], y[itrain]
X_valid, y_valid = X[ivalid, ...], y[ivalid]

helper.model_name.splits = self.splits

helper.train(lr=lr, epochs=self.num_epochs, recompile=recompile, verbose=verbose,
train_gen = (X_train, y_train),
valid_gen = (X_valid, y_valid))
helper.load_model()
helper.train(lr=lr*0.1, epochs=self.num_epochs, recompile=recompile, verbose=verbose,
train_gen = (X_train, y_train),
valid_gen = (X_valid, y_valid))

del helper
K.clear_session()


def predict(self, test_gen=None, splits=False, output='MOS', output_layer=None,
repeats=1, batch_size=None, remodel=True):
"""
description tbd
"""
predictions = []
for ens in range(self.ensemble_size):
mcrange = 1
if self.mc_dropout:
mcrange = 5
output='mos_v' + str(ens)
helper = self.helper
helper.model_name.update(ens_n = ens)
helper.model_name.update(stat = self.statistic)
if helper.load_model(verbose=1):
for mc in range(mcrange):
predictions.append(helper.predict(test_gen=test_gen, output_layer=output_layer,
repeats=repeats, batch_size=batch_size, remodel=remodel))

K.clear_session()

return np.array(predictions)

def evaluate_performance(self, test_gen=None, output='MOS', output_layer=None,
repeats=1, batch_size=None, remodel=True,
statistic='var'):
"""
description tbd
"""
predictions = self.predict(test_gen=test_gen, output=output, output_layer=output_layer, repeats=repeats,
batch_size=batch_size, remodel=remodel)
predictions = np.array(predictions)

if statistic=='var':
performance = np.var(np.array(predictions),axis=0)

if self.verbose:
plt.hist(performance, bins=25);

return performance

def update_splits(self, splits):
"""
description tbd
"""
self.splits = splits

def update_ids(self, ids):
"""
description tbd
"""
self.ids = ids
103 changes: 94 additions & 9 deletions image_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ def extract_random_patch(im, patch_size=(224, 224), border=(0, 0)):
Y0 = int(rand(1)*(Y_max-Y_min) + Y_min)
X0 = int(rand(1)*(X_max-X_min) + X_min)
patch = im[Y0:Y0+H_crop, X0:X0+W_crop, ]

return patch

def extract_patch(im, patch_size=(224, 224),
Expand Down Expand Up @@ -162,8 +163,82 @@ def extract_patch(im, patch_size=(224, 224),
min(max(int(Y0), 0), Y_max)

patch = im[Y0:Y0+H_crop, X0:X0+W_crop, ]

return patch

def cropout_random_patch(im, patch_size=(224, 224), border=(0, 0), fill_val=0):
"""
Cropout (replace) a random patch of size `patch_size` with `fill_val`,
with the center of the patch inside `border`
* im: np.ndarray of size H x W x C
* patch_size: 2-tuple of patch H x W
* border: 2-tuple of border H x W
* fill_val: value to fill into the cropout
:return: np.ndarray
"""
H, W, _ = im.shape
H_crop, W_crop = patch_size
H_crop = min(H, H_crop)
W_crop = min(W, W_crop)
Y_min, X_min = border
Y_max, X_max = (H - H_crop - Y_min, W - W_crop - X_min)
if Y_max < Y_min:
Y_min = old_div((H - H_crop), 2)
Y_max = Y_min
if X_max < X_min:
X_min = old_div((W - W_crop), 2)
X_max = X_min
Y0 = int(rand(1)*(Y_max-Y_min) + Y_min)
X0 = int(rand(1)*(X_max-X_min) + X_min)
im[Y0:Y0+H_crop, X0:X0+W_crop, ] = fill_val
return im

def cropout_patch(im, patch_size=(224, 224),
patch_position=(0.5, 0.5), fill_val=0):
"""
Cropout (replace) a patch of size `patch_size` with `fill_val`,
with its center at `patch_position` expressed as a ratio of the image's H and W
* im: np.ndarray of size H x W x C
* patch_size: 2-tuple of patch H x W
* patch_position: 2-tuple containing patch location
(0,0) = upper left corner, (1,1) = lower right corner
* fill_val: value to fill into the cropout
:return: np.ndarray
"""
Py, Px = patch_position
H, W, _ = im.shape
H_crop, W_crop = patch_size

H_crop, W_crop = min(H, H_crop), min(W, W_crop)
Y_max, X_max = (H - H_crop, W - W_crop)
Yc, Xc = H*Py, W*Px

X0, Y0 = Xc-old_div(W_crop,2), Yc-old_div(H_crop,2)
X0, Y0 = min(max(int(X0), 0), X_max),\
min(max(int(Y0), 0), Y_max)

im[Y0:Y0+H_crop, X0:X0+W_crop, ] = fill_val
return im

def imdistort_image(im, dist_fn, **params):
"""
Distort an image `im` by `dist_fn` with provided parameters.
Requires the imdistort_python package.
* im: np.ndarray of size H x W x C
* dist_fn: String name of the distortion function
:return: np.ndarray
"""
try:
from imdistort_python import distortions
im = getattr(distortions, dist_fn)(im, **params)
except ImportError:
print("Import Error: Couldn't load imdistort_python. Could not perform distortion.")

return im

def resize_image(x, size):
"""
Resize image using skimage.transform.resize even when range is outside [-1,1].
Expand Down Expand Up @@ -385,7 +460,7 @@ def rotate(self, angle, random=True):
mode='symmetric')
return self

def crop(self, crop_size, crop_pos=None, clip_rotation=False):
def crop(self, crop_size, crop_pos=None, clip_rotation=False, cropout=False):
"""
Crop a patch out of self.image. Relies on `extract_patch`.
Expand All @@ -402,9 +477,9 @@ def crop(self, crop_size, crop_pos=None, clip_rotation=False):
# if using a ratio crop, compute actual crop size
crop_size = [np.int32(c*dim) if 0 < c <= (1+1e-6) else c\
for c, dim in zip(crop_size, self.image.shape[:2])]

if self.verbose:
print('image_size:', self.image.shape, 'crop_size:', crop_size)
print('image_size:', self.image.shape, 'crop_size:', crop_size, 'cropping out:', cropout)

if crop_pos is None:
if crop_size != self.image.shape[:2]:
Expand All @@ -416,14 +491,24 @@ def crop(self, crop_size, crop_pos=None, clip_rotation=False):
border = (old_div((x[0]-y[0]),2), old_div((x[1]-y[1]),2))
else:
border = (0, 0)
self.image = extract_random_patch(self.image,
patch_size = crop_size,
border = border)
if cropout:
self.image = cropout_random_patch(self.image,
patch_size = crop_size,
border = border)
else:
self.image = extract_random_patch(self.image,
patch_size = crop_size,
border = border)
else:
if crop_size != self.image.shape[:2]:
self.image = extract_patch(self.image,
patch_size = crop_size,
patch_position = crop_pos)
if cropout:
self.image = cropout_patch(self.image,
patch_size = crop_size,
patch_position = crop_pos)
else:
self.image = extract_patch(self.image,
patch_size = crop_size,
patch_position = crop_pos)
return self

def fliplr(self, do=None):
Expand Down

0 comments on commit ca6aee3

Please sign in to comment.