├── .gitignore ├── README.md ├── tensorflow └── layer_rotation_control.py └── keras ├── layer_rotation_monitoring.py ├── layer_rotation_control.py └── Example.ipynb /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints/ 2 | *.h5 3 | *.npy 4 | *.pyc 5 | *.spydata 6 | *.p 7 | nohup.out 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Layer-rotation-tools 2 | Implementation of tools to control and monitor layer rotation in different DL libraries (cfr. [this paper](https://arxiv.org/abs/1806.01603v2)) 3 | 4 | # Request for contribution 5 | Code for tensorflow and pytorch is needed. Any help will be much appreciated! 6 | -------------------------------------------------------------------------------- /tensorflow/layer_rotation_control.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 3 | ''' 4 | import tensorflow as tf 5 | 6 | def layca(p, step, lr): 7 | ''' 8 | Core operations of layca. 9 | Takes the current parameters and the step computed by an optimizer, and 10 | - projects and normalizes the step such that the rotation operated on the layer's weights is controlled 11 | - after the step has been taken, recovers initial norms of the parameters 12 | 13 | !!! 14 | only kernels are optimized. Biases and batchnorm pararmeters are left unchanged. This did not affect performance in our experiments. 15 | One can decide to train them anyway (without layca operations) by changing last line to: 16 | return p - lr * step 17 | !!! 18 | ''' 19 | if 'kernel' in p.name: # only kernels are optimized when using Layca (and not biases and batchnorm parameters) 20 | # projecting step on tangent space of sphere -> orthogonal to the parameters p 21 | initial_norm = tf.norm(p) 22 | step = step - ( tf.reduce_sum(step * p, axis=None, keepdims=False) )* p / initial_norm**2 23 | 24 | # normalizing step size (with special attention to numerical problems) 25 | step = tf.cond(tf.norm(step)<= 1e-7, lambda: tf.zeros_like(step), lambda: step/ (tf.norm(step)) * initial_norm) 26 | 27 | # applying step 28 | new_p = p - lr * step 29 | 30 | # recovering norm of the parameter from before the update 31 | new_p = new_p / tf.norm(new_p) * initial_norm 32 | return new_p 33 | else: 34 | return p # - lr * step # uncomment to train biases and batchnorm parameters (without layca) 35 | 36 | -------------------------------------------------------------------------------- /keras/layer_rotation_monitoring.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Methods for recording and plotting layer rotation curves 3 | ''' 4 | 5 | import numpy as np 6 | from scipy.spatial.distance import cosine 7 | 8 | import matplotlib 9 | import matplotlib.pyplot as plt 10 | 11 | from keras.callbacks import Callback 12 | import keras.backend as K 13 | from keras.losses import categorical_crossentropy 14 | 15 | def get_kernel_layer_names(model): 16 | ''' 17 | collects name of all layers of a model that contain a kernel in topological order (input layers first). 18 | ''' 19 | layer_names = [] 20 | for l in model.layers: 21 | if len(l.weights) >0: 22 | if 'kernel' in l.weights[0].name: 23 | layer_names.append(l.name) 24 | return layer_names 25 | 26 | def plot_layer_rotation_curves(distances, ax = None): 27 | ''' 28 | utility to plot the layer-wise cosine distances between current parameters and initial parameters, 29 | as measured over training (i.e. layer rotation curves). 30 | deviations is a list of lists with epoch index in first axis, layer index in second axis, 31 | containing the cosine distances for each layer as recorded over training 32 | ''' 33 | distances = np.array(distances) 34 | 35 | # get one color per layer 36 | cm = plt.get_cmap('viridis') 37 | cm_inputs = np.linspace(0,1,distances.shape[1]) 38 | 39 | if not ax: 40 | ax = plt.subplot(1,1,1) 41 | for i in range(distances.shape[-1]): 42 | layer = i 43 | ax.plot(np.arange(distances.shape[0]+1), [0]+list(distances[:,layer]), label = str(layer), color = cm(cm_inputs[i])) 44 | 45 | ax.set_ylim([0,1.]) 46 | ax.set_xlim([0,distances.shape[0]]) 47 | 48 | ax.set_xlabel('Epoch') 49 | ax.set_ylabel('Cosine distance') 50 | 51 | def compute_layer_rotation(current_model, initial_w): 52 | ''' 53 | for each layer, computes cosine distance between current weights and initial weights 54 | initial_w is a list of tuples containing layer name and corresponding initial numpy weights 55 | ''' 56 | s = [] 57 | for l_name, w in initial_w: 58 | s.append(cosine( current_model.get_layer(l_name).get_weights()[0].flatten(), w.flatten())) 59 | return s 60 | 61 | class LayerRotationCurves(Callback): 62 | ''' 63 | Computes and saves layer rotation curves during training 64 | ''' 65 | def __init__(self, batch_frequency=np.inf): 66 | ''' 67 | batch_frequency is the frequency at which the cosine distances are computed (minimum once per epoch) 68 | ''' 69 | super().__init__() 70 | self.batch_frequency = batch_frequency 71 | 72 | self.memory = [] 73 | 74 | def set_model(self,model): 75 | super().set_model(model) 76 | layer_names = get_kernel_layer_names(model) 77 | 78 | # initial_w is a list of tuples containing layer name and corresponding initial numpy weights 79 | self.initial_w = list(zip(layer_names,[model.get_layer(l).get_weights()[0] for l in layer_names])) 80 | 81 | def on_batch_end(self, batch, logs=None): 82 | if batch % self.batch_frequency == 0: #batch 0 is accepted, batch resets at 0 at every epoch 83 | 84 | dist = compute_layer_rotation(self.model, self.initial_w) 85 | 86 | self.memory.append(dist) 87 | 88 | def plot(self,ax = None): 89 | plot_layer_rotation_curves(self.memory,ax) -------------------------------------------------------------------------------- /keras/layer_rotation_control.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Code for applying Layca on SGD, Adam, RMSprop and Adagrad. 3 | Source: code is based on keras' implementation of the original optimization methods. 4 | ''' 5 | 6 | from keras.optimizers import Optimizer 7 | import keras.backend as K 8 | from keras.legacy import interfaces 9 | 10 | import numpy as np 11 | 12 | def norm(w): 13 | ''' 14 | computes frobenius norm of a tensor w 15 | ''' 16 | return K.sqrt(K.sum(w*w)) 17 | 18 | def layca(p, step, lr): 19 | ''' 20 | Core operations of layca. 21 | Takes the current parameters and the step computed by an optimizer, and 22 | - projects and normalizes the step such that the rotation operated on the layer's weights is controlled 23 | - after the step has been taken, recovers initial norms of the parameters 24 | 25 | !!! 26 | only kernels are optimized. Biases and batchnorm pararmeters are left unchanged. This did not affect performance in our experiments. 27 | One can decide to train them anyway (without layca operations) by changing last line to: 28 | return p - lr * step 29 | !!! 30 | ''' 31 | if 'kernel' in p.name: # only kernels are optimized when using Layca (and not biases and batchnorm parameters) 32 | # projecting step on tangent space of sphere -> orthogonal to the parameters p 33 | initial_norm = norm(p) 34 | step = step - (K.sum(step * p))* p / initial_norm**2 35 | 36 | # normalizing step size (with special attention to numerical problems) 37 | step = K.switch(norm(step)<= K.epsilon(), lambda: K.zeros_like(step), lambda: step/ (norm(step)) * initial_norm) 38 | 39 | # applying step 40 | new_p = p - lr * step 41 | 42 | # recovering norm of the parameter from before the update 43 | new_p = new_p / norm(new_p) * initial_norm 44 | return new_p 45 | else: 46 | return p # - lr * step # uncomment to train biases and batchnorm parameters (without layca) 47 | 48 | class SGD(Optimizer): 49 | """Stochastic gradient descent optimizer. 50 | Includes support for momentum, 51 | learning rate decay, and Nesterov momentum. 52 | # Arguments 53 | lr: float >= 0. Learning rate. 54 | momentum: float >= 0. Parameter that accelerates SGD 55 | in the relevant direction and dampens oscillations. 56 | decay: float >= 0. Learning rate decay over each update. 57 | nesterov: boolean. Whether to apply Nesterov momentum. 58 | layca: boolean, wether to apply layca or not 59 | """ 60 | 61 | def __init__(self, lr=0.01, momentum=0., decay=0., 62 | nesterov=False, layca = False,**kwargs): 63 | super().__init__(**kwargs) 64 | with K.name_scope(self.__class__.__name__): 65 | self.iterations = K.variable(0, dtype='int64', name='iterations') 66 | self.lr = K.variable(lr, name='lr') 67 | self.momentum = K.variable(momentum, name='momentum') 68 | self.decay = K.variable(decay, name='decay') 69 | self.initial_decay = decay 70 | self.nesterov = nesterov 71 | 72 | self.layca = layca 73 | 74 | @interfaces.legacy_get_updates_support 75 | def get_updates(self, loss, params): 76 | grads = self.get_gradients(loss, params) 77 | self.updates = [K.update_add(self.iterations, 1)] 78 | 79 | lr = self.lr 80 | if self.initial_decay > 0: 81 | lr *= (1. / (1. + self.decay * K.cast(self.iterations, 82 | K.dtype(self.decay)))) 83 | # momentum 84 | shapes = [K.int_shape(p) for p in params] 85 | moments = [K.zeros(shape) for shape in shapes] 86 | self.weights = [self.iterations] + moments 87 | for p, g, m in zip(params, grads, moments): 88 | v = self.momentum * m - lr * g # velocity 89 | self.updates.append(K.update(m, v)) 90 | 91 | if self.nesterov: 92 | step = self.momentum * v - lr * g 93 | else: 94 | step = v 95 | 96 | if self.layca: 97 | new_p = layca(p, -step, lr) 98 | else: 99 | new_p = p + step 100 | 101 | # Apply constraints. 102 | if getattr(p, 'constraint', None) is not None: 103 | new_p = p.constraint(new_p) 104 | 105 | self.updates.append(K.update(p, new_p)) 106 | return self.updates 107 | 108 | def get_config(self): 109 | config = {'lr': float(K.get_value(self.lr)), 110 | 'momentum': float(K.get_value(self.momentum)), 111 | 'decay': float(K.get_value(self.decay)), 112 | 'nesterov': self.nesterov, 113 | 'layca':self.layca} 114 | base_config = super().get_config() 115 | return dict(list(base_config.items()) + list(config.items())) 116 | 117 | class RMSprop(Optimizer): 118 | """RMSProp optimizer. 119 | It is recommended to leave the parameters of this optimizer 120 | at their default values 121 | (except the learning rate, which can be freely tuned). 122 | This optimizer is usually a good choice for recurrent 123 | neural networks. 124 | # Arguments 125 | lr: float >= 0. Learning rate. 126 | rho: float >= 0. 127 | epsilon: float >= 0. Fuzz factor. If `None`, defaults to `K.epsilon()`. 128 | decay: float >= 0. Learning rate decay over each update. 129 | layca: boolean, wether to apply layca or not 130 | # References 131 | - [rmsprop: Divide the gradient by a running average of its recent magnitude](http://www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf) 132 | """ 133 | 134 | def __init__(self, lr=0.001, rho=0.9, epsilon=None, decay=0., layca = False, 135 | **kwargs): 136 | super(RMSprop, self).__init__(**kwargs) 137 | with K.name_scope(self.__class__.__name__): 138 | self.lr = K.variable(lr, name='lr') 139 | self.rho = K.variable(rho, name='rho') 140 | self.decay = K.variable(decay, name='decay') 141 | self.iterations = K.variable(0, dtype='int64', name='iterations') 142 | if epsilon is None: 143 | epsilon = K.epsilon() 144 | self.epsilon = epsilon 145 | self.initial_decay = decay 146 | 147 | self.layca = layca 148 | 149 | @interfaces.legacy_get_updates_support 150 | def get_updates(self, loss, params): 151 | grads = self.get_gradients(loss, params) 152 | accumulators = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params] 153 | self.weights = accumulators 154 | self.updates = [K.update_add(self.iterations, 1)] 155 | 156 | lr = self.lr 157 | if self.initial_decay > 0: 158 | lr *= (1. / (1. + self.decay * K.cast(self.iterations, 159 | K.dtype(self.decay)))) 160 | 161 | for p, g, a in zip(params, grads, accumulators): 162 | # update accumulator 163 | new_a = self.rho * a + (1. - self.rho) * K.square(g) 164 | self.updates.append(K.update(a, new_a)) 165 | #new_p = p - lr * g / (K.sqrt(new_a) + self.epsilon) 166 | step = lr * g / (K.sqrt(new_a) + self.epsilon) 167 | 168 | if self.layca: 169 | new_p = layca(p, step, lr) 170 | else: 171 | new_p = p - step 172 | 173 | # Apply constraints. 174 | if getattr(p, 'constraint', None) is not None: 175 | new_p = p.constraint(new_p) 176 | 177 | self.updates.append(K.update(p, new_p)) 178 | return self.updates 179 | 180 | def get_config(self): 181 | config = {'lr': float(K.get_value(self.lr)), 182 | 'rho': float(K.get_value(self.rho)), 183 | 'decay': float(K.get_value(self.decay)), 184 | 'epsilon': self.epsilon, 185 | 'layca':self.layca} 186 | base_config = super(RMSprop, self).get_config() 187 | return dict(list(base_config.items()) + list(config.items())) 188 | 189 | class Adam(Optimizer): 190 | """Adam optimizer. 191 | Default parameters follow those provided in the original paper. 192 | # Arguments 193 | lr: float >= 0. Learning rate. 194 | beta_1: float, 0 < beta < 1. Generally close to 1. 195 | beta_2: float, 0 < beta < 1. Generally close to 1. 196 | epsilon: float >= 0. Fuzz factor. If `None`, defaults to `K.epsilon()`. 197 | decay: float >= 0. Learning rate decay over each update. 198 | layca: boolean, wether to apply layca or not 199 | amsgrad: boolean. Whether to apply the AMSGrad variant of this 200 | algorithm from the paper "On the Convergence of Adam and 201 | Beyond". 202 | # References 203 | - [Adam - A Method for Stochastic Optimization](http://arxiv.org/abs/1412.6980v8) 204 | - [On the Convergence of Adam and Beyond](https://openreview.net/forum?id=ryQu7f-RZ) 205 | """ 206 | 207 | def __init__(self, lr=0.001, beta_1=0.9, beta_2=0.999, layca = False, 208 | epsilon=None, decay=0., amsgrad=False, **kwargs): 209 | super(Adam, self).__init__(**kwargs) 210 | with K.name_scope(self.__class__.__name__): 211 | self.iterations = K.variable(0, dtype='int64', name='iterations') 212 | self.lr = K.variable(lr, name='lr') 213 | self.beta_1 = K.variable(beta_1, name='beta_1') 214 | self.beta_2 = K.variable(beta_2, name='beta_2') 215 | self.decay = K.variable(decay, name='decay') 216 | if epsilon is None: 217 | epsilon = K.epsilon() 218 | self.epsilon = epsilon 219 | self.initial_decay = decay 220 | self.amsgrad = amsgrad 221 | 222 | self.layca = layca 223 | 224 | @interfaces.legacy_get_updates_support 225 | def get_updates(self, loss, params): 226 | grads = self.get_gradients(loss, params) 227 | self.updates = [K.update_add(self.iterations, 1)] 228 | 229 | lr = self.lr 230 | if self.initial_decay > 0: 231 | lr *= (1. / (1. + self.decay * K.cast(self.iterations, 232 | K.dtype(self.decay)))) 233 | 234 | t = K.cast(self.iterations, K.floatx()) + 1 235 | lr_t = lr * (K.sqrt(1. - K.pow(self.beta_2, t)) / 236 | (1. - K.pow(self.beta_1, t))) 237 | 238 | ms = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params] 239 | vs = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params] 240 | if self.amsgrad: 241 | vhats = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params] 242 | else: 243 | vhats = [K.zeros((1,)) for _ in params] 244 | self.weights = [self.iterations] + ms + vs + vhats 245 | 246 | for p, g, m, v, vhat in zip(params, grads, ms, vs, vhats): 247 | m_t = (self.beta_1 * m) + (1. - self.beta_1) * g 248 | v_t = (self.beta_2 * v) + (1. - self.beta_2) * K.square(g) 249 | if self.amsgrad: 250 | vhat_t = K.maximum(vhat, v_t) 251 | step = lr_t * m_t / (K.sqrt(vhat_t) + self.epsilon) 252 | self.updates.append(K.update(vhat, vhat_t)) 253 | else: 254 | step = lr_t * m_t / (K.sqrt(v_t) + self.epsilon) 255 | 256 | self.updates.append(K.update(m, m_t)) 257 | self.updates.append(K.update(v, v_t)) 258 | 259 | if self.layca: 260 | new_p = layca(p, step, lr) 261 | else: 262 | new_p = p - step 263 | 264 | # Apply constraints. 265 | if getattr(p, 'constraint', None) is not None: 266 | new_p = p.constraint(new_p) 267 | 268 | self.updates.append(K.update(p, new_p)) 269 | return self.updates 270 | 271 | def get_config(self): 272 | config = {'lr': float(K.get_value(self.lr)), 273 | 'beta_1': float(K.get_value(self.beta_1)), 274 | 'beta_2': float(K.get_value(self.beta_2)), 275 | 'decay': float(K.get_value(self.decay)), 276 | 'epsilon': self.epsilon, 277 | 'amsgrad': self.amsgrad, 278 | 'layca':self.layca} 279 | base_config = super(Adam, self).get_config() 280 | return dict(list(base_config.items()) + list(config.items())) 281 | 282 | class Adagrad(Optimizer): 283 | """Adagrad optimizer. 284 | It is recommended to leave the parameters of this optimizer 285 | at their default values. 286 | # Arguments 287 | lr: float >= 0. Learning rate. 288 | epsilon: float >= 0. If `None`, defaults to `K.epsilon()`. 289 | decay: float >= 0. Learning rate decay over each update. 290 | layca: boolean, wether to apply layca or not 291 | # References 292 | - [Adaptive Subgradient Methods for Online Learning and Stochastic Optimization](http://www.jmlr.org/papers/volume12/duchi11a/duchi11a.pdf) 293 | """ 294 | 295 | def __init__(self, lr=0.01, epsilon=None, decay=0., layca = False,**kwargs): 296 | super(Adagrad, self).__init__(**kwargs) 297 | with K.name_scope(self.__class__.__name__): 298 | self.lr = K.variable(lr, name='lr') 299 | self.decay = K.variable(decay, name='decay') 300 | self.iterations = K.variable(0, dtype='int64', name='iterations') 301 | if epsilon is None: 302 | epsilon = K.epsilon() 303 | self.epsilon = epsilon 304 | self.initial_decay = decay 305 | 306 | self.layca = layca 307 | 308 | @interfaces.legacy_get_updates_support 309 | def get_updates(self, loss, params): 310 | 311 | grads = self.get_gradients(loss, params) 312 | shapes = [K.int_shape(p) for p in params] 313 | accumulators = [K.zeros(shape) for shape in shapes] 314 | self.weights = accumulators 315 | self.updates = [K.update_add(self.iterations, 1)] 316 | 317 | lr = self.lr 318 | if self.initial_decay > 0: 319 | lr *= (1. / (1. + self.decay * K.cast(self.iterations, 320 | K.dtype(self.decay)))) 321 | 322 | for p, g, a in zip(params, grads, accumulators): 323 | new_a = a + K.square(g) # update accumulator 324 | self.updates.append(K.update(a, new_a)) 325 | step = lr * g / (K.sqrt(new_a) + self.epsilon) 326 | 327 | if self.layca: 328 | new_p = layca(p, step, lr) 329 | else: 330 | new_p = p - step 331 | 332 | # Apply constraints. 333 | if getattr(p, 'constraint', None) is not None: 334 | new_p = p.constraint(new_p) 335 | 336 | self.updates.append(K.update(p, new_p)) 337 | return self.updates 338 | 339 | def get_config(self): 340 | config = {'lr': float(K.get_value(self.lr)), 341 | 'decay': float(K.get_value(self.decay)), 342 | 'epsilon': self.epsilon, 343 | 'layca':self.layca} 344 | base_config = super(Adagrad, self).get_config() 345 | return dict(list(base_config.items()) + list(config.items())) -------------------------------------------------------------------------------- /keras/Example.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 8, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "x_train shape: (50000, 32, 32, 3)\n", 13 | "50000 train samples\n", 14 | "10000 test samples\n", 15 | "10000/10000 [==============================] - 1s 104us/step\n", 16 | "Test loss: 0.46083946466743947\n", 17 | "Test accuracy: 0.8746\n" 18 | ] 19 | }, 20 | { 21 | "data": { 22 | "image/png": "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\n", 23 | "text/html": [ 24 | "\n", 25 | "\n", 26 | "\n", 29 | "\n", 30 | "
\n", 31 | "" 67 | ], 68 | "text/plain": [ 69 | "" 70 | ] 71 | }, 72 | "metadata": {}, 73 | "output_type": "display_data" 74 | }, 75 | { 76 | "data": { 77 | "image/png": "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\n5AAAAABJRU5ErkJggg==\n", 78 | "text/html": [ 79 | "\n", 80 | "\n", 81 | "\n", 84 | "\n", 85 | "
\n", 86 | "" 122 | ], 123 | "text/plain": [ 124 | "" 125 | ] 126 | }, 127 | "metadata": {}, 128 | "output_type": "display_data" 129 | } 130 | ], 131 | "source": [ 132 | "'''\n", 133 | "Code inspired by keras cifar10_cnn.py example https://github.com/keras-team/keras/blob/master/examples/cifar10_cnn.py\n", 134 | "'''\n", 135 | "%matplotlib inline\n", 136 | "import mpld3\n", 137 | "mpld3.enable_notebook()\n", 138 | "\n", 139 | "from __future__ import print_function\n", 140 | "import keras\n", 141 | "from keras.datasets import cifar10\n", 142 | "from keras.models import Sequential\n", 143 | "from keras.layers import Dense, Activation, BatchNormalization\n", 144 | "from keras.layers import Conv2D, MaxPooling2D, GlobalAveragePooling2D\n", 145 | "from keras.callbacks import LearningRateScheduler\n", 146 | "import os\n", 147 | "\n", 148 | "import matplotlib.pyplot as plt\n", 149 | "\n", 150 | "from layer_rotation_control import SGD\n", 151 | "from layer_rotation_monitoring import LayerRotationCurves\n", 152 | "\n", 153 | "batch_size = 32\n", 154 | "num_classes = 10\n", 155 | "epochs = 100\n", 156 | "verbose = 0\n", 157 | "\n", 158 | "# The data, split between train and test sets:\n", 159 | "(x_train, y_train), (x_test, y_test) = cifar10.load_data()\n", 160 | "print('x_train shape:', x_train.shape)\n", 161 | "print(x_train.shape[0], 'train samples')\n", 162 | "print(x_test.shape[0], 'test samples')\n", 163 | "\n", 164 | "# Convert class vectors to binary class matrices.\n", 165 | "y_train = keras.utils.to_categorical(y_train, num_classes)\n", 166 | "y_test = keras.utils.to_categorical(y_test, num_classes)\n", 167 | "\n", 168 | "x_train = x_train.astype('float32')\n", 169 | "x_test = x_test.astype('float32')\n", 170 | "x_train /= 255\n", 171 | "x_test /= 255\n", 172 | "\n", 173 | "model = Sequential()\n", 174 | "model.add(Conv2D(64, (3, 3), padding='same',\n", 175 | " input_shape=x_train.shape[1:]))\n", 176 | "model.add(BatchNormalization())\n", 177 | "model.add(Activation('relu'))\n", 178 | "model.add(Conv2D(64, (3, 3)))\n", 179 | "model.add(BatchNormalization())\n", 180 | "model.add(Activation('relu'))\n", 181 | "model.add(MaxPooling2D(pool_size=(2, 2)))\n", 182 | "\n", 183 | "model.add(Conv2D(128, (3, 3), padding='same'))\n", 184 | "model.add(BatchNormalization())\n", 185 | "model.add(Activation('relu'))\n", 186 | "model.add(Conv2D(128, (3, 3)))\n", 187 | "model.add(BatchNormalization())\n", 188 | "model.add(Activation('relu'))\n", 189 | "model.add(MaxPooling2D(pool_size=(2, 2)))\n", 190 | "\n", 191 | "model.add(Conv2D(256, (3, 3), padding='same'))\n", 192 | "model.add(BatchNormalization())\n", 193 | "model.add(Activation('relu'))\n", 194 | "model.add(Conv2D(256, (3, 3)))\n", 195 | "model.add(BatchNormalization())\n", 196 | "model.add(Activation('relu'))\n", 197 | "\n", 198 | "model.add(GlobalAveragePooling2D())\n", 199 | "model.add(Dense(num_classes))\n", 200 | "model.add(Activation('softmax'))\n", 201 | "\n", 202 | "lr = 3**-3\n", 203 | "opt = SGD(lr, layca = True)\n", 204 | "\n", 205 | "# a keras callback to record layer rotation\n", 206 | "lrc = LayerRotationCurves()\n", 207 | "\n", 208 | "# learning rate schedule: divide learning rate by 5 at epochs 70 and 90\n", 209 | "def schedule(epoch):\n", 210 | " new_lr = lr\n", 211 | " if epoch > 70:\n", 212 | " new_lr *= 0.2\n", 213 | " if epoch >90:\n", 214 | " new_lr *= 0.2\n", 215 | " return new_lr\n", 216 | "lrs = LearningRateScheduler(schedule)\n", 217 | "\n", 218 | "callbacks = [lrc, lrs]\n", 219 | "\n", 220 | "# Let's train the model\n", 221 | "model.compile(loss='categorical_crossentropy',\n", 222 | " optimizer=opt,\n", 223 | " metrics=['accuracy'])\n", 224 | "\n", 225 | "history = model.fit(x_train, y_train,\n", 226 | " batch_size=batch_size,\n", 227 | " epochs=epochs,\n", 228 | " validation_data=(x_test, y_test),\n", 229 | " shuffle=True,\n", 230 | " callbacks = callbacks,\n", 231 | " verbose = verbose)\n", 232 | "\n", 233 | "# Score trained model.\n", 234 | "scores = model.evaluate(x_test, y_test, verbose=1)\n", 235 | "print('Test loss:', scores[0])\n", 236 | "print('Test accuracy:', scores[1])\n", 237 | "\n", 238 | "# plot training curves\n", 239 | "plt.figure()\n", 240 | "plt.plot(model.history.history['acc'])\n", 241 | "plt.plot(model.history.history['val_acc'])\n", 242 | "\n", 243 | "# plot layer rotation curves\n", 244 | "plt.figure()\n", 245 | "lrc.plot()" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": null, 251 | "metadata": { 252 | "collapsed": true 253 | }, 254 | "outputs": [], 255 | "source": [] 256 | } 257 | ], 258 | "metadata": { 259 | "kernelspec": { 260 | "display_name": "Python 3", 261 | "language": "python", 262 | "name": "python3" 263 | }, 264 | "language_info": { 265 | "codemirror_mode": { 266 | "name": "ipython", 267 | "version": 3 268 | }, 269 | "file_extension": ".py", 270 | "mimetype": "text/x-python", 271 | "name": "python", 272 | "nbconvert_exporter": "python", 273 | "pygments_lexer": "ipython3", 274 | "version": "3.5.6" 275 | } 276 | }, 277 | "nbformat": 4, 278 | "nbformat_minor": 2 279 | } 280 | --------------------------------------------------------------------------------