def _get_batch(self, batch_size, s="train"): """Create batch of n pairs, half same class, half different class""" X = self.data[s] n_classes, n_examples, w, h = X.shape pairs = [np.zeros((batch_size, w, h, 1))] * 2 targets = np.zeros((batch_size, )) half_batch = batch_size // 2 targets[half_batch:] = 1 categories_1 = rng.choice(n_classes, size=(batch_size, ), replace=False) first_half_2 = categories_1[:half_batch] second_half_2 = np.asarray( map(lambda c: (c + rng.randint(1, n_classes)) % n_classes, categories_1[half_batch:])) categories_2 = np.concatenate((first_half_2, second_half_2), axis=0) which_examples_1 = rng.choice(n_examples, size=batch_size, replace=True) which_examples_2 = rng.choice(n_examples, size=batch_size, replace=True) eprint('generating a batch of {}'.format(batch_size)) pairs[0] = X[categories_1, which_examples_1].reshape(batch_size, w, h, 1) pairs[1] = X[categories_2, which_examples_2].reshape(batch_size, w, h, 1) return pairs, targets
def _build_model_impl(self, input_shape): filter_W_init = RandomNormal(mean=0, stddev=1e-2) b_init = RandomNormal(mean=0.5, stddev=1e-2) fully_W_init = RandomNormal(mean=0, stddev=1e-1) left_input = Input(input_shape) right_input = Input(input_shape) self.encoder = Sequential() self.encoder.add(Conv2D(64, (4, 4), activation='relu', input_shape=input_shape, kernel_regularizer=l2(2e-4), kernel_initializer=filter_W_init, bias_initializer=b_init)) self.encoder.add(MaxPooling2D()) self.encoder.add(Conv2D(128, (3, 3), activation='relu', kernel_regularizer=l2(2e-4), kernel_initializer=filter_W_init, bias_initializer=b_init)) self.encoder.add(MaxPooling2D()) self.encoder.add(Conv2D(128, (2, 2), activation='relu', kernel_regularizer=l2(2e-4), kernel_initializer=filter_W_init, bias_initializer=b_init)) self.encoder.add(MaxPooling2D()) self.encoder.add(Conv2D(256, (2, 2), activation='relu', kernel_regularizer=l2(2e-4), kernel_initializer=filter_W_init, bias_initializer=b_init)) self.encoder.add(Flatten()) self.encoder.add(Dense(512, activation="sigmoid", kernel_regularizer=l2(1e-3), kernel_initializer=fully_W_init, bias_initializer=b_init)) # encode each of the two inputs into a vector with the convnet encoded_l = self.encoder(left_input) encoded_r = self.encoder(right_input) # merge two encoded inputs with the l1 distance between them both = Lambda(lambda x: K.abs(x[0] - x[1]), output_shape=lambda x: x[0])([encoded_l, encoded_r]) prediction = Dense(1, activation='sigmoid', bias_initializer=b_init, kernel_initializer=fully_W_init)(both) self.model = Model(inputs=[left_input, right_input], outputs=prediction) eprint( 'Model built with {} parameters'.format(self.model.count_params()))
def __init__(self, path): super(MnistGenerator, self).__init__() mnist = io.loadmat('{}/mnist-original.mat'.format(path)) X = mnist['data'].T # change from Matlab format to Numpy one y = mnist['label'].squeeze() # ditto eprint('load X with shape {}'.format(X.shape)) eprint('load y with shape {}'.format(y.shape)) # scaled_X = np.asarray( # map(lambda x: cv2.resize(x.reshape(28, 28), (105, 105)), X)) scaled_X = np.asarray(map(lambda x: x.reshape(28, 28), X)) rearranged_X = map(lambda i: scaled_X[y == i], range(10)) trim_to_dim = min(map(lambda x: x.shape[0], rearranged_X)) self.data = 255.0 - np.asarray( map(lambda x: x[:trim_to_dim], rearranged_X))
def _build_model(self, input_shape, force_rebuilt=False, build_model_only=False): if self.model is None or force_rebuilt: eprint('build model from scratch') self._build_model_impl(input_shape) eprint('reset init epoch to zero') self.init_epoch = 0 else: # train on a existed model pass if not build_model_only: self._create_callbacks() self._compile_model() self._restore_from_ckpt()
def __init__(self, path): super(OmniglotGenerator, self).__init__() self.data = {} self.classes = {} with open(os.path.join(path, "train.pickle"), "r") as f: self.data['train'], self.classes['train'] = pickle.load(f) with open(os.path.join(path, "val.pickle"), "r") as f: self.data['val'], self.classes['val'] = pickle.load(f) num_trains, num_examples, w, h = self.data['train'].shape eprint('(#classes, #examples, w, h): {}'.format( (num_trains, num_examples, w, h))) self.input_shape = (w, h, 1) # estimated number of positive pairs, let C = num_trains, # E = num_examples, then it equals C * choose(E, 2). estimated_positive_pairs = \ num_trains * num_examples * (num_examples - 1) // 2 eprint( 'estimated # positive-pairs: {}'.format(estimated_positive_pairs)) self.data_size = estimated_positive_pairs
def _fit_impl(self, generator): """ fit a generator :param generator: an instance of SNNGenerator or its subclasses """ steps_per_epoch = generator.data_size() // self.batch_size validation_steps = self.n_val // self.batch_size eprint('steps / epoch: {}'.format(steps_per_epoch)) eprint('validation steps: {}'.format(validation_steps)) self.model.fit_generator( generator=generator.train_generator(self.batch_size), steps_per_epoch=steps_per_epoch, epochs=self.n_epoch, validation_data=generator.dev_generator(self.batch_size), validation_steps=validation_steps, callbacks=self.callbacks, verbose=2, initial_epoch=self.init_epoch)
def __init__(self, path): super(GoldGenerator, self).__init__() loaded = np.load('{}/features.npz'.format(path)) self.images = loaded['features'] self.targets = loaded['targets'] assert len(self.images) == len(self.targets), \ '#images does not match #targets' self.h, self.w = self.images[0].shape[:2] eprint('targets = {}'.format(self.targets)) self.alphabet = loaded['alphabet'] eprint('number of chars in the alphabet: {}'.format(len( self.alphabet))) self.data = map(lambda g: self.images[self.targets == g], self.alphabet) self.indices = map(lambda g: np.where(self.targets == g)[0], self.alphabet) self.n_images, self.n_alphabet = len(self.images), len(self.alphabet) self.alphabet_basis = self._alphabet_basis() eprint('generate alphabet basis with shape {}'.format( self.alphabet_basis.shape)) self.data_size = np.sum( [len(d) * (len(d) - 1) // 2 for d in self.data])
def _save_impl(self, path): eprint('caution: model save fall back into its base class,' ' extended objects would not be saved.') eprint('implement your own _saveImpl if you need more.') pass
def _restore_from_ckpt(self): assert self.model is not None try: eprint('attempt to restore weights from the checkpoint ...') self.model.load_weights('{}/checkpoint.h5'.format(self.model_path)) except Exception as e: eprint('restore from checkpoint failed: {}'.format(e)) try: eprint('attempt to restore weights from saved model ...') self.model.load_weights('{}/model.h5'.format(self.model_path)) except Exception as e: eprint('restore from saved model failed: {}'.format(e)) try: eprint('attempt to restore epoch count ...') with open('{}/epoch_count.txt'.format(self.model_path), 'r') as f: epoch_count = int(f.readline()) eprint('reset init epoch from {} to {}'.format( self.init_epoch, epoch_count)) self.init_epoch = epoch_count except Exception as e: eprint('restore epoch count failed: {}'.format(e))
def setup_fine_tuning(self): eprint('set model to fine tune mode ...') for layer in self.model.layers[:-2]: layer.trainable = False
from snn.utils import eprint if __name__ == '__main__': generator = OmniglotGenerator(sys.argv[1]) # load training data from dir model_path = sys.argv[2] # output model path loss = 'binary_crossentropy' metrics = ['binary_crossentropy'] optimizer = Adam(0.00006) n_epoch = 10000 batch_size = 128 early_stop_patience = 10 n_val = 10000 try: eprint('try to load model from {}'.format(model_path)) encoder = SNN.load(model_path) except Exception as e: eprint('load model error: {}'.format(e)) eprint('attempt to load model failed, prepare to train it.') encoder = SNN(model_path=model_path) encoder.loss = loss encoder.metrics = metrics encoder.optimizer = optimizer encoder.n_epoch = n_epoch encoder.batch_size = batch_size encoder.early_step_patience = 10 encoder.n_val = n_val encoder.fit(generator)