Exemplo n.º 1
0
def histogram_2d(eta, phi, weights_px, weights_py, eta_range, phi_range, nbins, bin_dtype=tf.float32):
    eta_bins = tf.histogram_fixed_width_bins(eta, eta_range, nbins=nbins, dtype=bin_dtype)
    phi_bins = tf.histogram_fixed_width_bins(phi, phi_range, nbins=nbins, dtype=bin_dtype)

    hist_px = tf.zeros((nbins, nbins), dtype=weights_px.dtype)
    hist_py = tf.zeros((nbins, nbins), dtype=weights_py.dtype)
    indices = tf.transpose(tf.stack([phi_bins, eta_bins]))

    hist_px = tf.tensor_scatter_nd_add(hist_px, indices, weights_px)
    hist_py = tf.tensor_scatter_nd_add(hist_py, indices, weights_py)
    hist_pt = tf.sqrt(hist_px**2 + hist_py**2)
    return hist_pt
Exemplo n.º 2
0
def binned_average(values, selection_values, value_range, nBins, weights=None):
    """Computes an average of values binned according to the selection_values array
    Assumes the following shapes:
        values.shape  = (?, points, features)
        selection_values.shape = (?, points)

    returns the following shape: (?, nBins, features)

    """
    outputs = []
    all_counts = []
    indices = tf.histogram_fixed_width_bins(selection_values,
                                            value_range,
                                            nbins=nBins)
    for b in range(nBins):
        mask = tf.cast(tf.equal(indices, b), tf.float32)

        if weights is not None:
            mask = mask * weights
        mean = tf.reduce_sum(tf.expand_dims(mask, -1) * values, axis=1)
        counts = tf.reduce_sum(mask, axis=1, keepdims=True)
        outputs.append(mean / counts)
        all_counts.append(counts)

    counts = tf.stack(all_counts, axis=1)
    result = tf.stack(outputs, axis=1)
    result = tf.where(tf.is_nan(result), tf.zeros_like(result), result)

    return result, counts
Exemplo n.º 3
0
def bin(img, depth=16, center_u=0., center_v=0., eps=EPS, shrink=1, cs_func=to_uv, flat=False):
    if shrink != -1 and shrink != 1:
        img = tf.image.resize(img, (img.shape[0] // shrink, img.shape[1] // shrink))
    img_uv, Iy = cs_func(img)
    bn_cnt = depth
    # vr = tf.convert_to_tensor(list(range(-bn_cnt // 2, bn_cnt // 2)), dtype=tf.float32) * 0.05
    vr_u = [(-bn_cnt // 2 * eps) + center_u, (bn_cnt // 2 * eps) + center_u]
    vr_v = [(-bn_cnt // 2 * eps) + center_v, (bn_cnt // 2 * eps) + center_v]
    # vr = tf.scan(lambda x, y: x + y, vr) - 0.4
    bins_u = tf.histogram_fixed_width_bins(img_uv[..., 0], value_range=vr_u, nbins=bn_cnt)
    bins_v = tf.histogram_fixed_width_bins(img_uv[..., 1], value_range=vr_v, nbins=bn_cnt)
    bins = tf.stack([bins_u, bins_v], axis=-1)
    if flat:
        bins = bins[..., 0] * depth + bins[..., 1]

    return bins, Iy
Exemplo n.º 4
0
def discretize_in_bins(x):
    """Discretize a vector in two bins."""
    return tf.histogram_fixed_width_bins(
        x,
        [tf.reduce_min(x), tf.reduce_max(x)],
        nbins=2,
    )
Exemplo n.º 5
0
  def _bin_confusion_matrix_by_score(
      self, pred_labels: Sequence[Sequence[bool]],
      true_labels: Sequence[Sequence[bool]],
      binning_score: Sequence[Sequence[float]]) -> Dict[str, tf.Tensor]:
    """Compute the confusion matrix, binning predictions by a specified score.

    Computes the confusion matrix over matrices of predicted and true labels.
    Each element of the resultant confusion matrix is itself a matrix of the
    same shape as the original input labels.

    In the typical use of this function in OracleCollaborativeAUC, the variables
    T and N (in the args and returns sections below) are the number of
    thresholds and the number of examples, respectively.

    Args:
      pred_labels: Boolean tensor of shape [T, N] of predicted labels.
      true_labels: Boolean tensor of shape [T, N] of true labels.
      binning_score: Boolean tensor of shape [T, N] of scores to use in
        assigning labels to bins.

    Returns:
      Dictionary of strings to entries of the confusion matrix
      ('true_positives', 'true_negatives', 'false_positives',
      'false_negatives'). Each entry is a tensor of shape [T, nbins].
    """
    correct_preds = tf.math.equal(pred_labels, true_labels)

    # Elements of the confusion matrix have shape [M, N]
    pred_true_positives = tf.math.logical_and(correct_preds, pred_labels)
    pred_true_negatives = tf.math.logical_and(correct_preds,
                                              tf.math.logical_not(pred_labels))
    pred_false_positives = tf.math.logical_and(
        tf.math.logical_not(correct_preds), pred_labels)
    pred_false_negatives = tf.math.logical_and(
        tf.math.logical_not(correct_preds), tf.math.logical_not(pred_labels))

    # Cast confusion matrix elements from bool to self.dtype.
    pred_true_positives = tf.cast(pred_true_positives, self.dtype)
    pred_true_negatives = tf.cast(pred_true_negatives, self.dtype)
    pred_false_positives = tf.cast(pred_false_positives, self.dtype)
    pred_false_negatives = tf.cast(pred_false_negatives, self.dtype)

    bin_indices = tf.histogram_fixed_width_bins(
        binning_score, tf.constant([0.0, 1.0], self.dtype), nbins=self.num_bins)

    binned_true_positives = self._map_unsorted_segment_sum(
        pred_true_positives, bin_indices)
    binned_true_negatives = self._map_unsorted_segment_sum(
        pred_true_negatives, bin_indices)
    binned_false_positives = self._map_unsorted_segment_sum(
        pred_false_positives, bin_indices)
    binned_false_negatives = self._map_unsorted_segment_sum(
        pred_false_negatives, bin_indices)

    return {
        "true_positives": binned_true_positives,
        "true_negatives": binned_true_negatives,
        "false_positives": binned_false_positives,
        "false_negatives": binned_false_negatives
    }
Exemplo n.º 6
0
    def update_state(self, labels, probabilities, **kwargs):
        """Updates this metric.

    This will flatten the labels and probabilities, and then compute the ECE
    over all predictions.

    Args:
      labels: Tensor of shape [..., ] of class labels in [0, k-1].
      probabilities: Tensor of shape [..., ], [..., 1] or [..., k] of normalized
        probabilities associated with the True class in the binary case, or with
        each of k classes in the multiclass case.
      **kwargs: Other potential keywords, which will be ignored by this method.
    """
        del kwargs  # unused
        labels = tf.convert_to_tensor(labels)
        probabilities = tf.cast(probabilities, self.dtype)

        # Flatten labels to [N, ] and probabilities to [N, 1] or [N, k].
        if tf.rank(labels) != 1:
            labels = tf.reshape(labels, [-1])
        if tf.rank(probabilities) != 2 or (tf.shape(probabilities)[0] !=
                                           tf.shape(labels)[0]):
            probabilities = tf.reshape(probabilities,
                                       [tf.shape(labels)[0], -1])
        # Extend any probabilities of shape [N, 1] to shape [N, 2].
        # NOTE: XLA does not allow for different shapes in the branches of a
        # conditional statement. Therefore, explicit indexing is used.
        given_k = tf.shape(probabilities)[-1]
        k = tf.math.maximum(2, given_k)
        probabilities = tf.cond(
            given_k < 2, lambda: tf.concat([1. - probabilities, probabilities],
                                           axis=-1)[:, -k:],
            lambda: probabilities)

        pred_labels = tf.math.argmax(probabilities, axis=-1)
        pred_probs = tf.math.reduce_max(probabilities, axis=-1)
        correct_preds = tf.math.equal(pred_labels,
                                      tf.cast(labels, pred_labels.dtype))
        correct_preds = tf.cast(correct_preds, self.dtype)

        bin_indices = tf.histogram_fixed_width_bins(pred_probs,
                                                    tf.constant([0., 1.],
                                                                self.dtype),
                                                    nbins=self.num_bins)
        batch_correct_sums = tf.math.unsorted_segment_sum(
            data=tf.cast(correct_preds, self.dtype),
            segment_ids=bin_indices,
            num_segments=self.num_bins)
        batch_prob_sums = tf.math.unsorted_segment_sum(
            data=pred_probs,
            segment_ids=bin_indices,
            num_segments=self.num_bins)
        batch_counts = tf.math.unsorted_segment_sum(
            data=tf.ones_like(bin_indices),
            segment_ids=bin_indices,
            num_segments=self.num_bins)
        batch_counts = tf.cast(batch_counts, self.dtype)
        self.correct_sums.assign_add(batch_correct_sums)
        self.prob_sums.assign_add(batch_prob_sums)
        self.counts.assign_add(batch_counts)
Exemplo n.º 7
0
    def histogram(self, x, y, nbins=100, range_h=None):

        shape = tf.shape(y)
        batch_size = shape[0]

        x = tf.reshape(x, [-1])
        y = tf.reshape(y, [-1])

        if range_h is None:
            range_h = [
                tf.reduce_min(tf.concat([x, y], axis=-1)),
                tf.reduce_max(tf.concat([x, y], axis=-1))
            ]

        # hisy_bins is a Tensor holding the indices of the binned values whose shape matches y.
        histy_bins = tf.histogram_fixed_width_bins(y,
                                                   range_h,
                                                   nbins=nbins,
                                                   dtype=tf.int32)
        # and creates a histogram_fixed_width
        H = tf.map_fn(
            lambda i: tf.histogram_fixed_width(tf.boolean_mask(
                x, tf.equal(histy_bins, i)),
                                               range_h,
                                               nbins=nbins,
                                               dtype=tf.int32),
            tf.range(nbins))

        return tf.cast(H, dtype=tf.float32)
Exemplo n.º 8
0
def __get_p_vals(data_array):
    y_pred = data_array[:-1]
    y_true = data_array[-1]

    support = [tf.reduce_min(data_array), tf.reduce_max(data_array)]
    bins = tf.histogram_fixed_width_bins(y_pred,
                                         support,
                                         nbins=nbins,
                                         dtype=tf.dtypes.int32,
                                         name=None)
    probs = tf.math.bincount(bins, minlength=nbins,
                             maxlength=nbins) / y_pred.shape[0]
    bin_y_true = tf.histogram_fixed_width_bins(y_true,
                                               support,
                                               nbins=nbins,
                                               dtype=tf.dtypes.int32,
                                               name=None)
    res = tf.cast(tf.reduce_sum(probs[probs <= probs[bin_y_true]]), tf.float32)
    return res
Exemplo n.º 9
0
def cross_hist_from_tensor(tensor, num_bins, range_):
    with tf.name_scope('cross_hist_from_tensor'):
        bins = tf.histogram_fixed_width_bins(
            tensor,
            range_,
            nbins=num_bins,
        )
        bins_2d = self_cross_sum_with_factors(bins, -2, 1, num_bins)
        returned_value = hist_from_nonnegative_ints(bins_2d, -1, num_bins**2)
        return returned_value
Exemplo n.º 10
0
    def update_state(self,
                     y_true: Sequence[float],
                     y_pred: Sequence[float],
                     confidence: Sequence[float],
                     sample_weight: Optional[Sequence[float]] = None) -> None:
        """Updates confidence and accuracy statistics.

    Args:
      y_true: The ground truth labels. Shape (batch_size, ).
      y_pred: The predicted labels. Must be integer valued predictions for label
        index rather than the predictive probability. For multi-label
        classification problems, `y_pred` is typically obtained as
        `tf.math.reduce_max(logits)`. Shape (batch_size, ).
      confidence: The confidence score where higher value indicates lower
        uncertainty. Values should be within [0, 1].
      sample_weight: Optional weighting of each example. Defaults to 1. Can be a
        Tensor whose rank is either 0, or the same rank as `y_true`, and must be
        broadcastable to `y_true`.
    """
        batch_size = tf.shape(y_true)[0]

        # Preprocess `confidence` and `sample_weight` tensors.
        confidence = tf.cast(tf.convert_to_tensor(confidence),
                             dtype=self.dtype)
        confidence = tf.reshape(confidence, shape=(batch_size, ))

        if sample_weight is not None:
            sample_weight = tf.convert_to_tensor(sample_weight)
            sample_weight = tf.reshape(sample_weight, shape=(batch_size, ))
            sample_weight = tf.cast(sample_weight, dtype=self.dtype)
        else:
            sample_weight = tf.ones((batch_size, ), dtype=self.dtype)

        # Computes correct predictions.
        correct_preds = _compute_correct_predictions(y_true,
                                                     y_pred,
                                                     dtype=self.dtype)
        correct_preds_weighted = correct_preds * sample_weight

        # Computes batch-specific histogram statistics for confidence score.
        batch_bin_indices = tf.histogram_fixed_width_bins(
            confidence,
            tf.constant([0., 1.], self.dtype),
            nbins=self.num_approx_bins)
        batch_total_counts = tf.math.unsorted_segment_sum(
            data=sample_weight,
            segment_ids=batch_bin_indices,
            num_segments=self.num_approx_bins)
        batch_correct_counts = tf.math.unsorted_segment_sum(
            data=correct_preds_weighted,
            segment_ids=batch_bin_indices,
            num_segments=self.num_approx_bins)

        self.binned_total_counts.assign_add(batch_total_counts)
        self.binned_correct_counts.assign_add(batch_correct_counts)
Exemplo n.º 11
0
def test_hist_from_nonnegative_ints():
    print('\n' + "*" * 20 + '\nhist_from_nonnegative_ints')
    tensor = tf.histogram_fixed_width_bins(
        tf.random.normal([100000], dtype=tf.float32, mean=0, stddev=1),
        [-15., 15.],
        nbins=30,
    )
    tensor = tf.reshape(tensor, [10000, 10])
    hist = tensors.hist_from_nonnegative_ints(tensor, -2, 30)
    config = tf.ConfigProto(allow_soft_placement=True)
    config.gpu_options.allow_growth = True
    with tf.Session(config=config) as sess:
        print(np.max(sess.run(tensor)))
        print(sess.run(hist))
Exemplo n.º 12
0
 def histogram_collector(results, variables):
     """This function will receive a tensor (result)
     and the variables corresponding to those integrand results
     In the example integrand below, these corresponds to
         `final_result` and `histogram_values` respectively.
     `current_histograms` instead is the current value of the histogram
     which will be overwritten"""
     # Fill a histogram with HISTO_BINS (2) bins, (0 to 0.5, 0.5 to 1)
     # First generate the indices with TF
     indices = tf.histogram_fixed_width_bins(variables, [fzero, fone], nbins=HISTO_BINS)
     t_indices = tf.transpose(indices)
     # Then consume the results with the utility we provide
     partial_hist = consume_array_into_indices(results, t_indices, HISTO_BINS)
     # Then update the results of current_histograms
     new_histograms = partial_hist + current_histograms
     cummulator_tensor.assign(new_histograms)
Exemplo n.º 13
0
    def get_jh(x, y, value_range, nbins):
        dtype = tf.dtypes.int32
        x_range = value_range[0]
        y_range = value_range[1]
        histy_bins = tf.histogram_fixed_width_bins(y,
                                                   y_range,
                                                   nbins=nbins,
                                                   dtype=dtype)

        def masking_info(tf_val):
            return tf.math.equal(histy_bins, tf_val)

        H = tf.map_fn(
            lambda i: tf.histogram_fixed_width(
                x[masking_info(i)], x_range, nbins=nbins), tf.range(nbins))

        return H
Exemplo n.º 14
0
def histogram2D(x, y, value_range, x_bins=100, y_bins=None, dtype=tf.float64):
    """
    Generate a 2D histogram
    
    This code was copied from:
    https://gist.github.com/isentropic/a86effab2c007e86912a50f995cac52b
    
    And it was modified slightly.  This function uses tf instead of np to make the histogram.
    
    I had a tremendous amount of confusion about which index correlates to which dimension.
    After a bunch of testing it seems like the popular convention is the opposite of my
    intuition.  And I have been having this problem before...  So in the tensor that this 
    returns, y is the first index and x is the second.
    
    Parameters
    ----------
    x, y : 1D tensor
        The x and y values of the points to bin.
    value_range : 2x2 array-like
        The limits to use for the bins in the x and y directions
    xbins, ybins : int, optional
        Defaults to 100.  The number of bins to use in each dimension
    dtype : tf.dtype, optional
        Defaults to tf.float64.  The dtype to use for the histogram.
    """
    y_bins = y_bins or x_bins
    x_range = tf.cast(value_range[0], dtype)
    y_range = tf.cast(value_range[1], dtype)

    histy_bins = tf.histogram_fixed_width_bins(y,
                                               y_range,
                                               nbins=y_bins,
                                               dtype=dtype)

    H = tf.map_fn(
        lambda i: tf.histogram_fixed_width(
            x[histy_bins == i], x_range, nbins=x_bins), tf.range(y_bins))
    return H
    # noise_prob = noise_counts / np.sum(noise_counts)
    # img_prob = img_counts / np.sum(img_counts)
    # noise_prob = noise_prob[np.nonzero(noise_prob)]
    # img_prob = img_prob[np.nonzero(img_prob)]
    #
    # assert np.sum(noise_prob) == 1.0, print(np.sum(noise_prob))
    # assert np.sum(img_prob) == 1.0, np.sum(img_prob)
    #
    # noise_info = np.log2(noise_prob)
    # img_info = np.log2(img_prob)
    #
    # noise_entropy = -np.sum(noise_prob * noise_info)
    # img_entropy = -np.sum(img_prob * img_info)

    noise_idx = tf.histogram_fixed_width_bins(
        tf.reshape(noise, [-1]),
        [tf.reduce_min(noise), tf.reduce_max(noise)], 64)
    img_idx = tf.histogram_fixed_width_bins(
        tf.reshape(img, [-1]),
        [tf.reduce_min(img), tf.reduce_max(img)], 64)
    noise_idx = tf.sort(noise_idx)
    img_idx = tf.sort(img_idx)
    _, _, noise_counts = tf.unique_with_counts(noise_idx)
    _, _, img_counts = tf.unique_with_counts(img_idx)
    noise_prob = noise_counts / tf.reduce_sum(noise_counts)
    img_prob = img_counts / tf.reduce_sum(img_counts)

    assert tf.reduce_sum(noise_prob).numpy() == 1.0, tf.reduce_sum(noise_prob)
    assert tf.reduce_sum(img_prob).numpy() == 1.0, tf.reduce_sum(img_prob)

    noise_entropy = -tf.reduce_sum(noise_prob * tf.math.log(noise_prob))
Exemplo n.º 16
0
import tensorflow as tf
import numpy as np
import src.utilities.tf_utils as tfu
import matplotlib.pyplot as plt
from src.test_functions.np_tv_denoise_test import tv_denoise
from PIL import Image

tf.InteractiveSession()

A = tf.constant([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]])
a_b = tf.histogram_fixed_width_bins(values=A, value_range=[0., 9.], nbins=3)
b = tf.constant(2)
bi = a_b.eval()
x = (a_b + b).eval()

ten = tf.ones([6, 5, 3, 3])
drop_out = tf.nn.dropout(ten, keep_prob=2 / 3, noise_shape=[6, 5, 1, 1])

with tf.Session() as sess:
    dn = sess.run(drop_out)
    a = 0
img = np.array(
    plt.imread(
        "/home/christian/Projects/Lab_SS2019/dataset/2d_slices/png/raw/train/HGG/brats_2013_pat0006_1/VSD.Brain.XX.O.MR_Flair.54542/VSD.Brain.XX.O.MR_Flair.54542_82.png"
    ))

img2 = np.array(
    plt.imread(
        "/home/christian/Projects/Lab_SS2019/dataset/2d_slices/png/raw/train/HGG/brats_2013_pat0006_1/VSD.Brain.XX.O.MR_T2.54545/VSD.Brain.XX.O.MR_T2.54545_82.png"
    ))
Exemplo n.º 17
0
def _compute_calibration_bin_statistics(num_bins,
                                        logits=None,
                                        probabilities=None,
                                        labels_true=None,
                                        labels_predicted=None):
    """Compute binning statistics required for calibration measures.

  Args:
    num_bins: int, number of probability bins, e.g. 10.
    logits: Tensor, (n,nlabels), with logits for n instances and nlabels.
    probabilities: Tensor, (n,nlabels), with probs for n instances and nlabels.
    labels_true: Tensor, (n,), with tf.int32 or tf.int64 elements containing
      ground truth class labels in the range [0,nlabels].
    labels_predicted: Tensor, (n,), with tf.int32 or tf.int64 elements
      containing decisions of the predictive system.  If `None`, we will use
      the argmax decision using the `logits`.

  Returns:
    bz: Tensor, shape (2,num_bins), tf.int32, counts of incorrect (row 0) and
      correct (row 1) predictions in each of the `num_bins` probability bins.
    pmean_observed: Tensor, shape (num_bins,), tf.float32, the mean predictive
      probabilities in each probability bin.
  """
    if (logits is None) == (probabilities is None):
        raise ValueError(
            "_compute_calibration_bin_statistics expects exactly one of logits or "
            "probabilities.")
    elif probabilities is None:
        if logits.get_shape().as_list()[-1] == 1:  # pytype: disable=attribute-error
            raise ValueError(
                "_compute_calibration_bin_statistics expects logits for binary"
                " classification of shape (n, 2) for nlabels=2 but got ",
                logits.get_shape())  # pytype: disable=attribute-error
        probabilities = tf.math.softmax(logits, axis=1)
    elif (probabilities.get_shape().as_list()[-1] == 1
          or len(probabilities.get_shape().as_list()) == 1):
        raise ValueError(
            "_compute_calibration_bin_statistics expects probabilities for binary"
            " classification of shape (n, 2) for nlabels=2 but got ",
            probabilities.get_shape())

    if labels_predicted is None:
        # If no labels are provided, we take the label with the maximum probability
        # decision.  This corresponds to the optimal expected minimum loss decision
        # under 0/1 loss.
        pred_y = tf.cast(tf.argmax(probabilities, axis=1), tf.int32)
    else:
        pred_y = labels_predicted

    correct = tf.cast(tf.equal(pred_y, labels_true), tf.int32)

    # Collect predicted probabilities of decisions
    prob_y = tf.compat.v1.batch_gather(probabilities,
                                       tf.expand_dims(pred_y,
                                                      1))  # p(pred_y | x)
    prob_y = tf.reshape(prob_y, (tf.size(prob_y), ))

    # Compute b/z histogram statistics:
    # bz[0,bin] contains counts of incorrect predictions in the probability bin.
    # bz[1,bin] contains counts of correct predictions in the probability bin.
    bins = tf.histogram_fixed_width_bins(prob_y, [0.0, 1.0], nbins=num_bins)
    event_bin_counts = tf.math.bincount(correct * num_bins + bins,
                                        minlength=2 * num_bins,
                                        maxlength=2 * num_bins)
    event_bin_counts = tf.reshape(event_bin_counts, (2, num_bins))

    # Compute mean predicted probability value in each of the `num_bins` bins
    pmean_observed = tf.math.unsorted_segment_sum(prob_y, bins, num_bins)
    tiny = np.finfo(np.float32).tiny
    pmean_observed = pmean_observed / (
        tf.cast(tf.reduce_sum(event_bin_counts, axis=0), tf.float32) + tiny)

    return event_bin_counts, pmean_observed
Exemplo n.º 18
0
def hist_1d(values, num_bins, range_, axis):
    with tf.name_scope('hist_1d'):
        discrete = tf.histogram_fixed_width_bins(values, range_, num_bins)
        return hist_from_nonnegative_ints(discrete, axis, num_bins)
Exemplo n.º 19
0
    def _bin_confusion_matrix_by_score(
            self, pred_labels: Sequence[Sequence[bool]],
            true_labels: Sequence[Sequence[bool]],
            binning_score: Sequence[Sequence[float]]) -> Dict[str, tf.Tensor]:
        """Compute the confusion matrix, binning predictions by a specified score.

    Computes the confusion matrix over matrices of predicted and true labels.
    Each element of the resultant confusion matrix is itself a matrix of the
    same shape as the original input labels.

    In the typical use of this function in OracleCollaborativeAUC, the variables
    T and N (in the args and returns sections below) are the number of
    thresholds and the number of examples, respectively.

    Args:
      pred_labels: Boolean tensor of shape [T, N] of predicted labels.
      true_labels: Boolean tensor of shape [T, N] of true labels.
      binning_score: Boolean tensor of shape [T, N] of scores to use in
        assigning labels to bins.

    Returns:
      Dictionary of strings to entries of the confusion matrix
      ('true_positives', 'true_negatives', 'false_positives',
      'false_negatives'). Each entry is a tensor of shape [T, nbins].

      If oracle_threshold was set, nbins=2, storing respectively the number of
      examples below the oracle_threshold (i.e. sent to the oracle) and above it
      (not sent to the oracle).
    """
        correct_preds = tf.math.equal(pred_labels, true_labels)

        # Elements of the confusion matrix have shape [M, N]
        pred_true_positives = tf.math.logical_and(correct_preds, pred_labels)
        pred_true_negatives = tf.math.logical_and(
            correct_preds, tf.math.logical_not(pred_labels))
        pred_false_positives = tf.math.logical_and(
            tf.math.logical_not(correct_preds), pred_labels)
        pred_false_negatives = tf.math.logical_and(
            tf.math.logical_not(correct_preds),
            tf.math.logical_not(pred_labels))

        # Cast confusion matrix elements from bool to self.dtype.
        pred_true_positives = tf.cast(pred_true_positives, self.dtype)
        pred_true_negatives = tf.cast(pred_true_negatives, self.dtype)
        pred_false_positives = tf.cast(pred_false_positives, self.dtype)
        pred_false_negatives = tf.cast(pred_false_negatives, self.dtype)

        histogram_value_range = tf.constant([0.0, 1.0], self.dtype)
        if self.oracle_threshold is not None:
            # All predictions with score <= oracle_threshold are sent to the oracle.
            # With two bins, centering the value range on oracle_threshold yields a
            # histogram with all examples sent to the oracle in the lower (left) bin.
            histogram_value_range += self.oracle_threshold - 0.5
            # Move the histogram center up by epsilon to ensure <= rather than <.
            # By default, tf histogram gives [low, high); we want (low, high].
            histogram_value_range += tf.keras.backend.epsilon()
        bin_indices = tf.histogram_fixed_width_bins(binning_score,
                                                    histogram_value_range,
                                                    nbins=self.num_bins)

        binned_true_positives = self._map_unsorted_segment_sum(
            pred_true_positives, bin_indices)
        binned_true_negatives = self._map_unsorted_segment_sum(
            pred_true_negatives, bin_indices)
        binned_false_positives = self._map_unsorted_segment_sum(
            pred_false_positives, bin_indices)
        binned_false_negatives = self._map_unsorted_segment_sum(
            pred_false_negatives, bin_indices)

        return {
            "true_positives": binned_true_positives,
            "true_negatives": binned_true_negatives,
            "false_positives": binned_false_positives,
            "false_negatives": binned_false_negatives
        }
Exemplo n.º 20
0
 def f(sample):
     return tf.histogram_fixed_width_bins(
         sample, [tf.reduce_min(sample),
                  tf.reduce_max(sample)],
         nbins=2)
Exemplo n.º 21
0
def expected_calibration_error(y_true, y_pred, nbins=20):
  """Calculates Expected Calibration Error (ECE).

  ECE is a scalar summary statistic of calibration error. It is the
  sample-weighted average of the difference between the predicted and true
  probabilities of a positive detection across uniformly-spaced model
  confidences [0, 1]. See referenced paper for a thorough explanation.

  Reference:
    Guo, et. al, "On Calibration of Modern Neural Networks"
    Page 2, Expected Calibration Error (ECE).
    https://arxiv.org/pdf/1706.04599.pdf

  This function creates three local variables, `bin_counts`, `bin_true_sum`, and
  `bin_preds_sum` that are used to compute ECE.  For estimation of the metric
  over a stream of data, the function creates an `update_op` operation that
  updates these variables and returns the ECE.

  Args:
    y_true: 1-D tf.int64 Tensor of binarized ground truth, corresponding to each
      prediction in y_pred.
    y_pred: 1-D tf.float32 tensor of model confidence scores in range
      [0.0, 1.0].
    nbins: int specifying the number of uniformly-spaced bins into which y_pred
      will be bucketed.

  Returns:
    value_op: A value metric op that returns ece.
    update_op: An operation that increments the `bin_counts`, `bin_true_sum`,
      and `bin_preds_sum` variables appropriately and whose value matches `ece`.

  Raises:
    InvalidArgumentError: if y_pred is not in [0.0, 1.0].
  """
  bin_counts = metrics_impl.metric_variable(
      [nbins], tf.float32, name='bin_counts')
  bin_true_sum = metrics_impl.metric_variable(
      [nbins], tf.float32, name='true_sum')
  bin_preds_sum = metrics_impl.metric_variable(
      [nbins], tf.float32, name='preds_sum')

  with tf.control_dependencies([
      tf.assert_greater_equal(y_pred, 0.0),
      tf.assert_less_equal(y_pred, 1.0),
  ]):
    bin_ids = tf.histogram_fixed_width_bins(y_pred, [0.0, 1.0], nbins=nbins)

  with tf.control_dependencies([bin_ids]):
    update_bin_counts_op = tf.assign_add(
        bin_counts, tf.to_float(tf.bincount(bin_ids, minlength=nbins)))
    update_bin_true_sum_op = tf.assign_add(
        bin_true_sum,
        tf.to_float(tf.bincount(bin_ids, weights=y_true, minlength=nbins)))
    update_bin_preds_sum_op = tf.assign_add(
        bin_preds_sum,
        tf.to_float(tf.bincount(bin_ids, weights=y_pred, minlength=nbins)))

  ece_update_op = _ece_from_bins(
      update_bin_counts_op,
      update_bin_true_sum_op,
      update_bin_preds_sum_op,
      name='update_op')
  ece = _ece_from_bins(bin_counts, bin_true_sum, bin_preds_sum, name='value')
  return ece, ece_update_op
Exemplo n.º 22
0
    def create_hist(self, image, nbins, source_range, normalize):
        """
		Creates a histogram of a given image. The histogram is computed on the flattened image,
		so for colour images, the function should be used separately on each channel to obtain a histogram 
		for each colour channel.

		Parameters
		__________
		
		image: array - an array representation of the image
		nbins: int (optional) - number of bins used to calculate histogram
		source_range: string (optional) - 'image' (default) gets the range from the input image,
        'dtype' determines the range from the expected range of the images of that data type.
		normalize: bool (optional) - If True, the histogram will be normalized by the sum of its values.

		Returns
		_______
		
		hist: array - the values of the histogram
		bin_centers: array - the values of center of the bins.

		Example
		_______

		See main.py for example script

		"""
        # check the shape of image
        shape = tf.shape(image)

        if (tf.size(shape) == 3):
            print(
                "If this is a colour image, the histogram will be computed on the flattened image.\
				You can instead apply this function to each color channel.")

        # setup
        sess = tf.InteractiveSession()
        image = tf.constant(image)

        # flatten image
        image_flatten = tf.reshape(image, [-1])

        # specify the source range
        if (source_range == 'image'):

            # general range
            min_val = tf.reduce_min(image_flatten).eval()
            max_val = tf.reduce_max(image_flatten).eval()
            hist_range = tf.constant([min_val, max_val], dtype=tf.float64)

        elif (source_range == 'dtype'):

            # get the limits of the type
            hist_range = tf.DType(image_flatten.dtype).limits
            hist_range = tf.constant(hist_range, dtype=tf.float64)

        else:
            print('Wrong value for `source range` parameter')

        # cast
        image_flatten = tf.dtypes.cast(image_flatten, tf.float64)

        # get values and bin edges of the histogram
        hist = tf.histogram_fixed_width(image_flatten, hist_range, nbins=nbins)
        bins = tf.histogram_fixed_width_bins(image_flatten,
                                             hist_range,
                                             nbins=nbins)

        bin_centres = (bins[:-1] + bins[1:]) / 2

        # normalize if specified
        if (normalize):
            hist = hist / tf.reduce_sum(hist)

        return hist.eval(), bin_centres.eval()
Exemplo n.º 23
0
def expected_calibration_error(y_true, y_pred, nbins=20):
    """Calculates Expected Calibration Error (ECE).

  ECE is a scalar summary statistic of calibration error. It is the
  sample-weighted average of the difference between the predicted and true
  probabilities of a positive detection across uniformly-spaced model
  confidences [0, 1]. See referenced paper for a thorough explanation.

  Reference:
    Guo, et. al, "On Calibration of Modern Neural Networks"
    Page 2, Expected Calibration Error (ECE).
    https://arxiv.org/pdf/1706.04599.pdf

  This function creates three local variables, `bin_counts`, `bin_true_sum`, and
  `bin_preds_sum` that are used to compute ECE.  For estimation of the metric
  over a stream of data, the function creates an `update_op` operation that
  updates these variables and returns the ECE.

  Args:
    y_true: 1-D tf.int64 Tensor of binarized ground truth, corresponding to each
      prediction in y_pred.
    y_pred: 1-D tf.float32 tensor of model confidence scores in range
      [0.0, 1.0].
    nbins: int specifying the number of uniformly-spaced bins into which y_pred
      will be bucketed.

  Returns:
    value_op: A value metric op that returns ece.
    update_op: An operation that increments the `bin_counts`, `bin_true_sum`,
      and `bin_preds_sum` variables appropriately and whose value matches `ece`.

  Raises:
    InvalidArgumentError: if y_pred is not in [0.0, 1.0].
  """
    bin_counts = metrics_impl.metric_variable([nbins],
                                              tf.float32,
                                              name='bin_counts')
    bin_true_sum = metrics_impl.metric_variable([nbins],
                                                tf.float32,
                                                name='true_sum')
    bin_preds_sum = metrics_impl.metric_variable([nbins],
                                                 tf.float32,
                                                 name='preds_sum')

    with tf.control_dependencies([
            tf.assert_greater_equal(y_pred, 0.0),
            tf.assert_less_equal(y_pred, 1.0),
    ]):
        bin_ids = tf.histogram_fixed_width_bins(y_pred, [0.0, 1.0],
                                                nbins=nbins)

    with tf.control_dependencies([bin_ids]):
        update_bin_counts_op = tf.assign_add(
            bin_counts,
            tf.cast(tf.bincount(bin_ids, minlength=nbins), dtype=tf.float32))
        update_bin_true_sum_op = tf.assign_add(
            bin_true_sum,
            tf.cast(tf.bincount(bin_ids, weights=y_true, minlength=nbins),
                    dtype=tf.float32))
        update_bin_preds_sum_op = tf.assign_add(
            bin_preds_sum,
            tf.cast(tf.bincount(bin_ids, weights=y_pred, minlength=nbins),
                    dtype=tf.float32))

    ece_update_op = _ece_from_bins(update_bin_counts_op,
                                   update_bin_true_sum_op,
                                   update_bin_preds_sum_op,
                                   name='update_op')
    ece = _ece_from_bins(bin_counts, bin_true_sum, bin_preds_sum, name='value')
    return ece, ece_update_op
Exemplo n.º 24
0
def mclahe(x,
           kernel_size=None,
           n_bins=128,
           clip_limit=0.01,
           adaptive_hist_range=False,
           use_gpu=True):
    """
    Contrast limited adaptive histogram equalization implemented in tensorflow
    :param x: numpy array to which clahe is applied
    :param kernel_size: tuple of kernel sizes, 1/8 of dimension lengths of x if None
    :param n_bins: number of bins to be used in the histogram
    :param clip_limit: relative intensity limit to be ignored in the histogram equalization
    :param adaptive_hist_range: flag, if true individual range for histogram computation of each block is used
    :param use_gpu: Flag, if true gpu is used for computations if available
    :return: numpy array to which clahe was applied, scaled on interval [0, 1]
    """

    if kernel_size is None:
        kernel_size = tuple(s // 8 for s in x.shape)
    kernel_size = np.array(kernel_size)

    assert len(kernel_size) == len(x.shape)

    dim = len(x.shape)

    # Normalize data
    x_min = np.min(x)
    x_max = np.max(x)
    x = (x - x_min) / (x_max - x_min)

    # Pad data
    x_shape = np.array(x.shape)
    padding_x_length = kernel_size - 1 - ((x_shape - 1) % kernel_size)
    padding_x = np.column_stack(
        ((padding_x_length + 1) // 2, padding_x_length // 2))
    padding_hist = np.column_stack(
        (kernel_size // 2, (kernel_size + 1) // 2)) + padding_x
    x_hist_padded = np.pad(x, padding_hist, 'symmetric')

    # Set up tf graph
    with tf.variable_scope("clahe") as scope:
        tf_x_hist_padded_init = tf.placeholder(tf.float32,
                                               shape=x_hist_padded.shape)
        tf_x_hist_padded = tf.Variable(tf_x_hist_padded_init)
        tf_x_padded = tf.slice(tf_x_hist_padded, kernel_size // 2,
                               x_shape + padding_x_length)

        # Form blocks used for interpolation
        n_blocks = np.ceil(np.array(x.shape) / kernel_size).astype(np.int32)
        new_shape = np.reshape(np.column_stack((n_blocks, kernel_size)),
                               (2 * dim, ))
        perm = tuple(2 * i for i in range(dim)) + tuple(2 * i + 1
                                                        for i in range(dim))
        tf_x_block = tf.transpose(tf.reshape(tf_x_padded, new_shape),
                                  perm=perm)
        shape_x_block = np.concatenate((n_blocks, kernel_size))

        # Form block used for histogram
        n_blocks_hist = n_blocks + np.ones(dim, dtype=np.int32)
        new_shape = np.reshape(np.column_stack((n_blocks_hist, kernel_size)),
                               (2 * dim, ))
        perm = tuple(2 * i for i in range(dim)) + tuple(2 * i + 1
                                                        for i in range(dim))
        tf_x_hist = tf.transpose(tf.reshape(tf_x_hist_padded, new_shape),
                                 perm=perm)

        # Get maps
        # Get histogram
        if adaptive_hist_range:
            hist_ex_shape = np.concatenate((n_blocks_hist, [1] * dim))
            tf_x_hist_ex_init = tf.placeholder(tf.float32, shape=n_blocks_hist)
            tf_x_hist_min = tf.Variable(tf_x_hist_ex_init, dtype=tf.float32)
            tf_x_hist_max = tf.reduce_max(tf_x_hist, np.arange(-dim, 0))
            tf_x_hist_norm = tf.Variable(tf_x_hist_ex_init, dtype=tf.float32)
            tf_get_hist_min = tf.assign(
                tf_x_hist_min, tf.reduce_min(tf_x_hist, np.arange(-dim, 0)))
            tf_get_hist_norm = tf.assign(
                tf_x_hist_norm,
                tf.where(tf.equal(tf_x_hist_min, tf_x_hist_max),
                         tf.ones_like(tf_x_hist_min),
                         tf_x_hist_max - tf_x_hist_min))

            tf_x_hist_scaled = (tf_x_hist - tf.reshape(tf_x_hist_min, hist_ex_shape))\
                               / tf.reshape(tf_x_hist_norm, hist_ex_shape)
        else:
            tf_x_hist_scaled = tf_x_hist
        tf_hist = tf.cast(
            tf_batch_histogram(tf_x_hist_scaled, [0., 1.], dim, nbins=n_bins),
            tf.float32)
        # Clip histogram
        tf_n_to_high = tf.reduce_sum(
            tf.nn.relu(tf_hist - np.prod(kernel_size) * clip_limit),
            -1,
            keepdims=True)
        tf_hist_clipped = tf.minimum(
            tf_hist,
            np.prod(kernel_size) * clip_limit) + tf_n_to_high / n_bins
        tf_cdf = tf.cumsum(tf_hist_clipped, -1)
        tf_cdf_slice_size = tf.constant(np.concatenate((n_blocks_hist, [1])),
                                        tf.int32)
        tf_cdf_min = tf.slice(tf_cdf,
                              tf.constant([0] * (dim + 1), dtype=tf.int32),
                              tf_cdf_slice_size)
        tf_cdf_max = tf.slice(
            tf_cdf, tf.constant([0] * dim + [n_bins - 1], dtype=tf.int32),
            tf_cdf_slice_size)
        tf_cdf_norm = tf.where(tf.equal(tf_cdf_min, tf_cdf_max),
                               tf.ones_like(tf_cdf_max),
                               tf_cdf_max - tf_cdf_min)
        tf_mapping = (tf_cdf - tf_cdf_min) / tf_cdf_norm

        map_shape = np.concatenate((n_blocks_hist, [n_bins]))
        tf_map_init = tf.placeholder(tf.float32, shape=map_shape)
        tf_map = tf.Variable(tf_map_init, dtype=tf.float32)
        tf_get_map = tf.assign(tf_map, tf_mapping)

        # Prepare initializer
        tf_x_block_init = tf.placeholder(tf.float32, shape=shape_x_block)

        # Set up slice of data and map
        tf_slice_begin = tf.placeholder(tf.int32, shape=(dim, ))
        tf_map_slice_begin = tf.concat([tf_slice_begin, [0]], 0)
        tf_map_slice_size = tf.constant(np.concatenate((n_blocks, [n_bins])),
                                        dtype=tf.int32)
        tf_map_slice = tf.slice(tf_map, tf_map_slice_begin, tf_map_slice_size)
        # Get bins
        if adaptive_hist_range:
            # Local bins
            tf_hist_norm_slice_shape = np.concatenate((n_blocks, [1] * dim))
            tf_x_hist_min_sub = tf.slice(tf_x_hist_min, tf_slice_begin,
                                         n_blocks)
            tf_x_hist_norm_sub = tf.slice(tf_x_hist_norm, tf_slice_begin,
                                          n_blocks)
            tf_x_block_scaled = (tf_x_block - tf.reshape(tf_x_hist_min_sub, tf_hist_norm_slice_shape))\
                                / tf.reshape(tf_x_hist_norm_sub, tf_hist_norm_slice_shape)
            tf_bin = tf.histogram_fixed_width_bins(tf_x_block_scaled, [0., 1.],
                                                   nbins=n_bins)
        else:
            # Global bins
            tf_bin = tf.Variable(tf.cast(tf_x_block_init, tf.int32),
                                 dtype=tf.int32)
            tf_get_bin = tf.assign(
                tf_bin,
                tf.histogram_fixed_width_bins(tf_x_block, [0., 1.],
                                              nbins=n_bins))
        # Apply map
        tf_mapped_sub = tf_batch_gather(tf_map_slice, tf_bin, dim)
        # Apply coefficients
        tf_coeff = tf.placeholder(tf.float32)
        tf_res_sub = tf.Variable(tf_x_block_init, dtype=tf.float32)
        tf_apply_map = tf.assign(tf_res_sub, tf_mapped_sub)
        tf_apply_coeff = tf.assign(tf_res_sub, tf_coeff * tf_res_sub)
        # Update results
        tf_res = tf.Variable(tf_x_block_init, dtype=tf.float32)
        tf_update_res = tf.assign_add(tf_res, tf_res_sub)

        # Rescaling
        tf_res_min, tf_res_max = (tf.reduce_min(tf_res), tf.reduce_max(tf_res))
        tf_res_norm = (tf_res - tf_res_min) / (tf_res_max - tf_res_min)
        tf_rescale = tf.assign(tf_res, tf_res_norm)

        # Reshape result
        new_shape = tuple((axis, axis + dim) for axis in range(dim))
        new_shape = tuple(j for i in new_shape for j in i)
        tf_res_transposed = tf.transpose(tf_res, new_shape)
        tf_res_reshaped = tf.reshape(
            tf_res_transposed,
            tuple(n_blocks[axis] * kernel_size[axis] for axis in range(dim)))

        # Recover original size
        tf_res_cropped = tf.slice(tf_res_reshaped, padding_x[:, 0], x.shape)

        # Setting up tf session
        if use_gpu:
            config = None
        else:
            config = tf.ConfigProto(device_count={'GPU': 0})

        with tf.Session(config=config) as sess:
            map_init = np.zeros(map_shape, dtype=np.float32)
            x_block_init = np.zeros(shape_x_block, dtype=np.float32)
            # Initialize vars for local hist range if needed
            if adaptive_hist_range:
                x_hist_ex_init = np.zeros(n_blocks_hist, dtype=np.float32)
                tf_var_init = tf.initializers.variables([
                    tf_x_hist_padded, tf_map, tf_res, tf_res_sub,
                    tf_x_hist_min, tf_x_hist_norm
                ])
                sess.run(tf_var_init,
                         feed_dict={
                             tf_x_hist_padded_init: x_hist_padded,
                             tf_map_init: map_init,
                             tf_x_block_init: x_block_init,
                             tf_x_hist_ex_init: x_hist_ex_init
                         })
            else:
                tf_var_init = tf.initializers.variables(
                    [tf_x_hist_padded, tf_map, tf_bin, tf_res, tf_res_sub])
                sess.run(tf_var_init,
                         feed_dict={
                             tf_x_hist_padded_init: x_hist_padded,
                             tf_map_init: map_init,
                             tf_x_block_init: x_block_init
                         })

            # Run calculations
            # Normalize histogram data if needed
            if adaptive_hist_range:
                sess.run(tf_get_hist_min)
                sess.run(tf_get_hist_norm)
            sess.run(tf_get_map)
            # Get global hist bins if needed
            if not adaptive_hist_range:
                sess.run(tf_get_bin)
            # Loop over maps
            inds = [list(i) for i in product([0, 1], repeat=dim)]
            for ind_map in inds:
                sess.run(tf_apply_map, feed_dict={tf_slice_begin: ind_map})
                # Calculate and apply coefficients
                for axis in range(dim):
                    coeff = np.arange(kernel_size[axis],
                                      dtype=np.float32) / kernel_size[axis]
                    if kernel_size[axis] % 2 == 0:
                        coeff = 0.5 / kernel_size[axis] + coeff
                    if ind_map[axis] == 0:
                        coeff = 1. - coeff
                    new_shape = [1] * (dim + axis) + [
                        kernel_size[axis]
                    ] + [1] * (dim - 1 - axis)
                    coeff = np.reshape(coeff, new_shape)
                    sess.run(tf_apply_coeff, feed_dict={tf_coeff: coeff})
                # Update results
                sess.run(tf_update_res)

            # Rescaling
            sess.run(tf_rescale)

            # Get result
            result = sess.run(tf_res_cropped)

    return result
Exemplo n.º 25
0
def sft_generator(img_shape, hu_min, hu_max, spectr_norm=False, gen_out=None):
    input_layer = Input(shape=img_shape)

    # Part 1. Feature Extraction Network
    filter_outputs = [
        64, 54, 48, 43, 39, 35, 31, 28, 25, 22, 18, 16, 24, 8, 8, 32, 16
    ]
    fe_layers = []
    for i in range(12):
        if i == 0:
            # segmentation map
            indices = tf.histogram_fixed_width_bins(
                input_layer, [float(hu_min), float(hu_max)], 10)
            seg_map = tf.one_hot(indices, 10)
            seg_map = tf.squeeze(seg_map, axis=3)
            sm = condition()(seg_map)

            # feature map
            fe = conv2d(input_layer,
                        filters=filter_outputs[i],
                        kernel_size=3,
                        stride=2,
                        padding='same',
                        sn=spectr_norm)
            fe = LeakyReLU(0.1)(fe)
            fe = Dropout(0.2)(fe)
        else:
            fe = sft(units=[32, fe.shape[-1]])([fe, sm])
            fe = conv2d(fe,
                        filters=filter_outputs[i],
                        kernel_size=3,
                        stride=1,
                        padding='same',
                        sn=spectr_norm)
            fe = LeakyReLU(0.1)(fe)
            fe = Dropout(0.2)(fe)

        fe_layers.append(fe)

    fe_final_layer = Concatenate()(fe_layers)

    # Part 2.1 Reconstruction Network
    a1 = sft(units=[32, fe_final_layer.shape[-1]])([fe_final_layer, sm])
    a1 = conv2d(a1,
                filters=filter_outputs[12],
                kernel_size=1,
                stride=1,
                padding='same',
                sn=spectr_norm)
    a1 = LeakyReLU(0.1)(a1)
    a1 = Dropout(0.2)(a1)

    b1 = sft(units=[32, fe_final_layer.shape[-1]])([fe_final_layer, sm])
    b1 = conv2d(fe_final_layer,
                filters=filter_outputs[13],
                kernel_size=1,
                stride=1,
                padding='same',
                sn=spectr_norm)
    b1 = LeakyReLU(0.1)(b1)
    b1 = Dropout(0.2)(b1)

    b2 = sft(units=[32, b1.shape[-1]])([b1, sm])
    b2 = conv2d(b1,
                filters=filter_outputs[14],
                kernel_size=3,
                stride=1,
                padding='same',
                sn=spectr_norm)
    b2 = LeakyReLU(0.1)(b2)
    b2 = Dropout(0.2)(b2)

    reconstructed = Concatenate()([a1, b2])

    # Part 2.2 Upsampling
    c1 = conv2d(reconstructed,
                filters=filter_outputs[15],
                kernel_size=3,
                stride=1,
                padding='same',
                sn=spectr_norm)
    c1 = LeakyReLU(0.1)(c1)

    c2 = upsample(c1,
                  filters=filter_outputs[16],
                  kernel_size=4,
                  stride=2,
                  padding='same')
    c2 = LeakyReLU(0.1)(c2)

    output = conv2d(c2,
                    filters=1,
                    kernel_size=3,
                    stride=1,
                    padding='same',
                    bias=False,
                    activation=gen_out)

    return Model(input_layer, output)