def get_image_features(self, task, batched_lmap_speed_thresh=None): if batched_lmap_speed_thresh is None: batched_lmap_speed_thresh = self.batched_lmap_speed_thresh images = task.images try: rval, _images, cdict = self.image_features[images] # -- currently it is true that all tasks should be indexing into # -- the same set of images. Later when this is not the case, # -- delete this over-strict check. assert _images is images except KeyError: feature_lmap = self.get_image_features_lmap(task.images, batched_lmap_speed_thresh) rval = cache_memmap( feature_lmap, self.memmap_name + '_image_features_' + task.name, del_atexit=self.memmap_del_atexit) foobar.append_ndarray_signature(rval[0], 'get_image_features features 0', task.name) foobar.append_ndarray_signature(rval[100], 'get_image_features features 100', task.name) cdict = {} self.image_features[images] = rval, images, cdict return rval, cdict
def alloc_random_uniform_filterbank(n_filters, height, width, channels, dtype, rseed, normalize=True): """ Generate the same weights as are generated by pythor3 """ if height != width: raise ValueError('filters must be square') if channels is None: filter_shape = [n_filters, height, width] else: filter_shape = [n_filters, height, width, channels] rng = np.random.RandomState(rseed) foobar.append_randomstate('alloc_random_uniform_filterbank', rng) fb_data = rng.uniform(size=filter_shape) # normalize each filter in the bank if needed if normalize: # TODO: vectorize these computations, do all at once. for fidx, filt in enumerate(fb_data): # normalization here means zero-mean, unit-L2norm filt -= filt.mean() filt_norm = np.sqrt((filt * filt).sum()) assert filt_norm != 0 filt /= filt_norm fb_data[fidx] = filt foobar.append_ndarray_signature(fb_data, 'alloc_random_uniform_filterbank') return fb_data.astype(dtype)
def fb_whitened_projections(patches, pwfX, n_filters, rseed, dtype): """ pwfX is the output of patch_whitening_filterbank_X with reshape=False M, and fb will be reshaped to match elements of patches """ M, P, patches_cn = pwfX if patches_cn.ndim != 2: raise TypeError('wrong shape for pwfX args, should be flattened', patches_cn.shape) rng = np.random.RandomState(rseed) foobar.append_randomstate('fb_whitened_projections', rng) D = rng.randn(n_filters, patches_cn.shape[1]) D = D / (np.sqrt((D**2).sum(axis=1))[:, None] + 1e-20) fb = dot_f32(D, P) fb.shape = (n_filters, ) + patches.shape[1:] M.shape = patches.shape[1:] M = M.astype(dtype) fb = fb.astype(dtype) if fb.size == 0: raise ValueError('filterbank had size 0') foobar.append_ndarray_signature(M, 'fb_whitened_projections M') foobar.append_ndarray_signature(fb, 'fb_whitened_projections fb') return M, fb
def get_image_features(self, task, batched_lmap_speed_thresh=None): if batched_lmap_speed_thresh is None: batched_lmap_speed_thresh = self.batched_lmap_speed_thresh images = task.images try: rval, _images, cdict = self.image_features[images] # -- currently it is true that all tasks should be indexing into # -- the same set of images. Later when this is not the case, # -- delete this over-strict check. assert _images is images except KeyError: feature_lmap = self.get_image_features_lmap( task.images, batched_lmap_speed_thresh) rval = cache_memmap(feature_lmap, self.memmap_name + '_image_features_' + task.name, del_atexit=self.memmap_del_atexit) foobar.append_ndarray_signature(rval[0], 'get_image_features features 0', task.name) foobar.append_ndarray_signature(rval[100], 'get_image_features features 100', task.name) cdict = {} self.image_features[images] = rval, images, cdict return rval, cdict
def fb_whitened_projections(patches, pwfX, n_filters, rseed, dtype): """ pwfX is the output of patch_whitening_filterbank_X with reshape=False M, and fb will be reshaped to match elements of patches """ M, P, patches_cn = pwfX if patches_cn.ndim != 2: raise TypeError('wrong shape for pwfX args, should be flattened', patches_cn.shape) rng = np.random.RandomState(rseed) foobar.append_randomstate('fb_whitened_projections', rng) D = rng.randn(n_filters, patches_cn.shape[1]) D = D / (np.sqrt((D ** 2).sum(axis=1))[:, None] + 1e-20) fb = dot_f32(D, P) fb.shape = (n_filters,) + patches.shape[1:] M.shape = patches.shape[1:] M = M.astype(dtype) fb = fb.astype(dtype) if fb.size == 0: raise ValueError('filterbank had size 0') foobar.append_ndarray_signature(M, 'fb_whitened_projections M') foobar.append_ndarray_signature(fb, 'fb_whitened_projections fb') return M, fb
def load_ensemble_grams(self, norm_sample, ens, sample1, sample2): trial_attachments = self.ctrl.trials.trial_attachments # -- load the gram matrices saved by each ensemble member for trial in self.history: trial_norm_key = self.norm_key(norm_sample, tid=trial['tid']) info('Loading grams from document %i' % trial['tid']) debug(' .. saved_grams: %s' % str(trial['result']['grams'][trial_norm_key])) for (s1, s2) in trial['result']['grams'][trial_norm_key]: if set([sample1, sample2]) == set([s1, s2]): if not ens.has_gram(trial_norm_key, s1, s2): att_key = 'gram_%s_%s_%s.pkl' % (trial_norm_key, s1, s2) info('retrieving gram_data %i:%s' % (trial['tid'], att_key)) try: gram_data = cached_gram_load(trial['tid'], att_key) except IOError: gram_data = trial_attachments(trial)[att_key] cached_gram_save(trial['tid'], att_key, gram_data) info('retrieved %i bytes' % len(gram_data)) gram = loads_gram(gram_data) if s1 == sample1: ens.add_gram(trial_norm_key, sample1, sample2, gram) else: ens.add_gram(trial_norm_key, sample1, sample2, gram.T) foobar.append_ndarray_signature( gram, 'load gram', trial_norm_key, sample1, sample2) info('Loading grams done')
def unsup_images(data_view, trn, N): """ Return a block of """ if trn == 'DevTrain': # -- extract training images, and put them into channel-major format imgs = larray.reindex(data_view.image_pixels, data_view.dev_train['lpathidx'][0, :N])[:] imgs = np.asarray(imgs) assert 'int' in str(imgs.dtype) foobar.append_ndarray_signature(imgs, 'unsup_images') foobar.append_trace('unsup_images N', N) return imgs.transpose(0, 3, 1, 2).copy() else: raise NotImplementedError()
def patch_whitening_filterbank_X(patches, o_ndim, gamma, remove_mean, beta, hard_beta, ): """ patches - Image patches (can be uint8 pixels or floats) o_ndim - 2 to get matrix outputs, 4 to get image-stack outputs gamma - non-negative real to boost low-principle components remove_mean - see contrast_normalize beta - see contrast_normalize hard_beta - see contrast_normalize Returns: M, P, X M - mean of contrast-normalized patches P - whitening matrix / filterbank for contrast-normalized patches X - contrast-normalized patches """ # Algorithm from Coates' sc_vq_demo.m # -- patches -> column vectors X = patches.reshape(len(patches), -1).astype('float64') X = contrast_normalize(X, remove_mean=remove_mean, beta=beta, hard_beta=hard_beta) # -- ZCA whitening (with low-pass) logger.debug('patch_whitening_filterbank_X starting ZCA') M, _std = mean_and_std(X) Xm = X - M assert Xm.shape == X.shape logger.info('patch_whitening_filterbank_X starting ZCA: dot %s' % str(Xm.shape)) C = dot_f64(Xm.T, Xm) / (Xm.shape[0] - 1) logger.debug('patch_whitening_filterbank_X starting ZCA: eigh') D, V = np.linalg.eigh(C) logger.debug( 'patch_whitening_filterbank_X starting ZCA: dot %s' % str(V.shape)) P = dot_f32(np.sqrt(1.0 / (D + gamma)) * V, V.T) # -- return to image space if o_ndim == 4: M = M.reshape(patches.shape[1:]) P = P.reshape((P.shape[0],) + patches.shape[1:]) X = X.reshape((len(X),) + patches.shape[1:]) elif o_ndim == 2: pass else: raise ValueError('o_ndim not in (2, 4)', o_ndim) logger.debug('patch_whitening_filterbank_X -> done') foobar.append_ndarray_signature(M, 'patch_whitening_filterbank_X M') foobar.append_ndarray_signature(P, 'patch_whitening_filterbank_X P') foobar.append_ndarray_signature(X, 'patch_whitening_filterbank_X X') dtype = patches.dtype return M.astype(dtype), P.astype(dtype), X.astype(dtype)
def contrast_normalize(patches, remove_mean, beta, hard_beta): X = patches if X.ndim != 2: raise TypeError('contrast_normalize requires flat patches') if remove_mean: xm = X.mean(1) else: xm = X[:, 0] * 0 Xc = X - xm[:, None] if 0: # -- for some reason the following sometimes uses gigs of RAM l2 = (Xc * Xc).sum(axis=1) else: l2 = np.zeros_like(Xc[:, 0]) for i in xrange(Xc.shape[1]): l2 += Xc[:, i]**2 if hard_beta: div2 = np.maximum(l2, beta) else: div2 = l2 + beta Xc /= np.sqrt(div2[:, None]) foobar.append_ndarray_signature(Xc, 'contrast_normalize') return Xc
def fb_whitened_patches(patches, pwfX, n_filters, rseed, dtype): """ pwfX is the output of patch_whitening_filterbank_X with reshape=False M, and fb will be reshaped to match elements of patches """ M, P, patches_cn = pwfX rng = np.random.RandomState(rseed) foobar.append_randomstate('fb_whitened_patches', rng) d_elems = rng.randint(len(patches_cn), size=n_filters) D = dot_f64(patches_cn[d_elems] - M, P) D = D / (np.sqrt((D**2).sum(axis=1))[:, None] + 1e-20) fb = dot_f32(D, P) fb.shape = (n_filters, ) + patches.shape[1:] M.shape = patches.shape[1:] M = M.astype(dtype) fb = fb.astype(dtype) if fb.size == 0: raise ValueError('filterbank had size 0') foobar.append_ndarray_signature(M, 'fb_whitened_patches M') foobar.append_ndarray_signature(fb, 'fb_whitened_patches fb') return M, fb
def fb_whitened_patches(patches, pwfX, n_filters, rseed, dtype): """ pwfX is the output of patch_whitening_filterbank_X with reshape=False M, and fb will be reshaped to match elements of patches """ M, P, patches_cn = pwfX rng = np.random.RandomState(rseed) foobar.append_randomstate('fb_whitened_patches', rng) d_elems = rng.randint(len(patches_cn), size=n_filters) D = dot_f64(patches_cn[d_elems] - M, P) D = D / (np.sqrt((D ** 2).sum(axis=1))[:, None] + 1e-20) fb = dot_f32(D, P) fb.shape = (n_filters,) + patches.shape[1:] M.shape = patches.shape[1:] M = M.astype(dtype) fb = fb.astype(dtype) if fb.size == 0: raise ValueError('filterbank had size 0') foobar.append_ndarray_signature(M, 'fb_whitened_patches M') foobar.append_ndarray_signature(fb, 'fb_whitened_patches fb') return M, fb
def contrast_normalize(patches, remove_mean, beta, hard_beta): X = patches if X.ndim != 2: raise TypeError('contrast_normalize requires flat patches') if remove_mean: xm = X.mean(1) else: xm = X[:,0] * 0 Xc = X - xm[:, None] if 0: # -- for some reason the following sometimes uses gigs of RAM l2 = (Xc * Xc).sum(axis=1) else: l2 = np.zeros_like(Xc[:, 0]) for i in xrange(Xc.shape[1]): l2 += Xc[:, i] ** 2 if hard_beta: div2 = np.maximum(l2, beta) else: div2 = l2 + beta Xc /= np.sqrt(div2[:, None]) foobar.append_ndarray_signature(Xc, 'contrast_normalize') return Xc
def random_patches(images, N, R, C, rng, channel_major=False, memlimit=None): """Return a stack of N image patches (channel major version)""" def N_with_memlimit(): if memlimit is not None: # -- memlimit in bytes sizelimit = memlimit / images.dtype.itemsize return min(N, sizelimit // (R * C * iF)) else: return N if channel_major: n_imgs, iF, iR, iC = images.shape N = N_with_memlimit() rval = np.empty((N, iF, R, C), dtype=images.dtype) else: n_imgs, iR, iC, iF = images.shape N = N_with_memlimit() rval = np.empty((N, R, C, iF), dtype=images.dtype) foobar.append_trace('random_patches dims', *rval.shape) foobar.append_randomstate('random_patches rng', rng) srcs = rng.randint(n_imgs, size=N) if R > iR or C > iC: raise InvalidDescription('cannot extract patches', (R, C)) roffsets = rng.randint(iR - R + 1, size=N) coffsets = rng.randint(iC - C + 1, size=N) # TODO: this can be done with one advanced index right? for rv_i, src_i, ro, co in zip(rval, srcs, roffsets, coffsets): if channel_major: rv_i[:] = images[src_i, :, ro: ro + R, co : co + C] else: rv_i[:] = images[src_i, ro: ro + R, co : co + C] foobar.append_ndarray_signature(rval, 'random_patches rval') return rval
def random_patches(images, N, R, C, rng, channel_major=False, memlimit=None): """Return a stack of N image patches (channel major version)""" def N_with_memlimit(): if memlimit is not None: # -- memlimit in bytes sizelimit = memlimit / images.dtype.itemsize return min(N, sizelimit // (R * C * iF)) else: return N if channel_major: n_imgs, iF, iR, iC = images.shape N = N_with_memlimit() rval = np.empty((N, iF, R, C), dtype=images.dtype) else: n_imgs, iR, iC, iF = images.shape N = N_with_memlimit() rval = np.empty((N, R, C, iF), dtype=images.dtype) foobar.append_trace('random_patches dims', *rval.shape) foobar.append_randomstate('random_patches rng', rng) srcs = rng.randint(n_imgs, size=N) if R > iR or C > iC: raise InvalidDescription('cannot extract patches', (R, C)) roffsets = rng.randint(iR - R + 1, size=N) coffsets = rng.randint(iC - C + 1, size=N) # TODO: this can be done with one advanced index right? for rv_i, src_i, ro, co in zip(rval, srcs, roffsets, coffsets): if channel_major: rv_i[:] = images[src_i, :, ro:ro + R, co:co + C] else: rv_i[:] = images[src_i, ro:ro + R, co:co + C] foobar.append_ndarray_signature(rval, 'random_patches rval') return rval
def normalized_image_match_features(self, task, svm_dct, role, batched_lmap_speed_thresh=None): assert role in ('train', 'test') if batched_lmap_speed_thresh is None: batched_lmap_speed_thresh = self.batched_lmap_speed_thresh image_features, cdict = self.get_image_features(task, batched_lmap_speed_thresh=batched_lmap_speed_thresh) del cdict # -- no longer used (waste of memory) pipeline = self.pipeline info('Indexing into image_features of shape %s' % str(image_features.shape)) comps = [getattr(comparisons, cc) for cc in self.comparison_names] n_features = np.prod(image_features.shape[1:]) n_trn = len(task.lidx) x_trn_shp = (n_trn, len(comps), n_features) info('Allocating training ndarray of shape %s' % str(x_trn_shp)) x_trn = np.empty(x_trn_shp, dtype='float32') # -- pre-compute all of the image_features we will need all_l_features = reindex(image_features, task.lidx)[:] all_r_features = reindex(image_features, task.ridx)[:] all_l_features = all_l_features.reshape(len(all_l_features), -1) all_r_features = all_r_features.reshape(len(all_r_features), -1) foobar.append_ndarray_signature(all_l_features, 'normalized_image_match l_features', task.name) foobar.append_ndarray_signature(all_r_features, 'normalized_image_match r_features', task.name) if role == 'train': if np.allclose(all_l_features.var(axis=0), 0.0): raise ValueError( 'Homogeneous features (non-finite features)') xmean_l, xstd_l = mean_and_std(all_l_features, remove_std0=pipeline['remove_std0']) xmean_r, xstd_r = mean_and_std(all_r_features, remove_std0=pipeline['remove_std0']) xmean = (xmean_l + xmean_r) / 2.0 # -- this is an ad-hoc way of blending the variances. xstd = np.sqrt(np.maximum(xstd_l, xstd_r) ** 2 + pipeline['varthresh']) foobar.append_ndarray_signature( xmean, 'normalized_image_match xmean', task.name) foobar.append_ndarray_signature( xstd, 'normalized_image_match xstd', task.name) svm_dct['xmean'] = xmean svm_dct['xstd'] = xstd else: xmean = svm_dct['xmean'] xstd = svm_dct['xstd'] info('Computing comparison features') # -- now compute the "comparison functions" into x_trn for jj, (lfeat, rfeat) in enumerate( zip(all_l_features, all_r_features)): lfeat_z = (lfeat - xmean) / xstd rfeat_z = (rfeat - xmean) / xstd for ci, comp in enumerate(comps): x_trn[jj, ci, :] = comp(lfeat_z, rfeat_z) if pipeline['divrowl2']: info('Dividing by feature norms') # -- now normalize by average feature norm because some # comparison functions come out smaller than others if role == 'train': svm_dct['divrowl2_avg_nrm'] = {} for ci, cname in enumerate(self.comparison_names): avg_nrm = average_row_l2norm(x_trn[:, ci, :]) + 1e-7 svm_dct['divrowl2_avg_nrm'][cname] = avg_nrm avg_nrm_vec = [svm_dct['divrowl2_avg_nrm'][cname] for cname in self.comparison_names] x_trn /= np.asarray(avg_nrm_vec)[None, :, None] foobar.append_trace('get_normlized_features avg_nrm', avg_nrm_vec) # -- collapse comparison and feature dimensions x_trn.shape = (x_trn.shape[0], x_trn.shape[1] * x_trn.shape[2]) foobar.append_ndarray_signature( x_trn, 'normalized_image_match x_trn', task.name) info('normalized_image_match_features complete') return x_trn
def train_image_match_indexed(self, task, valid=None): pipeline = self.pipeline info('training svm on %s' % task.name) ens = EnsembleSVC(task.name) norm_task = task.name norm_key = self.norm_key(norm_task) svm_dct = { 'ens': ens, 'norm_key': norm_key, 'norm_task': task.name, 'task_name': task.name, } ens.add_member(norm_key) ens.add_sample(task.name, task.y) x_trn = self.normalized_image_match_features(task, svm_dct, role='train') ens.add_features(norm_key, task.name, x_trn) foobar.append_ndarray_signature(x_trn, 'train_image x_trn', norm_key, task.name) info('computing gram: %s / %s / %s' % ( norm_key, task.name, task.name)) ens.compute_gram(norm_key, task.name, task.name, dtype='float32') foobar.append_ndarray_signature( ens._grams[(norm_key, task.name, task.name)], 'train_image train_gram', norm_key, task.name) if valid is not None: info('cross-validating svm on %s' % valid.name) x_val = self.normalized_image_match_features(valid, svm_dct, role='test', # -- assume that slow features were caught earlier batched_lmap_speed_thresh={'seconds': 30, 'elements': 1}, ) foobar.append_ndarray_signature( x_val, 'train_image x_val', norm_key, valid.name, task.name) ens.add_sample(valid.name, valid.y) ens.add_features(norm_key, valid.name, x_val) info('computing gram: %s / %s / %s' % ( norm_key, valid.name, task.name)) ens.compute_gram(norm_key, valid.name, task.name, dtype='float32') foobar.append_ndarray_signature( ens._grams[(norm_key, valid.name, task.name)], 'train_image valid_gram', norm_key, valid.name, task.name) # -- re-fit the model using best weights on train + valid sets info('computing gram: %s / %s / %s' % ( norm_key, valid.name, valid.name)) ens.compute_gram(norm_key, valid.name, valid.name, dtype='float32') train_valid = '%s_%s' % (task.name, valid.name) ens.add_compound_sample(train_valid, [task.name, valid.name]) def load_history(): info('loading history') self.load_ensemble_history( fields=['result.weights','result.grams']) self.load_ensemble_weights(norm_task, task.name, ens) self.load_ensemble_grams(norm_task, ens, task.name, task.name) if valid is not None: self.load_ensemble_grams(norm_task, ens, valid.name, task.name) self.load_ensemble_grams(norm_task, ens, valid.name, valid.name) def train_main(): ens.train_sample = task.name t0 = time.time() if valid is None: svm_dct['l2_reg'] = pipeline['l2_reg'] ens.fit_svm(svm_dct['l2_reg']) svm_dct['train_error'] = ens.error_rate(task.name) svm_dct['loss'] = svm_dct['train_error'] else: #scales = {m: 3.0 for m in ens._weights} scales = dict([(m, 3.0) for m in ens._weights]) scales[norm_key] = 100.0 info('fit_weights_crossvalid(%s, %i)' % ( valid.name, self.svm_crossvalid_max_evals)) ens.fit_weights_crossvalid(valid.name, max_evals=self.svm_crossvalid_max_evals, scales=scales) foobar.append_trace('xvalid weights', sorted(ens._weights.items())) svm_dct['task_error'] = ens.error_rate(task.name) foobar.append_trace('task_error', svm_dct['task_error']) svm_dct['valid_name'] = valid.name svm_dct['valid_error'] = ens.error_rate(valid.name) info('valid_error %f' % svm_dct['valid_error']) foobar.append_trace('valid_error', svm_dct['valid_error']) svm_dct['l2_reg'] = None # -- use default when retraining # -- re-fit the model using best weights on train + valid sets ens.train_sample = train_valid ens.fit_svm() fit_time = time.time() - t0 svm_dct['fit_time'] = fit_time info('training with just the current features...') train_main() svm_dct['task_error_no_ensemble'] = svm_dct['task_error'] svm_dct['valid_error_no_ensemble'] = svm_dct['valid_error'] load_history() if self.history: info('training the full ensemble...') train_main() try: print_summary = ens.print_summary except AttributeError: print_summary = lambda : None print_summary() dct = self._results['train_image_match_indexed'] dct.setdefault(norm_key, {}) if task.name in dct[norm_key]: warn('Overwriting train_image_match_indexed result: %s' % task.name) dct[norm_key][task.name] = svm_dct return svm_dct
def normalized_image_match_features(self, task, svm_dct, role, batched_lmap_speed_thresh=None): assert role in ('train', 'test') if batched_lmap_speed_thresh is None: batched_lmap_speed_thresh = self.batched_lmap_speed_thresh image_features, cdict = self.get_image_features( task, batched_lmap_speed_thresh=batched_lmap_speed_thresh) del cdict # -- no longer used (waste of memory) pipeline = self.pipeline info('Indexing into image_features of shape %s' % str(image_features.shape)) comps = [getattr(comparisons, cc) for cc in self.comparison_names] n_features = np.prod(image_features.shape[1:]) n_trn = len(task.lidx) x_trn_shp = (n_trn, len(comps), n_features) info('Allocating training ndarray of shape %s' % str(x_trn_shp)) x_trn = np.empty(x_trn_shp, dtype='float32') # -- pre-compute all of the image_features we will need all_l_features = reindex(image_features, task.lidx)[:] all_r_features = reindex(image_features, task.ridx)[:] all_l_features = all_l_features.reshape(len(all_l_features), -1) all_r_features = all_r_features.reshape(len(all_r_features), -1) foobar.append_ndarray_signature(all_l_features, 'normalized_image_match l_features', task.name) foobar.append_ndarray_signature(all_r_features, 'normalized_image_match r_features', task.name) if role == 'train': if np.allclose(all_l_features.var(axis=0), 0.0): raise ValueError('Homogeneous features (non-finite features)') xmean_l, xstd_l = mean_and_std(all_l_features, remove_std0=pipeline['remove_std0']) xmean_r, xstd_r = mean_and_std(all_r_features, remove_std0=pipeline['remove_std0']) xmean = (xmean_l + xmean_r) / 2.0 # -- this is an ad-hoc way of blending the variances. xstd = np.sqrt( np.maximum(xstd_l, xstd_r)**2 + pipeline['varthresh']) foobar.append_ndarray_signature(xmean, 'normalized_image_match xmean', task.name) foobar.append_ndarray_signature(xstd, 'normalized_image_match xstd', task.name) svm_dct['xmean'] = xmean svm_dct['xstd'] = xstd else: xmean = svm_dct['xmean'] xstd = svm_dct['xstd'] info('Computing comparison features') # -- now compute the "comparison functions" into x_trn for jj, (lfeat, rfeat) in enumerate(zip(all_l_features, all_r_features)): lfeat_z = (lfeat - xmean) / xstd rfeat_z = (rfeat - xmean) / xstd for ci, comp in enumerate(comps): x_trn[jj, ci, :] = comp(lfeat_z, rfeat_z) if pipeline['divrowl2']: info('Dividing by feature norms') # -- now normalize by average feature norm because some # comparison functions come out smaller than others if role == 'train': svm_dct['divrowl2_avg_nrm'] = {} for ci, cname in enumerate(self.comparison_names): avg_nrm = average_row_l2norm(x_trn[:, ci, :]) + 1e-7 svm_dct['divrowl2_avg_nrm'][cname] = avg_nrm avg_nrm_vec = [ svm_dct['divrowl2_avg_nrm'][cname] for cname in self.comparison_names ] x_trn /= np.asarray(avg_nrm_vec)[None, :, None] foobar.append_trace('get_normlized_features avg_nrm', avg_nrm_vec) # -- collapse comparison and feature dimensions x_trn.shape = (x_trn.shape[0], x_trn.shape[1] * x_trn.shape[2]) foobar.append_ndarray_signature(x_trn, 'normalized_image_match x_trn', task.name) info('normalized_image_match_features complete') return x_trn
def patch_whitening_filterbank_X( patches, o_ndim, gamma, remove_mean, beta, hard_beta, ): """ patches - Image patches (can be uint8 pixels or floats) o_ndim - 2 to get matrix outputs, 4 to get image-stack outputs gamma - non-negative real to boost low-principle components remove_mean - see contrast_normalize beta - see contrast_normalize hard_beta - see contrast_normalize Returns: M, P, X M - mean of contrast-normalized patches P - whitening matrix / filterbank for contrast-normalized patches X - contrast-normalized patches """ # Algorithm from Coates' sc_vq_demo.m # -- patches -> column vectors X = patches.reshape(len(patches), -1).astype('float64') X = contrast_normalize(X, remove_mean=remove_mean, beta=beta, hard_beta=hard_beta) # -- ZCA whitening (with low-pass) logger.debug('patch_whitening_filterbank_X starting ZCA') M, _std = mean_and_std(X) Xm = X - M assert Xm.shape == X.shape logger.info('patch_whitening_filterbank_X starting ZCA: dot %s' % str(Xm.shape)) C = dot_f64(Xm.T, Xm) / (Xm.shape[0] - 1) logger.debug('patch_whitening_filterbank_X starting ZCA: eigh') D, V = np.linalg.eigh(C) logger.debug('patch_whitening_filterbank_X starting ZCA: dot %s' % str(V.shape)) P = dot_f32(np.sqrt(1.0 / (D + gamma)) * V, V.T) # -- return to image space if o_ndim == 4: M = M.reshape(patches.shape[1:]) P = P.reshape((P.shape[0], ) + patches.shape[1:]) X = X.reshape((len(X), ) + patches.shape[1:]) elif o_ndim == 2: pass else: raise ValueError('o_ndim not in (2, 4)', o_ndim) logger.debug('patch_whitening_filterbank_X -> done') foobar.append_ndarray_signature(M, 'patch_whitening_filterbank_X M') foobar.append_ndarray_signature(P, 'patch_whitening_filterbank_X P') foobar.append_ndarray_signature(X, 'patch_whitening_filterbank_X X') dtype = patches.dtype return M.astype(dtype), P.astype(dtype), X.astype(dtype)