├── .gitignore ├── README.md └── classifier.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pollenating_insects_ramp 2 | Participation to RAMP 05 - Pollenating insects 3 | -------------------------------------------------------------------------------- /classifier.py: -------------------------------------------------------------------------------- 1 | import os 2 | os.environ["THEANO_FLAGS"] = "device=gpu" 3 | from sklearn.base import BaseEstimator 4 | import os 5 | from lasagne import layers, nonlinearities, updates, init, objectives 6 | from lasagne.updates import nesterov_momentum, rmsprop, adagrad 7 | from nolearn.lasagne import NeuralNet, BatchIterator 8 | from nolearn.lasagne.handlers import EarlyStopping 9 | import numpy as np 10 | from caffezoo.googlenet import GoogleNet 11 | from itertools import repeat 12 | from sklearn.pipeline import make_pipeline 13 | 14 | def makeGaussian(size, fwhm = 3, center=None): 15 | """ Make a square gaussian kernel. 16 | 17 | size is the length of a side of the square 18 | fwhm is full-width-half-maximum, which 19 | can be thought of as an effective radius. 20 | """ 21 | 22 | x = np.arange(0, size, 1, float) 23 | y = x[:,np.newaxis] 24 | 25 | if center is None: 26 | x0 = y0 = size // 2 27 | else: 28 | x0 = center[0] 29 | y0 = center[1] 30 | 31 | return np.exp(-4*np.log(2) * ((x-x0)**2 + (y-y0)**2) / fwhm**2).astype(np.float32) 32 | 33 | def apply_filter(x, filt): 34 | return np.array([ ex * filt for ex in x]) 35 | 36 | def sample_from_rotation_x(x): 37 | x_extends = [] 38 | for i in range(x.shape[0]): 39 | x_extends.extend([ 40 | np.array([x[i,:,:,0], x[i,:,:,1], x[i,:,:,2]]), 41 | np.array([np.rot90(x[i,:,:,0]),np.rot90(x[i,:,:,1]), np.rot90(x[i,:,:,2])]), 42 | np.array([np.rot90(x[i,:,:,0],2),np.rot90(x[i,:,:,1],2), np.rot90(x[i,:,:,2],2)]), 43 | np.array([np.rot90(x[i,:,:,0],3),np.rot90(x[i,:,:,1],3), np.rot90(x[i,:,:,2],3)]) 44 | ]) 45 | x_extends = np.array(x_extends) #.transpose((0, 2, 3, 1)) 46 | return x_extends 47 | 48 | def sample_from_rotation_y(y): 49 | y_extends = [] 50 | for i in y: 51 | y_extends.extend( repeat( i ,4) ) 52 | return np.array(y_extends) 53 | 54 | class FlipBatchIterator(BatchIterator): 55 | def transform(self, Xb, yb): 56 | Xb, yb = super(FlipBatchIterator, self).transform(Xb, yb) 57 | # Flip half of the images in this batch at random: 58 | bs = Xb.shape[0] 59 | indices = np.random.choice(bs, bs / 4, replace=False) 60 | Xb[indices] = Xb[indices, :, ::-1] 61 | 62 | # Drop randomly half of the features in each batch: 63 | bf = Xb.shape[2] 64 | indices_features = np.random.choice(bf, bf / 2, replace=False) 65 | Xb = Xb.transpose((2, 0, 1, 3)) 66 | Xb[indices_features] = Xb[indices_features] 67 | Xb = Xb.transpose((1, 2, 0, 3)) 68 | return Xb, yb 69 | 70 | def build_model(crop_value): 71 | L=[ 72 | (layers.InputLayer, {'shape':(None, 3, 64-2*crop_value, 64-2*crop_value)}), 73 | (layers.Conv2DLayer, {'num_filters':64, 'filter_size':(3,3), 'pad':0}), 74 | (layers.MaxPool2DLayer, {'pool_size': (2, 2)}), 75 | (layers.Conv2DLayer, {'num_filters':128, 'filter_size':(2,2), 'pad':0}), 76 | (layers.MaxPool2DLayer, {'pool_size': (2, 2)}), 77 | (layers.Conv2DLayer, {'num_filters':128, 'filter_size':(2,2), 'pad':0}), 78 | (layers.MaxPool2DLayer, {'pool_size': (4, 4)}), 79 | (layers.DenseLayer, {'num_units': 512, 'nonlinearity':nonlinearities.leaky_rectify, 'W': init.GlorotUniform(gain='relu')}), 80 | (layers.DropoutLayer, {'p':0.5}), 81 | (layers.DenseLayer, {'num_units': 512, 'nonlinearity':nonlinearities.leaky_rectify, 'W': init.GlorotUniform(gain='relu')}), 82 | (layers.DenseLayer, {'num_units': 18, 'nonlinearity':nonlinearities.softmax}), 83 | ] 84 | 85 | net = NeuralNet( 86 | layers=L, 87 | update=adagrad, 88 | update_learning_rate=0.01, 89 | use_label_encoder=True, 90 | verbose=1, 91 | max_epochs=100, 92 | batch_iterator_train=FlipBatchIterator(batch_size=128), 93 | on_epoch_finished=[EarlyStopping(patience=50, criterion='valid_loss')] 94 | ) 95 | return net 96 | 97 | class Classifier(BaseEstimator): 98 | 99 | def __init__(self): 100 | self.crop_value = 0 101 | self.gaussianFilter = np.tile(makeGaussian(64-2*self.crop_value, 64-2*self.crop_value-10), (3,1,1)).transpose(1,2,0) 102 | self.net = build_model(self.crop_value) 103 | 104 | def data_augmentation(self, X, y): 105 | X = sample_from_rotation_x(X) 106 | y = sample_from_rotation_y(y) 107 | return X, y 108 | 109 | def preprocess(self, X, transpose=True): 110 | X = (X / 255.) 111 | #X = X[:, self.crop_value:64-self.crop_value, self.crop_value:64-self.crop_value, :] 112 | X = apply_filter(X, self.gaussianFilter) 113 | X = X.astype(np.float32) 114 | if transpose: 115 | X = X.transpose((0, 3, 1, 2)) 116 | return X 117 | 118 | def preprocess_y(self, y): 119 | return y.astype(np.int32) 120 | 121 | def fit(self, X, y): 122 | X, y = self.preprocess(X, False), self.preprocess_y(y) 123 | X, y = self.data_augmentation(X, y) 124 | self.net.fit(X, y) 125 | return self 126 | 127 | def predict(self, X): 128 | X = self.preprocess(X) 129 | return self.net.predict(X) 130 | 131 | def predict_proba(self, X): 132 | X = self.preprocess(X) 133 | return self.net.predict_proba(X) 134 | 135 | 136 | --------------------------------------------------------------------------------