def load_tf_ae(filepath: str) -> tf.keras.Model: """ Load AE. Parameters ---------- filepath Save directory. Returns ------- Loaded AE. """ model_dir = os.path.join(filepath, 'model') if not [f for f in os.listdir(model_dir) if not f.startswith('.')]: logger.warning( 'No encoder, decoder or ae found in {}.'.format(model_dir)) return None encoder_net = tf.keras.models.load_model( os.path.join(model_dir, 'encoder_net.h5')) decoder_net = tf.keras.models.load_model( os.path.join(model_dir, 'decoder_net.h5')) ae = AE(encoder_net, decoder_net) ae.load_weights(os.path.join(model_dir, 'ae.ckpt')) return ae
def __init__(self, threshold: float = None, ae: tf.keras.Model = None, encoder_net: tf.keras.Sequential = None, decoder_net: tf.keras.Sequential = None, data_type: str = None) -> None: """ AE-based outlier detector. Parameters ---------- threshold Threshold used for outlier score to determine outliers. ae A trained tf.keras model if available. encoder_net Layers for the encoder wrapped in a tf.keras.Sequential class if no 'ae' is specified. decoder_net Layers for the decoder wrapped in a tf.keras.Sequential class if no 'ae' is specified. data_type Optionally specify the data type (tabular, image or time-series). Added to metadata. """ super().__init__() if threshold is None: logger.warning( 'No threshold level set. Need to infer threshold using `infer_threshold`.' ) self.threshold = threshold # check if model can be loaded, otherwise initialize AE model if isinstance(ae, tf.keras.Model): self.ae = ae elif isinstance(encoder_net, tf.keras.Sequential) and isinstance( decoder_net, tf.keras.Sequential): self.ae = AE(encoder_net, decoder_net) else: raise TypeError( 'No valid format detected for `ae` (tf.keras.Model) ' 'or `encoder_net`, `decoder_net` (tf.keras.Sequential).') # set metadata self.meta['detector_type'] = 'offline' self.meta['data_type'] = data_type
def __init__(self, threshold: float = None, ae: tf.keras.Model = None, model: tf.keras.Model = None, encoder_net: tf.keras.Sequential = None, decoder_net: tf.keras.Sequential = None, model_hl: List[tf.keras.Model] = None, hidden_layer_kld: dict = None, w_model_hl: list = None, temperature: float = 1., data_type: str = None) -> None: """ Autoencoder (AE) based adversarial detector. Parameters ---------- threshold Threshold used for adversarial score to determine adversarial instances. ae A trained tf.keras autoencoder model if available. model A trained tf.keras classification model. encoder_net Layers for the encoder wrapped in a tf.keras.Sequential class if no 'ae' is specified. decoder_net Layers for the decoder wrapped in a tf.keras.Sequential class if no 'ae' is specified. model_hl List with tf.keras models for the hidden layer K-L divergence computation. hidden_layer_kld Dictionary with as keys the hidden layer(s) of the model which are extracted and used during training of the AE, and as values the output dimension for the hidden layer. w_model_hl Weights assigned to the loss of each model in model_hl. temperature Temperature used for model prediction scaling. Temperature <1 sharpens the prediction probability distribution. data_type Optionally specifiy the data type (tabular, image or time-series). Added to metadata. """ super().__init__() if threshold is None: logger.warning( 'No threshold level set. Need to infer threshold using `infer_threshold`.' ) self.threshold = threshold self.model = model for layer in self.model.layers: # freeze model layers layer.trainable = False # check if model can be loaded, otherwise initialize AE model if isinstance(ae, tf.keras.Model): self.ae = ae elif isinstance(encoder_net, tf.keras.Sequential) and isinstance( decoder_net, tf.keras.Sequential): self.ae = AE(encoder_net, decoder_net) # define AE model else: raise TypeError( 'No valid format detected for `ae` (tf.keras.Model) ' 'or `encoder_net` and `decoder_net` (tf.keras.Sequential).') # intermediate feature map outputs for KLD and loss weights self.hidden_layer_kld = hidden_layer_kld if isinstance(model_hl, list): self.model_hl = model_hl elif isinstance(hidden_layer_kld, dict): self.model_hl = [] for hidden_layer, output_dim in hidden_layer_kld.items(): self.model_hl.append( DenseHidden(self.model, hidden_layer, output_dim)) else: self.model_hl = None self.w_model_hl = w_model_hl if self.w_model_hl is None and isinstance(self.model_hl, list): self.w_model_hl = list(np.ones(len(self.model_hl))) self.temperature = temperature # set metadata self.meta['detector_type'] = 'offline' self.meta['data_type'] = data_type
input_dim = 784 latent_dim = 50 encoder_net = tf.keras.Sequential([ InputLayer(input_shape=(input_dim, )), Dense(128, activation=tf.nn.relu), Dense(latent_dim, activation=None) ]) decoder_net = tf.keras.Sequential([ InputLayer(input_shape=(latent_dim, )), Dense(128, activation=tf.nn.relu), Dense(input_dim, activation=tf.nn.sigmoid) ]) ae = AE(encoder_net, decoder_net) vae = VAE(encoder_net, decoder_net, latent_dim) tests = [ae, vae] @pytest.fixture def tf_v_ae_mnist(request): # load and preprocess MNIST data (X_train, _), (X_test, _) = tf.keras.datasets.mnist.load_data() X = X_train.reshape(60000, input_dim)[:1000] # only train on 1000 instances X = X.astype(np.float32) X /= 255 # init model, predict with untrained model, train and predict with trained model model = request.param
super(MyModel, self).__init__() self.dense = Dense(n_classes, activation='softmax') def call(self, x: np.ndarray) -> tf.Tensor: return self.dense(x) model = MyModel() encoder_net = tf.keras.Sequential( [InputLayer(input_shape=(n_features, )), Dense(latent_dim)]) decoder_net = tf.keras.Sequential( [InputLayer(input_shape=(latent_dim, )), Dense(n_features)]) AutoEncoder = AE(encoder_net, decoder_net) # model, proba, return_class, shape tests_predict = [(model, True, False, None), (model, False, True, None), (model, False, False, (n, n_classes)), (AutoEncoder, False, False, None), (AutoEncoder, True, False, None)] n_tests = len(tests_predict) @pytest.fixture def update_predict_batch(request): return tests_predict[request.param] @pytest.mark.parametrize('update_predict_batch',
def fetch_detector(filepath: str, detector_type: str, dataset: str, detector_name: str, model=None): filepath = os.path.join(filepath, detector_name) if not os.path.isdir(filepath): logger.warning('Directory {} does not exist and is now created.'.format(filepath)) os.mkdir(filepath) url = 'https://storage.googleapis.com/seldon-models/alibi-detect/' if detector_type == 'adversarial': url = os.path.join(url, 'ad', dataset, model, detector_name) elif detector_type == 'outlier': url = os.path.join(url, 'od', dataset, detector_name) # fetch and save metadata path_meta = os.path.join(url, 'meta.pickle') meta = cp.load(urlopen(path_meta)) with open(os.path.join(filepath, 'meta.pickle'), 'wb') as f: pickle.dump(meta, f) # fetch and save state dict path_state = os.path.join(url, meta['name'] + '.pickle') state_dict = cp.load(urlopen(path_state)) with open(os.path.join(filepath, meta['name'] + '.pickle'), 'wb') as f: pickle.dump(state_dict, f) # load detector url_models = os.path.join(url, 'model') model_path = os.path.join(filepath, 'model') if not os.path.isdir(model_path): os.mkdir(model_path) if meta['name'] == 'AdversarialAE': # encoder and decoder enc_path = tf.keras.utils.get_file( os.path.join(model_path, 'encoder_net.h5'), os.path.join(url_models, 'encoder_net.h5') ) dec_path = tf.keras.utils.get_file( os.path.join(model_path, 'decoder_net.h5'), os.path.join(url_models, 'decoder_net.h5') ) encoder_net = tf.keras.models.load_model(enc_path) decoder_net = tf.keras.models.load_model(dec_path) # classifier if dataset == 'cifar10' and model == 'resnet56': custom_objects = {'backend': backend} else: custom_objects = None clf_path = tf.keras.utils.get_file( os.path.join(model_path, 'model.h5'), os.path.join(url_models, 'model.h5') ) clf = tf.keras.models.load_model(clf_path, custom_objects=custom_objects) # autoencoder ae = AE(encoder_net, decoder_net) # hidden layers hidden_layer_kld = state_dict['hidden_layer_kld'] if isinstance(hidden_layer_kld, dict): model_hl = [] for i, (hidden_layer, output_dim) in enumerate(hidden_layer_kld.items()): ckpt_tmp = 'model_hl_' + str(i) + '.ckpt.index' data_0_tmp = 'model_hl_' + str(i) + '.ckpt.data-00000-of-00002' data_1_tmp = 'model_hl_' + str(i) + '.ckpt.data-00001-of-00002' ckpt = tf.keras.utils.get_file( os.path.join(model_path, ckpt_tmp), os.path.join(url_models, ckpt_tmp) ) data_0 = tf.keras.utils.get_file( # noqa os.path.join(model_path, data_0_tmp), os.path.join(url_models, data_0_tmp) ) data_1 = tf.keras.utils.get_file( # noqa os.path.join(model_path, data_1_tmp), os.path.join(url_models, data_1_tmp) ) m = DenseHidden(clf, hidden_layer, output_dim) m.load_weights(ckpt[:-6]) model_hl.append(m) else: model_hl = None # adversarial detector detector = init_ad_ae(state_dict, ae, clf, model_hl) else: raise NotImplementedError return detector