Repository: izikgo/AnomalyDetectionTransformations
Branch: master
Commit: 6327041c6377
Files: 14
Total size: 60.8 KB
Directory structure:
gitextract__9qwn17c/
├── .gitignore
├── LICENSE
├── README.md
├── experiments.py
├── intuition_experiments.py
├── models/
│ ├── __init__.py
│ ├── adgan.py
│ ├── dagmm.py
│ ├── dsebm.py
│ ├── encoders_decoders.py
│ └── wide_residual_network.py
├── multiclass_experiment.py
├── transformations.py
└── utils.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Custom
*.png
*.h5
*.npz
*.csv
*.zip
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# IPython Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# dotenv
.env
# virtualenv
venv/
ENV/
# Spyder project settings
.spyderproject
# Rope project settings
.ropeproject
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2018 izikgo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Deep Anomaly Detection Using Geometric Transformations
To be presented in NIPS 2018 by Izhak Golan and Ran El-Yaniv.
## Introduction
This is the official implementation of "Deep Anomaly Detection Using Geometric Transformations".
It includes all experiments reported in the paper.
## Requirements
* Python 3.5+
* Keras 2.2.0
* Tensorflow 1.8.0
* sklearn 0.19.1
## Citation
If you use the ideas or method presented in the paper, please cite:
```
@inproceedings{NEURIPS2018_5e62d03a,
author = {Golan, Izhak and El-Yaniv, Ran},
booktitle = {Advances in Neural Information Processing Systems},
editor = {S. Bengio and H. Wallach and H. Larochelle and K. Grauman and N. Cesa-Bianchi and R. Garnett},
pages = {},
publisher = {Curran Associates, Inc.},
title = {Deep Anomaly Detection Using Geometric Transformations},
url = {https://proceedings.neurips.cc/paper/2018/file/5e62d03aec0d17facfc5355dd90d441c-Paper.pdf},
volume = {31},
year = {2018}
}
```
================================================
FILE: experiments.py
================================================
import os
import csv
from collections import defaultdict
from glob import glob
from datetime import datetime
from multiprocessing import Manager, freeze_support, Process
import numpy as np
import scipy.stats
from scipy.special import psi, polygamma
from sklearn.metrics import roc_auc_score
from sklearn.svm import OneClassSVM
from sklearn.model_selection import ParameterGrid
from sklearn.externals.joblib import Parallel, delayed
from keras.models import Model, Input, Sequential
from keras.layers import Dense, Dropout
from keras.utils import to_categorical
from utils import load_cifar10, load_cats_vs_dogs, load_fashion_mnist, load_cifar100
from utils import save_roc_pr_curve_data, get_class_name_from_index, get_channels_axis
from transformations import Transformer
from models.wide_residual_network import create_wide_residual_network
from models.encoders_decoders import conv_encoder, conv_decoder
from models import dsebm, dagmm, adgan
import keras.backend as K
RESULTS_DIR = ''
def _transformations_experiment(dataset_load_fn, dataset_name, single_class_ind, gpu_q):
gpu_to_use = gpu_q.get()
os.environ["CUDA_VISIBLE_DEVICES"] = gpu_to_use
(x_train, y_train), (x_test, y_test) = dataset_load_fn()
if dataset_name in ['cats-vs-dogs']:
transformer = Transformer(16, 16)
n, k = (16, 8)
else:
transformer = Transformer(8, 8)
n, k = (10, 4)
mdl = create_wide_residual_network(x_train.shape[1:], transformer.n_transforms, n, k)
mdl.compile('adam',
'categorical_crossentropy',
['acc'])
x_train_task = x_train[y_train.flatten() == single_class_ind]
transformations_inds = np.tile(np.arange(transformer.n_transforms), len(x_train_task))
x_train_task_transformed = transformer.transform_batch(np.repeat(x_train_task, transformer.n_transforms, axis=0),
transformations_inds)
batch_size = 128
mdl.fit(x=x_train_task_transformed, y=to_categorical(transformations_inds),
batch_size=batch_size, epochs=int(np.ceil(200/transformer.n_transforms))
)
#################################################################################################
# simplified normality score
#################################################################################################
# preds = np.zeros((len(x_test), transformer.n_transforms))
# for t in range(transformer.n_transforms):
# preds[:, t] = mdl.predict(transformer.transform_batch(x_test, [t] * len(x_test)),
# batch_size=batch_size)[:, t]
#
# labels = y_test.flatten() == single_class_ind
# scores = preds.mean(axis=-1)
#################################################################################################
def calc_approx_alpha_sum(observations):
N = len(observations)
f = np.mean(observations, axis=0)
return (N * (len(f) - 1) * (-psi(1))) / (
N * np.sum(f * np.log(f)) - np.sum(f * np.sum(np.log(observations), axis=0)))
def inv_psi(y, iters=5):
# initial estimate
cond = y >= -2.22
x = cond * (np.exp(y) + 0.5) + (1 - cond) * -1 / (y - psi(1))
for _ in range(iters):
x = x - (psi(x) - y) / polygamma(1, x)
return x
def fixed_point_dirichlet_mle(alpha_init, log_p_hat, max_iter=1000):
alpha_new = alpha_old = alpha_init
for _ in range(max_iter):
alpha_new = inv_psi(psi(np.sum(alpha_old)) + log_p_hat)
if np.sqrt(np.sum((alpha_old - alpha_new) ** 2)) < 1e-9:
break
alpha_old = alpha_new
return alpha_new
def dirichlet_normality_score(alpha, p):
return np.sum((alpha - 1) * np.log(p), axis=-1)
scores = np.zeros((len(x_test),))
observed_data = x_train_task
for t_ind in range(transformer.n_transforms):
observed_dirichlet = mdl.predict(transformer.transform_batch(observed_data, [t_ind] * len(observed_data)),
batch_size=1024)
log_p_hat_train = np.log(observed_dirichlet).mean(axis=0)
alpha_sum_approx = calc_approx_alpha_sum(observed_dirichlet)
alpha_0 = observed_dirichlet.mean(axis=0) * alpha_sum_approx
mle_alpha_t = fixed_point_dirichlet_mle(alpha_0, log_p_hat_train)
x_test_p = mdl.predict(transformer.transform_batch(x_test, [t_ind] * len(x_test)),
batch_size=1024)
scores += dirichlet_normality_score(mle_alpha_t, x_test_p)
scores /= transformer.n_transforms
labels = y_test.flatten() == single_class_ind
res_file_name = '{}_transformations_{}_{}.npz'.format(dataset_name,
get_class_name_from_index(single_class_ind, dataset_name),
datetime.now().strftime('%Y-%m-%d-%H%M'))
res_file_path = os.path.join(RESULTS_DIR, dataset_name, res_file_name)
save_roc_pr_curve_data(scores, labels, res_file_path)
mdl_weights_name = '{}_transformations_{}_{}_weights.h5'.format(dataset_name,
get_class_name_from_index(single_class_ind, dataset_name),
datetime.now().strftime('%Y-%m-%d-%H%M'))
mdl_weights_path = os.path.join(RESULTS_DIR, dataset_name, mdl_weights_name)
mdl.save_weights(mdl_weights_path)
gpu_q.put(gpu_to_use)
def _train_ocsvm_and_score(params, xtrain, test_labels, xtest):
return roc_auc_score(test_labels, OneClassSVM(**params).fit(xtrain).decision_function(xtest))
def _raw_ocsvm_experiment(dataset_load_fn, dataset_name, single_class_ind):
(x_train, y_train), (x_test, y_test) = dataset_load_fn()
x_train = x_train.reshape((len(x_train), -1))
x_test = x_test.reshape((len(x_test), -1))
x_train_task = x_train[y_train.flatten() == single_class_ind]
if dataset_name in ['cats-vs-dogs']: # OC-SVM is quadratic on the number of examples, so subsample training set
subsample_inds = np.random.choice(len(x_train_task), 5000, replace=False)
x_train_task = x_train_task[subsample_inds]
pg = ParameterGrid({'nu': np.linspace(0.1, 0.9, num=9),
'gamma': np.logspace(-7, 2, num=10, base=2)})
results = Parallel(n_jobs=6)(
delayed(_train_ocsvm_and_score)(d, x_train_task, y_test.flatten() == single_class_ind, x_test)
for d in pg)
best_params, best_auc_score = max(zip(pg, results), key=lambda t: t[-1])
best_ocsvm = OneClassSVM(**best_params).fit(x_train_task)
scores = best_ocsvm.decision_function(x_test)
labels = y_test.flatten() == single_class_ind
res_file_name = '{}_raw-oc-svm_{}_{}.npz'.format(dataset_name,
get_class_name_from_index(single_class_ind, dataset_name),
datetime.now().strftime('%Y-%m-%d-%H%M'))
res_file_path = os.path.join(RESULTS_DIR, dataset_name, res_file_name)
save_roc_pr_curve_data(scores, labels, res_file_path)
def _cae_ocsvm_experiment(dataset_load_fn, dataset_name, single_class_ind, gpu_q):
gpu_to_use = gpu_q.get()
os.environ["CUDA_VISIBLE_DEVICES"] = gpu_to_use
(x_train, y_train), (x_test, y_test) = dataset_load_fn()
n_channels = x_train.shape[get_channels_axis()]
input_side = x_train.shape[2] # channel side will always be at shape[2]
enc = conv_encoder(input_side, n_channels)
dec = conv_decoder(input_side, n_channels)
x_in = Input(shape=x_train.shape[1:])
x_rec = dec(enc(x_in))
cae = Model(x_in, x_rec)
cae.compile('adam', 'mse')
x_train_task = x_train[y_train.flatten() == single_class_ind]
x_test_task = x_test[y_test.flatten() == single_class_ind] # This is just for visual monitoring
cae.fit(x=x_train_task, y=x_train_task, batch_size=128, epochs=200, validation_data=(x_test_task, x_test_task))
x_train_task_rep = enc.predict(x_train_task, batch_size=128)
if dataset_name in ['cats-vs-dogs']: # OC-SVM is quadratic on the number of examples, so subsample training set
subsample_inds = np.random.choice(len(x_train_task_rep), 2500, replace=False)
x_train_task_rep = x_train_task_rep[subsample_inds]
x_test_rep = enc.predict(x_test, batch_size=128)
pg = ParameterGrid({'nu': np.linspace(0.1, 0.9, num=9),
'gamma': np.logspace(-7, 2, num=10, base=2)})
results = Parallel(n_jobs=6)(
delayed(_train_ocsvm_and_score)(d, x_train_task_rep, y_test.flatten() == single_class_ind, x_test_rep)
for d in pg)
best_params, best_auc_score = max(zip(pg, results), key=lambda t: t[-1])
print(best_params)
best_ocsvm = OneClassSVM(**best_params).fit(x_train_task_rep)
scores = best_ocsvm.decision_function(x_test_rep)
labels = y_test.flatten() == single_class_ind
res_file_name = '{}_cae-oc-svm_{}_{}.npz'.format(dataset_name,
get_class_name_from_index(single_class_ind, dataset_name),
datetime.now().strftime('%Y-%m-%d-%H%M'))
res_file_path = os.path.join(RESULTS_DIR, dataset_name, res_file_name)
save_roc_pr_curve_data(scores, labels, res_file_path)
gpu_q.put(gpu_to_use)
def _dsebm_experiment(dataset_load_fn, dataset_name, single_class_ind, gpu_q):
gpu_to_use = gpu_q.get()
os.environ["CUDA_VISIBLE_DEVICES"] = gpu_to_use
(x_train, y_train), (x_test, y_test) = dataset_load_fn()
n_channels = x_train.shape[get_channels_axis()]
input_side = x_train.shape[2] # image side will always be at shape[2]
encoder_mdl = conv_encoder(input_side, n_channels, representation_activation='relu')
energy_mdl = dsebm.create_energy_model(encoder_mdl)
reconstruction_mdl = dsebm.create_reconstruction_model(energy_mdl)
# optimization parameters
batch_size = 128
epochs = 200
reconstruction_mdl.compile('adam', 'mse')
x_train_task = x_train[y_train.flatten() == single_class_ind]
x_test_task = x_test[y_test.flatten() == single_class_ind] # This is just for visual monitoring
reconstruction_mdl.fit(x=x_train_task, y=x_train_task,
batch_size=batch_size,
epochs=epochs,
validation_data=(x_test_task, x_test_task))
scores = -energy_mdl.predict(x_test, batch_size)
labels = y_test.flatten() == single_class_ind
res_file_name = '{}_dsebm_{}_{}.npz'.format(dataset_name,
get_class_name_from_index(single_class_ind, dataset_name),
datetime.now().strftime('%Y-%m-%d-%H%M'))
res_file_path = os.path.join(RESULTS_DIR, dataset_name, res_file_name)
save_roc_pr_curve_data(scores, labels, res_file_path)
gpu_q.put(gpu_to_use)
def _dagmm_experiment(dataset_load_fn, dataset_name, single_class_ind, gpu_q):
gpu_to_use = gpu_q.get()
os.environ["CUDA_VISIBLE_DEVICES"] = gpu_to_use
(x_train, y_train), (x_test, y_test) = dataset_load_fn()
n_channels = x_train.shape[get_channels_axis()]
input_side = x_train.shape[2] # image side will always be at shape[2]
enc = conv_encoder(input_side, n_channels, representation_dim=5,
representation_activation='linear')
dec = conv_decoder(input_side, n_channels=n_channels, representation_dim=enc.output_shape[-1])
n_components = 3
estimation = Sequential([Dense(64, activation='tanh', input_dim=enc.output_shape[-1] + 2), Dropout(0.5),
Dense(10, activation='tanh'), Dropout(0.5),
Dense(n_components, activation='softmax')]
)
batch_size = 256
epochs = 200
lambda_diag = 0.0005
lambda_energy = 0.01
dagmm_mdl = dagmm.create_dagmm_model(enc, dec, estimation, lambda_diag)
dagmm_mdl.compile('adam', ['mse', lambda y_true, y_pred: lambda_energy*y_pred])
x_train_task = x_train[y_train.flatten() == single_class_ind]
x_test_task = x_test[y_test.flatten() == single_class_ind] # This is just for visual monitoring
dagmm_mdl.fit(x=x_train_task, y=[x_train_task, np.zeros((len(x_train_task), 1))], # second y is dummy
batch_size=batch_size,
epochs=epochs,
validation_data=(x_test_task, [x_test_task, np.zeros((len(x_test_task), 1))]),
# verbose=0
)
energy_mdl = Model(dagmm_mdl.input, dagmm_mdl.output[-1])
scores = -energy_mdl.predict(x_test, batch_size)
scores = scores.flatten()
if not np.all(np.isfinite(scores)):
min_finite = np.min(scores[np.isfinite(scores)])
scores[~np.isfinite(scores)] = min_finite - 1
labels = y_test.flatten() == single_class_ind
res_file_name = '{}_dagmm_{}_{}.npz'.format(dataset_name,
get_class_name_from_index(single_class_ind, dataset_name),
datetime.now().strftime('%Y-%m-%d-%H%M'))
res_file_path = os.path.join(RESULTS_DIR, dataset_name, res_file_name)
save_roc_pr_curve_data(scores, labels, res_file_path)
gpu_q.put(gpu_to_use)
def _adgan_experiment(dataset_load_fn, dataset_name, single_class_ind, gpu_q):
gpu_to_use = gpu_q.get()
os.environ["CUDA_VISIBLE_DEVICES"] = gpu_to_use
(x_train, y_train), (x_test, y_test) = dataset_load_fn()
if len(x_test) > 5000:
# subsample x_test due to runtime complexity
chosen_inds = np.random.choice(len(x_test), 5000, replace=False)
x_test = x_test[chosen_inds]
y_test = y_test[chosen_inds]
n_channels = x_train.shape[get_channels_axis()]
input_side = x_train.shape[2] # image side will always be at shape[2]
critic = conv_encoder(input_side, n_channels, representation_dim=1,
representation_activation='linear')
noise_size = 256
generator = conv_decoder(input_side, n_channels=n_channels, representation_dim=noise_size)
def prior_gen(b_size):
return np.random.normal(size=(b_size, noise_size))
batch_size = 128
epochs = 100
x_train_task = x_train[y_train.flatten() == single_class_ind]
def data_gen(b_size):
chosen_inds = np.random.choice(len(x_train_task), b_size, replace=False)
return x_train_task[chosen_inds]
adgan.train_wgan_with_grad_penalty(prior_gen, generator, data_gen, critic, batch_size, epochs, grad_pen_coef=20)
scores = adgan.scores_from_adgan_generator(x_test, prior_gen, generator)
labels = y_test.flatten() == single_class_ind
res_file_name = '{}_adgan_{}_{}.npz'.format(dataset_name,
get_class_name_from_index(single_class_ind, dataset_name),
datetime.now().strftime('%Y-%m-%d-%H%M'))
res_file_path = os.path.join(RESULTS_DIR, dataset_name, res_file_name)
save_roc_pr_curve_data(scores, labels, res_file_path)
gpu_q.put(gpu_to_use)
def run_experiments(load_dataset_fn, dataset_name, q, n_classes):
# CAE OC-SVM
processes = [Process(target=_cae_ocsvm_experiment,
args=(load_dataset_fn, dataset_name, c, q)) for c in range(n_classes)]
for p in processes:
p.start()
p.join()
# Raw OC-SVM
for c in range(n_classes):
_raw_ocsvm_experiment(load_dataset_fn, dataset_name, c)
n_runs = 5
# Transformations
for _ in range(n_runs):
processes = [Process(target=_transformations_experiment,
args=(load_dataset_fn, dataset_name, c, q)) for c in range(n_classes)]
if dataset_name in ['cats-vs-dogs']: # Self-labeled set is memory consuming
for p in processes:
p.start()
p.join()
else:
for p in processes:
p.start()
for p in processes:
p.join()
# DSEBM
for _ in range(n_runs):
processes = [Process(target=_dsebm_experiment,
args=(load_dataset_fn, dataset_name, c, q)) for c in range(n_classes)]
for p in processes:
p.start()
for p in processes:
p.join()
# DAGMM
for _ in range(n_runs):
processes = [Process(target=_dagmm_experiment,
args=(load_dataset_fn, dataset_name, c, q)) for c in range(n_classes)]
for p in processes:
p.start()
for p in processes:
p.join()
# ADGAN
processes = [Process(target=_adgan_experiment,
args=(load_dataset_fn, dataset_name, c, q)) for c in range(n_classes)]
for p in processes:
p.start()
for p in processes:
p.join()
def create_auc_table(metric='roc_auc'):
file_path = glob(os.path.join(RESULTS_DIR, '*', '*.npz'))
results = defaultdict(lambda: defaultdict(lambda: defaultdict(list)))
methods = set()
for p in file_path:
_, f_name = os.path.split(p)
dataset_name, method, single_class_name = f_name.split(sep='_')[:3]
methods.add(method)
npz = np.load(p)
roc_auc = npz[metric]
results[dataset_name][single_class_name][method].append(roc_auc)
for ds_name in results:
for sc_name in results[ds_name]:
for method_name in results[ds_name][sc_name]:
roc_aucs = results[ds_name][sc_name][method_name]
results[ds_name][sc_name][method_name] = [np.mean(roc_aucs),
0 if len(roc_aucs) == 1 else scipy.stats.sem(np.array(roc_aucs))
]
with open('results-{}.csv'.format(metric), 'w') as csvfile:
fieldnames = ['dataset', 'single class name'] + sorted(list(methods))
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for ds_name in sorted(results.keys()):
for sc_name in sorted(results[ds_name].keys()):
row_dict = {'dataset': ds_name, 'single class name': sc_name}
row_dict.update({method_name: '{:.3f} ({:.3f})'.format(*results[ds_name][sc_name][method_name])
for method_name in results[ds_name][sc_name]})
writer.writerow(row_dict)
if __name__ == '__main__':
freeze_support()
N_GPUS = 2
man = Manager()
q = man.Queue(N_GPUS)
for g in range(N_GPUS):
q.put(str(g))
experiments_list = [
(load_cifar10, 'cifar10', 10),
(load_cifar100, 'cifar100', 20),
(load_fashion_mnist, 'fashion-mnist', 10),
(load_cats_vs_dogs, 'cats-vs-dogs', 2),
]
for data_load_fn, dataset_name, n_classes in experiments_list:
run_experiments(data_load_fn, dataset_name, q, n_classes)
================================================
FILE: intuition_experiments.py
================================================
import itertools
import numpy as np
from scipy.ndimage.filters import gaussian_filter
import matplotlib.pyplot as plt
from transformations import SimpleTransformer
from utils import load_mnist
from keras.utils import to_categorical
from keras.layers import Flatten, Conv2D, Dense, BatchNormalization, MaxPool2D, Input, Lambda, average
from keras.models import Sequential, Model
import keras.backend as K
import tensorflow as tf
(x_train, y_train), (x_test, y_test) = load_mnist()
# scale to be in [0, 1]
x_train = (x_train + 1) / 2.
x_test = (x_test + 1) / 2.
single_class_ind = 3
anomaly_class_ind = 0
x_train_single = x_train[y_train == single_class_ind]
x_test_single = x_test[y_test == single_class_ind]
x_test_anomaly = x_test[y_test == anomaly_class_ind]
transformer = SimpleTransformer()
transformations_inds = np.tile(np.arange(transformer.n_transforms), len(x_train_single))
x_train_single_transformed = transformer.transform_batch(np.repeat(x_train_single, transformer.n_transforms, axis=0),
transformations_inds)
mdl = Sequential([Conv2D(32, (3, 3), padding='same', input_shape=(32, 32, 1), activation='relu'),
BatchNormalization(axis=-1),
MaxPool2D(),
Flatten(),
Dense(10, activation='relu'),
BatchNormalization(axis=-1),
Dense(transformer.n_transforms, activation='softmax')])
mdl.compile('adam',
'categorical_crossentropy',
['acc'])
batch_size = 64
mdl.fit(x=x_train_single_transformed,
y=to_categorical(transformations_inds),
batch_size=batch_size,
validation_split=0.1,
epochs=10)
single_class_preds = np.zeros((len(x_test_single), transformer.n_transforms))
for t in range(transformer.n_transforms):
single_class_preds[:, t] = mdl.predict(transformer.transform_batch(x_test_single, [t] * len(x_test_single)),
batch_size=batch_size)[:, t]
single_class_scores = single_class_preds.mean(axis=-1)
anomaly_class_preds = np.zeros((len(x_test_anomaly), transformer.n_transforms))
for t in range(transformer.n_transforms):
anomaly_class_preds[:, t] = mdl.predict(transformer.transform_batch(x_test_anomaly, [t] * len(x_test_anomaly)),
batch_size=batch_size)[:, t]
anomaly_class_scores = anomaly_class_preds.mean(axis=-1)
def affine(x, is_flip, k_rotate):
return tf.image.rot90(tf.image.flip_left_right(x) if is_flip else x,
k=k_rotate)
x_in = Input(batch_shape=mdl.input_shape)
transformations_sm_responses = [mdl(Lambda(affine, arguments={'is_flip': is_flip, 'k_rotate': k_rotate})(x_in))
for is_flip, k_rotate in itertools.product((False, True), range(4))]
out = average([Lambda(lambda sm_res: sm_res[:, j:j+1])(tens) for j, tens in enumerate(transformations_sm_responses)])
inference_mdl = Model(x_in, out)
grads_tensor = K.gradients([inference_mdl.output], [inference_mdl.input])[0]
grads_fn = K.function([inference_mdl.input], [grads_tensor])
def optimize_anomaly_images():
for im_ind in range(len(x_test_anomaly)):
im = x_test_anomaly[im_ind:im_ind+1].copy()
eta = 5
for _ in range(200):
grads = grads_fn([im])[0]
grads[np.abs(grads * im) < np.percentile(np.abs(grads * im), 80)] = 0
im_diff = grads * eta
im_diff *= 0.99
im += im_diff
im = gaussian_filter(im, 0.28)
im = np.clip(im, 0, 1)
im[im < np.percentile(np.abs(im), 80)] = 0
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(4, 2))
ax1.imshow(x_test_anomaly[im_ind].squeeze(), cmap='Greys_r')
ax1.grid(False)
ax1.tick_params(which='both', bottom=False, top=False, left=False, right=False,
labelbottom=False, labeltop=False, labelleft=False, labelright=False)
ax2.imshow(im.squeeze(), cmap='Greys_r')
ax2.grid(False)
ax2.tick_params(which='both', bottom=False, top=False, left=False, right=False,
labelbottom=False, labeltop=False, labelleft=False, labelright=False)
fig.savefig('0_{}.png'.format(im_ind))
plt.close()
print('0_3_{} done'.format(im_ind))
def optimize_normal_images():
for im_ind in range(len(x_train_single)):
im = x_train_single[im_ind:im_ind+1].copy()
eta = 5
for _ in range(200):
grads = grads_fn([im])[0]
grads[np.abs(grads * im) < np.percentile(np.abs(grads * im), 80)] = 0
im_diff = grads * eta
im_diff *= 0.99
im += im_diff
im = gaussian_filter(im, 0.28)
im = np.clip(im, 0, 1)
im[im < np.percentile(np.abs(im), 80)] = 0
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(4, 2))
ax1.imshow(x_train_single[im_ind].squeeze(), cmap='Greys_r')
ax1.grid(False)
ax1.tick_params(which='both', bottom=False, top=False, left=False, right=False,
labelbottom=False, labeltop=False, labelleft=False, labelright=False)
ax2.imshow(im.squeeze(), cmap='Greys_r')
ax2.grid(False)
ax2.tick_params(which='both', bottom=False, top=False, left=False, right=False,
labelbottom=False, labeltop=False, labelleft=False, labelright=False)
fig.savefig('3_{}.png'.format(im_ind))
plt.close()
print('3_3_{} done'.format(im_ind))
optimize_normal_images()
optimize_anomaly_images()
================================================
FILE: models/__init__.py
================================================
================================================
FILE: models/adgan.py
================================================
import numpy as np
from keras.optimizers import Adam
from keras.models import Model
from keras.layers.merge import subtract
from keras.utils.generic_utils import Progbar
from keras.engine.topology import Input, Layer
from keras.callbacks import CallbackList
import keras.backend as K
class GradPenLayer(Layer):
def call(self, inputs, **kwargs):
interp_in, critic_interp_score_in = inputs[0], inputs[1]
interp_critic_grad = K.batch_flatten(K.gradients(critic_interp_score_in, [interp_in])[0])
interp_critic_grad_norm = K.sqrt(K.sum(K.square(interp_critic_grad), axis=-1, keepdims=True))
return K.square(interp_critic_grad_norm - 1.) # two sided regularisation
# return K.square(K.relu(interp_critic_grad_norm - 1.)) # one sided regularisation
def compute_output_shape(self, input_shape):
return input_shape[0], 1
def train_wgan_with_grad_penalty(prior_gen, generator, data_gen, critic, batch_size, epochs,
batches_per_epoch=100, optimizer=Adam(lr=1e-4, beta_1=0, beta_2=0.9),
grad_pen_coef=10., critic_gen_train_ratio=2, callbacks=None):
# build model to train the critic
data_shape = critic.input_shape[1:]
real_critic_input = Input(shape=data_shape, name='real_in')
fake_critic_input = Input(shape=data_shape, name='fake_in')
interp_critic_input = Input(shape=data_shape, name='interp_in')
real_critic_score = critic(real_critic_input)
fake_critic_score = critic(fake_critic_input)
interp_critic_score = critic(interp_critic_input)
critic_loss = subtract([fake_critic_score, real_critic_score])
gradient_penalty = GradPenLayer()([interp_critic_input, interp_critic_score])
critic_train_mdl = Model([real_critic_input, fake_critic_input, interp_critic_input],
[critic_loss, gradient_penalty])
critic_train_mdl.compile(optimizer=optimizer,
loss=lambda y_true, y_pred: y_pred,
loss_weights=[1., grad_pen_coef])
# build model to train generator
prior_input = Input(shape=generator.input_shape[1:], name='prior_in')
critic.trainable = False
critic_on_generator_score = critic(generator(prior_input))
generator_train_mdl = Model(prior_input, critic_on_generator_score)
generator_train_mdl.compile(optimizer=optimizer, loss=lambda y_true, y_pred: -y_pred)
# init callbacks
callbacks = callbacks or []
callbacks = CallbackList(callbacks)
callbacks.set_model({'generator': generator, 'critic': critic})
callbacks.set_params({
'batch_size': batch_size,
'epochs': epochs,
'steps': batches_per_epoch,
'samples': batches_per_epoch * batch_size,
'prior_gen': prior_gen,
'data_gen': data_gen,
})
# train
print('Training on {} samples for {} epochs'.format(batches_per_epoch * batch_size, epochs))
callbacks.on_train_begin()
for e in range(epochs):
print('Epoch {}/{}'.format(e + 1, epochs))
callbacks.on_epoch_begin(e)
progbar = Progbar(target=batches_per_epoch*batch_size)
dummy_y = np.array([None]*batch_size)
for b in range(batches_per_epoch):
callbacks.on_batch_begin(b)
batch_losses = np.zeros(shape=3)
for critic_upd in range(critic_gen_train_ratio):
real_batch = data_gen(batch_size)
fake_batch = generator.predict(prior_gen(batch_size))
weights = np.random.uniform(size=batch_size)
weights = weights.reshape((-1,) + (1,)*(len(real_batch.shape)-1))
interp_batch = weights * real_batch + (1. - weights) * fake_batch
x_batch = {'real_in': real_batch, 'fake_in': fake_batch, 'interp_in': interp_batch}
cur_losses = np.array(critic_train_mdl.train_on_batch(x=x_batch, y=[dummy_y, dummy_y]))
batch_losses += cur_losses
generator_train_mdl.train_on_batch(x=prior_gen(batch_size), y=dummy_y)
losses_names = ('total_loss', 'critic_loss', 'gradient_pen')
progbar.add(batch_size, zip(losses_names, batch_losses))
callbacks.on_batch_end(b)
progbar.update(batches_per_epoch*batch_size)
callbacks.on_epoch_end(e)
callbacks.on_train_end()
def scores_from_adgan_generator(x_test, prior_gen, generator, n_seeds=8, k=5, z_lr=0.25, gen_lr=5e-5):
generator.trainable = True
initial_weights = generator.get_weights()
gen_opt = Adam(lr=gen_lr, beta_1=0.5)
z_opt = Adam(lr=z_lr, beta_1=0.5)
x_ph = K.placeholder((1,)+x_test.shape[1:])
z = K.variable(prior_gen(1))
rec_loss = K.mean(K.square(x_ph - generator(z)))
z_train_fn = K.function([x_ph], [rec_loss], updates=z_opt.get_updates(rec_loss, [z]))
g_train_fn = K.function([x_ph, K.learning_phase()], [rec_loss],
updates=gen_opt.get_updates(rec_loss, generator.trainable_weights))
gen_opt_initial_params = gen_opt.get_weights()
z_opt_initial_params = z_opt.get_weights()
scores = []
for x in x_test:
x = np.expand_dims(x, axis=0)
losses = []
for j in range(n_seeds):
K.set_value(z, prior_gen(1))
generator.set_weights(initial_weights)
gen_opt.set_weights(gen_opt_initial_params)
z_opt.set_weights(z_opt_initial_params)
for _ in range(k):
z_train_fn([x])
g_train_fn([x, 1])
loss = z_train_fn([x])[0]
losses.append(loss)
score = -np.mean(losses)
scores.append(score)
return np.array(scores)
================================================
FILE: models/dagmm.py
================================================
import numpy as np
from keras.models import Input, Model
from keras.layers import concatenate, Lambda, Layer, add
import keras.backend as K
import tensorflow as tf
class GaussianMixtureComponent(Layer):
def __init__(self, lambd_diag=0.005, **kwargs):
self.lambd_diag = lambd_diag
super().__init__(**kwargs)
def build(self, input_shapes):
z_shape, _ = input_shapes
self.phi = self.add_weight(name='phi',
shape=(1,),
initializer='ones',
trainable=False)
self.mu = self.add_weight(name='mu',
shape=(1, z_shape[1]),
initializer='uniform',
trainable=False)
self.sigma = self.add_weight(name='sig',
shape=(z_shape[1], z_shape[1]),
initializer='identity',
trainable=False)
super().build(input_shapes)
def call(self, inputs, training=None):
z, gamma_k = inputs
gamma_k_sum = K.sum(gamma_k)
est_phi = K.mean(gamma_k, axis=0)
est_mu = K.dot(K.transpose(gamma_k), z) / gamma_k_sum
est_sigma = K.dot(K.transpose(z - est_mu),
gamma_k * (z - est_mu)) / gamma_k_sum
est_sigma = est_sigma + (K.random_normal(shape=(K.int_shape(z)[1], 1), mean=1e-3, stddev=1e-4) * K.eye(K.int_shape(z)[1]))
self.add_update(K.update(self.phi, est_phi), inputs)
self.add_update(K.update(self.mu, est_mu), inputs)
self.add_update(K.update(self.sigma, est_sigma), inputs)
est_sigma_diag_inv = K.eye(K.int_shape(self.sigma)[0]) / est_sigma
self.add_loss(self.lambd_diag * K.sum(est_sigma_diag_inv), inputs)
phi = K.in_train_phase(est_phi, self.phi, training)
mu = K.in_train_phase(est_mu, self.mu, training)
sigma = K.in_train_phase(est_sigma, self.sigma, training)
return GaussianMixtureComponent._calc_component_density(z, phi, mu, sigma)
@staticmethod
def _calc_component_density(z, phi, mu, sigma):
sig_inv = tf.matrix_inverse(sigma)
sig_sqrt_det = K.sqrt(tf.matrix_determinant(2 * np.pi * sigma) + K.epsilon())
density = phi * (K.exp(-0.5 * K.sum(K.dot(z - mu, sig_inv) * (z - mu),
axis=-1,
keepdims=True)) / sig_sqrt_det) + K.epsilon()
return density
def compute_output_shape(self, input_shapes):
z_shape, gamma_k_shape = input_shapes
return z_shape[0], 1
def create_dagmm_model(encoder, decoder, estimation_encoder, lambd_diag=0.005):
x_in = Input(batch_shape=encoder.input_shape)
zc = encoder(x_in)
decoder.name = 'reconstruction'
x_rec = decoder(zc)
euclid_dist = Lambda(lambda args: K.sqrt(K.sum(K.batch_flatten(K.square(args[0] - args[1])),
axis=-1, keepdims=True) /
K.sum(K.batch_flatten(K.square(args[0])),
axis=-1, keepdims=True)),
output_shape=(1,))([x_in, x_rec])
cos_sim = Lambda(lambda args: K.batch_dot(K.l2_normalize(K.batch_flatten(args[0]), axis=-1),
K.l2_normalize(K.batch_flatten(args[1]), axis=-1),
axes=-1),
output_shape=(1,))([x_in, x_rec])
zr = concatenate([euclid_dist, cos_sim])
z = concatenate([zc, zr])
gamma = estimation_encoder(z)
gamma_ks = [Lambda(lambda g: g[:, k:k + 1], output_shape=(1,))(gamma)
for k in range(estimation_encoder.output_shape[-1])]
components = [GaussianMixtureComponent(lambd_diag)([z, gamma_k])
for gamma_k in gamma_ks]
density = add(components) if len(components) > 1 else components[0]
energy = Lambda(lambda dens: -K.log(dens), name='energy')(density)
dagmm = Model(x_in, [x_rec, energy])
return dagmm
================================================
FILE: models/dsebm.py
================================================
from keras.layers import *
from keras.models import Model
import keras.backend as K
class Prior(Layer):
def __init__(self,
bias_initializer='zeros',
bias_regularizer=None,
bias_constraint=None,
**kwargs):
if 'input_shape' not in kwargs and 'input_dim' in kwargs:
kwargs['input_shape'] = (kwargs.pop('input_dim'),)
super(Prior, self).__init__(**kwargs)
self.bias_initializer = initializers.get(bias_initializer)
self.bias_regularizer = regularizers.get(bias_regularizer)
self.bias_constraint = constraints.get(bias_constraint)
self.input_spec = InputSpec(min_ndim=2)
self.bias = None
def build(self, input_shape):
self.bias = self.add_weight(shape=input_shape[1:],
initializer=self.bias_initializer,
name='bias',
regularizer=self.bias_regularizer,
constraint=self.bias_constraint)
super(Prior, self).build(input_shape)
def compute_output_shape(self, input_shape):
return input_shape[0], 1
def call(self, x, **kwargs):
return K.sum(K.batch_flatten(K.square(K.bias_add(x, -self.bias))), axis=-1, keepdims=True)
def create_energy_model(encoder_mdl):
x_in = Input(batch_shape=encoder_mdl.input_shape)
encoded = encoder_mdl(x_in)
prior = Prior()(x_in)
energy = Lambda(lambda args: 0.5*args[0] - K.sum(K.batch_flatten(args[1]), axis=-1, keepdims=True),
output_shape=(1,))([prior, encoded])
return Model(x_in, energy)
def create_reconstruction_model(energy_mdl):
x_in = Input(batch_shape=energy_mdl.input_shape)
x = GaussianNoise(stddev=.5)(x_in) # only active in training
energy = energy_mdl(x)
rec = Lambda(lambda args: args[1] - K.gradients(args[0], args[1]),
output_shape=energy_mdl.input_shape[1:])([energy, x])
return Model(x_in, rec)
================================================
FILE: models/encoders_decoders.py
================================================
from keras.models import Model
from keras.layers import Input, Conv2D, Activation, BatchNormalization, Flatten, Dense, Conv2DTranspose, Reshape
from utils import get_channels_axis
def conv_encoder(input_side=32, n_channels=3, representation_dim=256, representation_activation='tanh',
intermediate_activation='relu'):
nf = 64
input_shape = (n_channels, input_side, input_side) if get_channels_axis() == 1 else (input_side, input_side,
n_channels)
x_in = Input(shape=input_shape)
enc = x_in
# downsample x0.5
enc = Conv2D(nf, kernel_size=(3, 3), strides=(2, 2), padding='same')(enc)
enc = BatchNormalization(axis=get_channels_axis())(enc)
enc = Activation(intermediate_activation)(enc)
# downsample x0.5
enc = Conv2D(nf * 2, kernel_size=(3, 3), strides=(2, 2), padding='same')(enc)
enc = BatchNormalization(axis=get_channels_axis())(enc)
enc = Activation(intermediate_activation)(enc)
# downsample x0.5
enc = Conv2D(nf * 4, kernel_size=(3, 3), strides=(2, 2), padding='same')(enc)
enc = BatchNormalization(axis=get_channels_axis())(enc)
enc = Activation(intermediate_activation)(enc)
if input_side == 64:
# downsample x0.5
enc = Conv2D(nf * 8, kernel_size=(3, 3), strides=(2, 2), padding='same')(enc)
enc = BatchNormalization(axis=get_channels_axis())(enc)
enc = Activation(intermediate_activation)(enc)
enc = Flatten()(enc)
rep = Dense(representation_dim, activation=representation_activation)(enc)
return Model(x_in, rep)
def conv_decoder(output_side=32, n_channels=3, representation_dim=256, activation='relu'):
nf = 64
rep_in = Input(shape=(representation_dim,))
g = Dense(nf * 4 * 4 * 4)(rep_in)
g = BatchNormalization(axis=-1)(g)
g = Activation(activation)(g)
conv_shape = (nf * 4, 4, 4) if get_channels_axis() == 1 else (4, 4, nf * 4)
g = Reshape(conv_shape)(g)
# upsample x2
g = Conv2DTranspose(nf * 2, kernel_size=(3, 3), strides=(2, 2), padding='same')(g)
g = BatchNormalization(axis=get_channels_axis())(g)
g = Activation(activation)(g)
# upsample x2
g = Conv2DTranspose(nf, kernel_size=(3, 3), strides=(2, 2), padding='same')(g)
g = BatchNormalization(axis=get_channels_axis())(g)
g = Activation(activation)(g)
if output_side == 64:
# upsample x2
g = Conv2DTranspose(nf, kernel_size=(3, 3), strides=(2, 2), padding='same')(g)
g = BatchNormalization(axis=get_channels_axis())(g)
g = Activation(activation)(g)
# upsample x2
g = Conv2DTranspose(n_channels, kernel_size=(3, 3), strides=(2, 2), padding='same')(g)
g = Activation('tanh')(g)
return Model(rep_in, g)
================================================
FILE: models/wide_residual_network.py
================================================
from keras.models import Model
from keras.layers import *
from keras.regularizers import l2
from keras.initializers import _compute_fans
from keras.optimizers import SGD
from keras import backend as K
WEIGHT_DECAY = 0.5 * 0.0005
class SGDTorch(SGD):
@interfaces.legacy_get_updates_support
def get_updates(self, loss, params):
grads = self.get_gradients(loss, params)
self.updates = [K.update_add(self.iterations, 1)]
lr = self.lr
if self.initial_decay > 0:
lr *= (1. / (1. + self.decay * K.cast(self.iterations,
K.dtype(self.decay))))
# momentum
shapes = [K.int_shape(p) for p in params]
moments = [K.zeros(shape) for shape in shapes]
self.weights = [self.iterations] + moments
for p, g, m in zip(params, grads, moments):
v = self.momentum * m + g # velocity
self.updates.append(K.update(m, v))
if self.nesterov:
new_p = p - lr * (self.momentum * v + g)
else:
new_p = p - lr * v
# Apply constraints.
if getattr(p, 'constraint', None) is not None:
new_p = p.constraint(new_p)
self.updates.append(K.update(p, new_p))
return self.updates
def _get_channels_axis():
return -1 if K.image_data_format() == 'channels_last' else 1
def _conv_kernel_initializer(shape, dtype=None):
fan_in, fan_out = _compute_fans(shape)
stddev = np.sqrt(2. / fan_in)
return K.random_normal(shape, 0., stddev, dtype)
def _dense_kernel_initializer(shape, dtype=None):
fan_in, fan_out = _compute_fans(shape)
stddev = 1. / np.sqrt(fan_in)
return K.random_uniform(shape, -stddev, stddev, dtype)
def batch_norm():
return BatchNormalization(axis=_get_channels_axis(), momentum=0.9, epsilon=1e-5,
beta_regularizer=l2(WEIGHT_DECAY), gamma_regularizer=l2(WEIGHT_DECAY))
def conv2d(output_channels, kernel_size, strides=1):
return Convolution2D(output_channels, kernel_size, strides=strides, padding='same', use_bias=False,
kernel_initializer=_conv_kernel_initializer, kernel_regularizer=l2(WEIGHT_DECAY))
def dense(output_units):
return Dense(output_units, kernel_initializer=_dense_kernel_initializer, kernel_regularizer=l2(WEIGHT_DECAY),
bias_regularizer=l2(WEIGHT_DECAY))
def _add_basic_block(x_in, out_channels, strides, dropout_rate=0.0):
is_channels_equal = K.int_shape(x_in)[_get_channels_axis()] == out_channels
bn1 = batch_norm()(x_in)
bn1 = Activation('relu')(bn1)
out = conv2d(out_channels, 3, strides)(bn1)
out = batch_norm()(out)
out = Activation('relu')(out)
out = Dropout(dropout_rate)(out)
out = conv2d(out_channels, 3, 1)(out)
shortcut = x_in if is_channels_equal else conv2d(out_channels, 1, strides)(bn1)
out = add([out, shortcut])
return out
def _add_conv_group(x_in, out_channels, n, strides, dropout_rate=0.0):
out = _add_basic_block(x_in, out_channels, strides, dropout_rate)
for _ in range(1, n):
out = _add_basic_block(out, out_channels, 1, dropout_rate)
return out
def create_wide_residual_network(input_shape, num_classes, depth, widen_factor=1, dropout_rate=0.0,
final_activation='softmax'):
n_channels = [16, 16*widen_factor, 32*widen_factor, 64*widen_factor]
assert ((depth - 4) % 6 == 0), 'depth should be 6n+4'
n = (depth - 4) // 6
inp = Input(shape=input_shape)
conv1 = conv2d(n_channels[0], 3)(inp) # one conv at the beginning (spatial size: 32x32)
conv2 = _add_conv_group(conv1, n_channels[1], n, 1, dropout_rate) # Stage 1 (spatial size: 32x32)
conv3 = _add_conv_group(conv2, n_channels[2], n, 2, dropout_rate) # Stage 2 (spatial size: 16x16)
conv4 = _add_conv_group(conv3, n_channels[3], n, 2, dropout_rate) # Stage 3 (spatial size: 8x8)
out = batch_norm()(conv4)
out = Activation('relu')(out)
out = AveragePooling2D(8)(out)
out = Flatten()(out)
out = dense(num_classes)(out)
out = Activation(final_activation)(out)
return Model(inp, out)
================================================
FILE: multiclass_experiment.py
================================================
from glob import glob
import os
import numpy as np
import matplotlib.pyplot as plt
from keras.utils import to_categorical
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import LearningRateScheduler
from keras.layers import Activation
from keras import backend as K
from keras.models import Model
from models.wide_residual_network import create_wide_residual_network, SGDTorch, dense
from utils import load_cifar10, normalize_minus1_1, save_roc_pr_curve_data
from transformations import Transformer
def load_tinyimagenet(tinyimagenet_path='./'):
images = [plt.imread(fp) for fp in glob(os.path.join(tinyimagenet_path, '*.jpg'))]
for i in range(len(images)):
if len(images[i].shape) != 3:
images[i] = np.stack([images[i], images[i], images[i]], axis=-1)
images = np.stack(images)
images = normalize_minus1_1(K.cast_to_floatx(images))
return images
def train_cifar10():
(x_train, y_train), (x_test, y_test) = load_cifar10()
idg = ImageDataGenerator(
horizontal_flip=True,
height_shift_range=4,
width_shift_range=4,
fill_mode='reflect'
)
idg.fit(x_train)
n = 16
k = 8
mdl = create_wide_residual_network(x_train.shape[1:], 10, n, k)
mdl.compile(SGDTorch(lr=.1, momentum=0.9, nesterov=True), 'categorical_crossentropy', ['acc'])
lr_cb = LearningRateScheduler(lambda e: 0.1 * (0.2 ** (e >= 160 and 3 or e >= 120 and 2 or e >= 60 and 1 or 0)))
batch_size = 128
mdl.fit_generator(
generator=idg.flow(x_train, to_categorical(y_train), batch_size=batch_size),
epochs=200,
validation_data=(idg.standardize(x_test), to_categorical(y_test)),
callbacks=[lr_cb]
)
mdl.save_weights('cifar10_WRN_{}-{}.h5'.format(n, k))
def train_cifar10_transformations():
(x_train, y_train), _ = load_cifar10()
transformer = Transformer(8, 8)
def data_gen(x, y, batch_size):
while True:
ind_permutation = np.random.permutation(len(x))
for b_start_ind in range(0, len(x), batch_size):
batch_inds = ind_permutation[b_start_ind:b_start_ind + batch_size]
x_batch = x[batch_inds]
y_batch = y[batch_inds].flatten()
if K.image_data_format() == 'channels_first':
x_batch = np.transpose(x_batch, (0, 2, 3, 1))
y_t_batch = np.random.randint(0, transformer.n_transforms, size=len(x_batch))
x_batch = transformer.transform_batch(x_batch, y_t_batch)
if K.image_data_format() == 'channels_first':
x_batch = np.transpose(x_batch, (0, 3, 1, 2))
yield (x_batch, [to_categorical(y_batch, num_classes=10), to_categorical(y_t_batch, num_classes=transformer.n_transforms)])
n = 16
k = 8
base_mdl = create_wide_residual_network(x_train.shape[1:], 10, n, k)
transformations_cls_out = Activation('softmax')(dense(transformer.n_transforms)(base_mdl.get_layer(index=-3).output))
mdl = Model(base_mdl.input, [base_mdl.output, transformations_cls_out])
mdl.compile(SGDTorch(lr=.1, momentum=0.9, nesterov=True), 'categorical_crossentropy', ['acc'])
lr_cb = LearningRateScheduler(lambda e: 0.1 * (0.2 ** (e >= 160 and 3 or e >= 120 and 2 or e >= 60 and 1 or 0)))
batch_size = 128
mdl.fit_generator(
generator=data_gen(x_train, y_train, batch_size=batch_size),
steps_per_epoch=len(x_train) // batch_size,
epochs=200,
callbacks=[lr_cb]
)
mdl.save_weights('cifar10_WRN_doublehead-transformations_{}-{}.h5'.format(n, k))
def transformation_cifar10_vs_tinyimagenet():
_, (x_test, y_test) = load_cifar10()
x_test_out = load_tinyimagenet('/home/izikgo/Imagenet_resize/Imagenet_resize/')
transformer = Transformer(8, 8)
n = 16
k = 8
base_mdl = create_wide_residual_network(x_test.shape[1:], 10, n, k)
transformations_cls_out = Activation('softmax')(dense(transformer.n_transforms)(base_mdl.get_layer(index=-3).output))
mdl = Model(base_mdl.input, [base_mdl.output, transformations_cls_out])
mdl.load_weights('cifar10_WRN_doublehead-transformations_{}-{}.h5'.format(n, k))
scores_mdl = Model(mdl.input, mdl.output[1])
x_test_all = np.concatenate((x_test, x_test_out))
preds = np.zeros((len(x_test_all), transformer.n_transforms))
for t in range(transformer.n_transforms):
preds[:, t] = scores_mdl.predict(transformer.transform_batch(x_test_all, [t] * len(x_test_all)),
batch_size=128)[:, t]
labels = np.concatenate((np.ones(len(x_test)), np.zeros(len(x_test_out))))
scores = preds.mean(axis=-1)
save_roc_pr_curve_data(scores, labels, 'cifar10-vs-tinyimagenet_transformations.npz')
if __name__ == '__main__':
train_cifar10_transformations()
transformation_cifar10_vs_tinyimagenet()
================================================
FILE: transformations.py
================================================
import abc
import itertools
import numpy as np
from keras.preprocessing.image import apply_affine_transform
class AffineTransformation(object):
def __init__(self, flip, tx, ty, k_90_rotate):
self.flip = flip
self.tx = tx
self.ty = ty
self.k_90_rotate = k_90_rotate
def __call__(self, x):
res_x = x
if self.flip:
res_x = np.fliplr(res_x)
if self.tx != 0 or self.ty != 0:
res_x = apply_affine_transform(res_x, tx=self.tx, ty=self.ty, channel_axis=2, fill_mode='reflect')
if self.k_90_rotate != 0:
res_x = np.rot90(res_x, self.k_90_rotate)
return res_x
class AbstractTransformer(abc.ABC):
def __init__(self):
self._transformation_list = None
self._create_transformation_list()
@property
def n_transforms(self):
return len(self._transformation_list)
@abc.abstractmethod
def _create_transformation_list(self):
return
def transform_batch(self, x_batch, t_inds):
assert len(x_batch) == len(t_inds)
transformed_batch = x_batch.copy()
for i, t_ind in enumerate(t_inds):
transformed_batch[i] = self._transformation_list[t_ind](transformed_batch[i])
return transformed_batch
class Transformer(AbstractTransformer):
def __init__(self, translation_x=8, translation_y=8):
self.max_tx = translation_x
self.max_ty = translation_y
super().__init__()
def _create_transformation_list(self):
transformation_list = []
for is_flip, tx, ty, k_rotate in itertools.product((False, True),
(0, -self.max_tx, self.max_tx),
(0, -self.max_ty, self.max_ty),
range(4)):
transformation = AffineTransformation(is_flip, tx, ty, k_rotate)
transformation_list.append(transformation)
self._transformation_list = transformation_list
class SimpleTransformer(AbstractTransformer):
def _create_transformation_list(self):
transformation_list = []
for is_flip, k_rotate in itertools.product((False, True),
range(4)):
transformation = AffineTransformation(is_flip, 0, 0, k_rotate)
transformation_list.append(transformation)
self._transformation_list = transformation_list
================================================
FILE: utils.py
================================================
from glob import glob
import os
import numpy as np
import cv2
from sklearn.metrics import roc_curve, precision_recall_curve, auc
from keras.datasets import mnist, fashion_mnist, cifar100, cifar10
from keras.backend import cast_to_floatx
def resize_and_crop_image(input_file, output_side_length, greyscale=False):
img = cv2.imread(input_file)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB if not greyscale else cv2.COLOR_BGR2GRAY)
height, width = img.shape[:2]
new_height = output_side_length
new_width = output_side_length
if height > width:
new_height = int(output_side_length * height / width)
else:
new_width = int(output_side_length * width / height)
resized_img = cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_AREA)
height_offset = (new_height - output_side_length) // 2
width_offset = (new_width - output_side_length) // 2
cropped_img = resized_img[height_offset:height_offset + output_side_length,
width_offset:width_offset + output_side_length]
assert cropped_img.shape[:2] == (output_side_length, output_side_length)
return cropped_img
def normalize_minus1_1(data):
return 2*(data/255.) - 1
def get_channels_axis():
import keras
idf = keras.backend.image_data_format()
if idf == 'channels_first':
return 1
assert idf == 'channels_last'
return 3
def load_fashion_mnist():
(X_train, y_train), (X_test, y_test) = fashion_mnist.load_data()
X_train = normalize_minus1_1(cast_to_floatx(np.pad(X_train, ((0, 0), (2, 2), (2, 2)), 'constant')))
X_train = np.expand_dims(X_train, axis=get_channels_axis())
X_test = normalize_minus1_1(cast_to_floatx(np.pad(X_test, ((0, 0), (2, 2), (2, 2)), 'constant')))
X_test = np.expand_dims(X_test, axis=get_channels_axis())
return (X_train, y_train), (X_test, y_test)
def load_mnist():
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = normalize_minus1_1(cast_to_floatx(np.pad(X_train, ((0, 0), (2, 2), (2, 2)), 'constant')))
X_train = np.expand_dims(X_train, axis=get_channels_axis())
X_test = normalize_minus1_1(cast_to_floatx(np.pad(X_test, ((0, 0), (2, 2), (2, 2)), 'constant')))
X_test = np.expand_dims(X_test, axis=get_channels_axis())
return (X_train, y_train), (X_test, y_test)
def load_cifar10():
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
X_train = normalize_minus1_1(cast_to_floatx(X_train))
X_test = normalize_minus1_1(cast_to_floatx(X_test))
return (X_train, y_train), (X_test, y_test)
def load_cifar100(label_mode='coarse'):
(X_train, y_train), (X_test, y_test) = cifar100.load_data(label_mode=label_mode)
X_train = normalize_minus1_1(cast_to_floatx(X_train))
X_test = normalize_minus1_1(cast_to_floatx(X_test))
return (X_train, y_train), (X_test, y_test)
def save_roc_pr_curve_data(scores, labels, file_path):
scores = scores.flatten()
labels = labels.flatten()
scores_pos = scores[labels == 1]
scores_neg = scores[labels != 1]
truth = np.concatenate((np.zeros_like(scores_neg), np.ones_like(scores_pos)))
preds = np.concatenate((scores_neg, scores_pos))
fpr, tpr, roc_thresholds = roc_curve(truth, preds)
roc_auc = auc(fpr, tpr)
# pr curve where "normal" is the positive class
precision_norm, recall_norm, pr_thresholds_norm = precision_recall_curve(truth, preds)
pr_auc_norm = auc(recall_norm, precision_norm)
# pr curve where "anomaly" is the positive class
precision_anom, recall_anom, pr_thresholds_anom = precision_recall_curve(truth, -preds, pos_label=0)
pr_auc_anom = auc(recall_anom, precision_anom)
np.savez_compressed(file_path,
preds=preds, truth=truth,
fpr=fpr, tpr=tpr, roc_thresholds=roc_thresholds, roc_auc=roc_auc,
precision_norm=precision_norm, recall_norm=recall_norm,
pr_thresholds_norm=pr_thresholds_norm, pr_auc_norm=pr_auc_norm,
precision_anom=precision_anom, recall_anom=recall_anom,
pr_thresholds_anom=pr_thresholds_anom, pr_auc_anom=pr_auc_anom)
def create_cats_vs_dogs_npz(cats_vs_dogs_path='./'):
labels = ['cat', 'dog']
label_to_y_dict = {l: i for i, l in enumerate(labels)}
def _load_from_dir(dir_name):
glob_path = os.path.join(cats_vs_dogs_path, dir_name, '*.*.jpg')
imgs_paths = glob(glob_path)
images = [resize_and_crop_image(p, 64) for p in imgs_paths]
x = np.stack(images)
y = [label_to_y_dict[os.path.split(p)[-1][:3]] for p in imgs_paths]
y = np.array(y)
return x, y
x_train, y_train = _load_from_dir('train')
x_test, y_test = _load_from_dir('test')
np.savez_compressed(os.path.join(cats_vs_dogs_path, 'cats_vs_dogs.npz'),
x_train=x_train, y_train=y_train,
x_test=x_test, y_test=y_test)
def load_cats_vs_dogs(cats_vs_dogs_path='./'):
npz_file = np.load(os.path.join(cats_vs_dogs_path, 'cats_vs_dogs.npz'))
x_train = normalize_minus1_1(cast_to_floatx(npz_file['x_train']))
y_train = npz_file['y_train']
x_test = normalize_minus1_1(cast_to_floatx(npz_file['x_test']))
y_test = npz_file['y_test']
return (x_train, y_train), (x_test, y_test)
def get_class_name_from_index(index, dataset_name):
ind_to_name = {
'cifar10': ('airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'),
'cifar100': ('aquatic mammals', 'fish', 'flowers', 'food containers', 'fruit and vegetables',
'household electrical devices', 'household furniture', 'insects', 'large carnivores',
'large man-made outdoor things', 'large natural outdoor scenes', 'large omnivores and herbivores',
'medium-sized mammals', 'non-insect invertebrates', 'people', 'reptiles', 'small mammals', 'trees',
'vehicles 1', 'vehicles 2'),
'fashion-mnist': ('t-shirt', 'trouser', 'pullover', 'dress', 'coat', 'sandal', 'shirt', 'sneaker', 'bag',
'ankle-boot'),
'cats-vs-dogs': ('cat', 'dog'),
}
return ind_to_name[dataset_name][index]
gitextract__9qwn17c/ ├── .gitignore ├── LICENSE ├── README.md ├── experiments.py ├── intuition_experiments.py ├── models/ │ ├── __init__.py │ ├── adgan.py │ ├── dagmm.py │ ├── dsebm.py │ ├── encoders_decoders.py │ └── wide_residual_network.py ├── multiclass_experiment.py ├── transformations.py └── utils.py
SYMBOL INDEX (72 symbols across 10 files)
FILE: experiments.py
function _transformations_experiment (line 28) | def _transformations_experiment(dataset_load_fn, dataset_name, single_cl...
function _train_ocsvm_and_score (line 129) | def _train_ocsvm_and_score(params, xtrain, test_labels, xtest):
function _raw_ocsvm_experiment (line 133) | def _raw_ocsvm_experiment(dataset_load_fn, dataset_name, single_class_ind):
function _cae_ocsvm_experiment (line 163) | def _cae_ocsvm_experiment(dataset_load_fn, dataset_name, single_class_in...
function _dsebm_experiment (line 210) | def _dsebm_experiment(dataset_load_fn, dataset_name, single_class_ind, g...
function _dagmm_experiment (line 244) | def _dagmm_experiment(dataset_load_fn, dataset_name, single_class_ind, g...
function _adgan_experiment (line 294) | def _adgan_experiment(dataset_load_fn, dataset_name, single_class_ind, g...
function run_experiments (line 337) | def run_experiments(load_dataset_fn, dataset_name, q, n_classes):
function create_auc_table (line 393) | def create_auc_table(metric='roc_auc'):
FILE: intuition_experiments.py
function affine (line 64) | def affine(x, is_flip, k_rotate):
function optimize_anomaly_images (line 81) | def optimize_anomaly_images():
function optimize_normal_images (line 112) | def optimize_normal_images():
FILE: models/adgan.py
class GradPenLayer (line 11) | class GradPenLayer(Layer):
method call (line 12) | def call(self, inputs, **kwargs):
method compute_output_shape (line 19) | def compute_output_shape(self, input_shape):
function train_wgan_with_grad_penalty (line 23) | def train_wgan_with_grad_penalty(prior_gen, generator, data_gen, critic,...
function scores_from_adgan_generator (line 100) | def scores_from_adgan_generator(x_test, prior_gen, generator, n_seeds=8,...
FILE: models/dagmm.py
class GaussianMixtureComponent (line 8) | class GaussianMixtureComponent(Layer):
method __init__ (line 9) | def __init__(self, lambd_diag=0.005, **kwargs):
method build (line 13) | def build(self, input_shapes):
method call (line 29) | def call(self, inputs, training=None):
method _calc_component_density (line 53) | def _calc_component_density(z, phi, mu, sigma):
method compute_output_shape (line 62) | def compute_output_shape(self, input_shapes):
function create_dagmm_model (line 67) | def create_dagmm_model(encoder, decoder, estimation_encoder, lambd_diag=...
FILE: models/dsebm.py
class Prior (line 6) | class Prior(Layer):
method __init__ (line 7) | def __init__(self,
method build (line 21) | def build(self, input_shape):
method compute_output_shape (line 29) | def compute_output_shape(self, input_shape):
method call (line 32) | def call(self, x, **kwargs):
function create_energy_model (line 36) | def create_energy_model(encoder_mdl):
function create_reconstruction_model (line 46) | def create_reconstruction_model(energy_mdl):
FILE: models/encoders_decoders.py
function conv_encoder (line 6) | def conv_encoder(input_side=32, n_channels=3, representation_dim=256, re...
function conv_decoder (line 42) | def conv_decoder(output_side=32, n_channels=3, representation_dim=256, a...
FILE: models/wide_residual_network.py
class SGDTorch (line 12) | class SGDTorch(SGD):
method get_updates (line 14) | def get_updates(self, loss, params):
function _get_channels_axis (line 43) | def _get_channels_axis():
function _conv_kernel_initializer (line 47) | def _conv_kernel_initializer(shape, dtype=None):
function _dense_kernel_initializer (line 53) | def _dense_kernel_initializer(shape, dtype=None):
function batch_norm (line 59) | def batch_norm():
function conv2d (line 64) | def conv2d(output_channels, kernel_size, strides=1):
function dense (line 69) | def dense(output_units):
function _add_basic_block (line 74) | def _add_basic_block(x_in, out_channels, strides, dropout_rate=0.0):
function _add_conv_group (line 89) | def _add_conv_group(x_in, out_channels, n, strides, dropout_rate=0.0):
function create_wide_residual_network (line 96) | def create_wide_residual_network(input_shape, num_classes, depth, widen_...
FILE: multiclass_experiment.py
function load_tinyimagenet (line 16) | def load_tinyimagenet(tinyimagenet_path='./'):
function train_cifar10 (line 28) | def train_cifar10():
function train_cifar10_transformations (line 57) | def train_cifar10_transformations():
function transformation_cifar10_vs_tinyimagenet (line 104) | def transformation_cifar10_vs_tinyimagenet():
FILE: transformations.py
class AffineTransformation (line 8) | class AffineTransformation(object):
method __init__ (line 9) | def __init__(self, flip, tx, ty, k_90_rotate):
method __call__ (line 15) | def __call__(self, x):
class AbstractTransformer (line 27) | class AbstractTransformer(abc.ABC):
method __init__ (line 28) | def __init__(self):
method n_transforms (line 33) | def n_transforms(self):
method _create_transformation_list (line 37) | def _create_transformation_list(self):
method transform_batch (line 40) | def transform_batch(self, x_batch, t_inds):
class Transformer (line 49) | class Transformer(AbstractTransformer):
method __init__ (line 50) | def __init__(self, translation_x=8, translation_y=8):
method _create_transformation_list (line 55) | def _create_transformation_list(self):
class SimpleTransformer (line 67) | class SimpleTransformer(AbstractTransformer):
method _create_transformation_list (line 68) | def _create_transformation_list(self):
FILE: utils.py
function resize_and_crop_image (line 10) | def resize_and_crop_image(input_file, output_side_length, greyscale=False):
function normalize_minus1_1 (line 29) | def normalize_minus1_1(data):
function get_channels_axis (line 33) | def get_channels_axis():
function load_fashion_mnist (line 42) | def load_fashion_mnist():
function load_mnist (line 51) | def load_mnist():
function load_cifar10 (line 60) | def load_cifar10():
function load_cifar100 (line 67) | def load_cifar100(label_mode='coarse'):
function save_roc_pr_curve_data (line 74) | def save_roc_pr_curve_data(scores, labels, file_path):
function create_cats_vs_dogs_npz (line 103) | def create_cats_vs_dogs_npz(cats_vs_dogs_path='./'):
function load_cats_vs_dogs (line 124) | def load_cats_vs_dogs(cats_vs_dogs_path='./'):
function get_class_name_from_index (line 134) | def get_class_name_from_index(index, dataset_name):
Condensed preview — 14 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (66K chars).
[
{
"path": ".gitignore",
"chars": 1180,
"preview": "# Custom\r\n*.png\r\n*.h5\r\n*.npz\r\n*.csv\r\n*.zip\r\n\r\n# Byte-compiled / optimized / DLL files\r\n__pycache__/\r\n*.py[cod]\r\n*$py.cla"
},
{
"path": "LICENSE",
"chars": 1063,
"preview": "MIT License\n\nCopyright (c) 2018 izikgo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof "
},
{
"path": "README.md",
"chars": 961,
"preview": "# Deep Anomaly Detection Using Geometric Transformations\nTo be presented in NIPS 2018 by Izhak Golan and Ran El-Yaniv.\n\n"
},
{
"path": "experiments.py",
"chars": 19617,
"preview": "import os\r\nimport csv\r\nfrom collections import defaultdict\r\nfrom glob import glob\r\nfrom datetime import datetime\r\nfrom m"
},
{
"path": "intuition_experiments.py",
"chars": 5779,
"preview": "import itertools\r\nimport numpy as np\r\nfrom scipy.ndimage.filters import gaussian_filter\r\nimport matplotlib.pyplot as plt"
},
{
"path": "models/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "models/adgan.py",
"chars": 5853,
"preview": "import numpy as np\r\nfrom keras.optimizers import Adam\r\nfrom keras.models import Model\r\nfrom keras.layers.merge import su"
},
{
"path": "models/dagmm.py",
"chars": 4303,
"preview": "import numpy as np\r\nfrom keras.models import Input, Model\r\nfrom keras.layers import concatenate, Lambda, Layer, add\r\nimp"
},
{
"path": "models/dsebm.py",
"chars": 2103,
"preview": "from keras.layers import *\r\nfrom keras.models import Model\r\nimport keras.backend as K\r\n\r\n\r\nclass Prior(Layer):\r\n def "
},
{
"path": "models/encoders_decoders.py",
"chars": 2896,
"preview": "from keras.models import Model\r\nfrom keras.layers import Input, Conv2D, Activation, BatchNormalization, Flatten, Dense, "
},
{
"path": "models/wide_residual_network.py",
"chars": 4342,
"preview": "from keras.models import Model\r\nfrom keras.layers import *\r\nfrom keras.regularizers import l2\r\nfrom keras.initializers i"
},
{
"path": "multiclass_experiment.py",
"chars": 5067,
"preview": "from glob import glob\r\nimport os\r\nimport numpy as np\r\nimport matplotlib.pyplot as plt\r\nfrom keras.utils import to_catego"
},
{
"path": "transformations.py",
"chars": 2599,
"preview": "import abc\r\nimport itertools\r\nimport numpy as np\r\n\r\nfrom keras.preprocessing.image import apply_affine_transform\r\n\r\n\r\ncl"
},
{
"path": "utils.py",
"chars": 6449,
"preview": "from glob import glob\r\nimport os\r\nimport numpy as np\r\nimport cv2\r\nfrom sklearn.metrics import roc_curve, precision_recal"
}
]
About this extraction
This page contains the full source code of the izikgo/AnomalyDetectionTransformations GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 14 files (60.8 KB), approximately 15.6k tokens, and a symbol index with 72 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.