def plot_pos_dep(m, param, train, use_sigmoid=False, plot=True, figsize=(15, 6)):
    position_stats = train[5]
    # pprint(position_stats)
    w_final = m.layers[-1].get_weights()[0][0, :]
    #print("w_final: ", w_final)
    df_list = []
    if plot:
        plt.figure(figsize=figsize)
    for i, l in enumerate(train[3]):
        # Get the range
        start = position_stats[l]["min"]
        end = position_stats[l]["max"]
        bs = BSpline(start, end, n_bases=param["data"]["n_bases"])
        x_range = np.linspace(start, end, 1000)
        X_pred = bs.predict(x_range)

        if param["model"]["pos_effect"]["merge"]["type"] == "concatenate":
            w_cur = w_final.reshape((-1, ))[1 + i]
        else:
            w_cur = w_final.reshape((1, -1))

        layer = m.get_layer(l + "_conv")
        w = layer.get_weights()[0].squeeze(0)
        y_pred = np.dot(X_pred, w) * w_cur
        if plot:
            plt.subplot(3, 3, i + 1)
            plt.tight_layout()
            if use_sigmoid:
                plt.plot(x_range, sigmoid(y_pred))
            else:
                plt.plot(x_range, y_pred)
            plt.xlim(start, end)
            plt.title(l)
        y = y_pred.reshape((-1,))
        assert len(x_range) == len(y)
        df_list.append(pd.DataFrame({"x": x_range, "y": y, "feature": l}))

    dfpos = pd.concat(df_list)
    return dfpos
Ejemplo n.º 2
0
class GAMSmooth(Layer):
    def __name__(self):
        return "GAMSmooth"

    def __init__(
            self,
            # spline type
            n_bases=10,
            spline_order=3,
            share_splines=False,
            spline_exp=False,
            # regularization
            l2_smooth=1e-5,
            l2=1e-5,
            use_bias=False,
            bias_initializer='zeros',
            **kwargs):
        """

        # Arguments
            n_splines int: Number of splines used for the positional bias.
            spline_exp (bool): If True, the positional bias score is observed by: `np.exp(spline_score)`,
               where `spline_score` is the linear combination of B-spline basis functions.
               If False, `np.exp(spline_score + 1)` is used.
            l2 (float): L2 regularization strength for the second order differences in positional bias' smooth splines.
            (GAM smoothing regularization)
            l2_smooth (float): L2 regularization strength for the spline base coefficients.
            use_bias: boolean; should we add a bias to the transition
            bias_initializer; bias initializer - from keras.initailizers
        """
        self.n_bases = n_bases
        self.spline_order = spline_order
        self.share_splines = share_splines
        self.spline_exp = spline_exp
        self.l2 = l2
        self.l2_smooth = l2_smooth
        self.use_bias = use_bias
        self.bias_initializer = initializers.get(bias_initializer)

        super(GAMSmooth, self).__init__(**kwargs)

    def build(self, input_shape):
        # input_shape = (None, steps, filters)

        start = 0
        end = input_shape[1]
        filters = input_shape[2]

        if self.share_splines:
            n_spline_tracks = 1
        else:
            n_spline_tracks = filters

        # setup the bspline object
        self.bs = BSpline(start,
                          end - 1,
                          n_bases=self.n_bases,
                          spline_order=self.spline_order)

        # create X_spline,
        self.positions = np.arange(end)
        self.X_spline = self.bs.predict(
            self.positions, add_intercept=False)  # shape = (end, self.n_bases)

        # convert to the right precision and K.constant
        self.X_spline_K = K.constant(K.cast_to_floatx(self.X_spline))

        # add weights - all set to 0
        self.kernel = self.add_weight(shape=(self.n_bases, n_spline_tracks),
                                      initializer='zeros',
                                      name='kernel',
                                      regularizer=GAMRegularizer(
                                          self.n_bases, self.spline_order,
                                          self.l2_smooth, self.l2),
                                      trainable=True)

        if self.use_bias:
            self.bias = self.add_weight((n_spline_tracks, ),
                                        initializer=self.bias_initializer,
                                        name='bias',
                                        regularizer=None)

        super(GAMSmooth,
              self).build(input_shape)  # Be sure to call this somewhere!

    def call(self, x):

        spline_track = K.dot(self.X_spline_K, self.kernel)

        if self.use_bias:
            spline_track = K.bias_add(spline_track, self.bias)

        if self.spline_exp:
            spline_track = K.exp(spline_track)
        else:
            spline_track = spline_track + 1

        # multiply together the two coefficients
        output = spline_track * x

        return output

    def compute_output_shape(self, input_shape):
        return input_shape

    def get_config(self):
        config = {
            'n_bases': self.n_bases,
            'spline_order': self.spline_order,
            'share_splines': self.share_splines,
            'spline_exp': self.spline_exp,
            'l2_smooth': self.l2_smooth,
            'l2': self.l2,
            'use_bias': self.use_bias,
            'bias_initializer': initializers.serialize(self.bias_initializer),
        }
        base_config = super(GAMSmooth, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

    def positional_effect(self):
        w = self.get_weights()[0]
        pos_effect = np.dot(self.X_spline, w)
        return {"positional_effect": pos_effect, "positions": self.positions}

    def plot(self, *args, **kwargs):
        pe = self.positional_effect()
        plt.plot(pe["positions"], pe["positional_effect"], *args, **kwargs)
        plt.xlabel("Position")
        plt.ylabel("Positional effect")
Ejemplo n.º 3
0
def encodeSplines(x,
                  n_bases=10,
                  spline_order=3,
                  start=None,
                  end=None,
                  warn=True):
    """**Deprecated**. Function version of the transformer class `EncodeSplines`.
    Get B-spline base-function expansion

    # Details
        First, the knots for B-spline basis functions are placed
        equidistantly on the [start, end] range.
        (inferred from the data if None). Next, b_n(x) value is
        is computed for each x and each n (spline-index) with
        `scipy.interpolate.splev`.

    # Arguments
        x: a numpy array of positions with 2 dimensions
        n_bases int: Number of spline bases.
        spline_order: 2 for quadratic, 3 for qubic splines
        start, end: range of values. If None, they are inferred from the data
        as minimum and maximum value.
        warn: Show warnings.

    # Returns
        `np.ndarray` of shape `(x.shape[0], x.shape[1], n_bases)`
    """

    # TODO - make it general...
    if len(x.shape) == 1:
        x = x.reshape((-1, 1))

    if start is None:
        start = np.nanmin(x)
    else:
        if x.min() < start:
            if warn:
                print(
                    "WARNING, x.min() < start for some elements. Truncating them to start: x[x < start] = start"
                )
            x = _trunc(x, minval=start)
    if end is None:
        end = np.nanmax(x)
    else:
        if x.max() > end:
            if warn:
                print(
                    "WARNING, x.max() > end for some elements. Truncating them to end: x[x > end] = end"
                )
            x = _trunc(x, maxval=end)
    bs = BSpline(start, end, n_bases=n_bases, spline_order=spline_order)

    # concatenate x to long
    assert len(x.shape) == 2
    n_rows = x.shape[0]
    n_cols = x.shape[1]

    x_long = x.reshape((-1, ))

    x_feat = bs.predict(
        x_long, add_intercept=False)  # shape = (n_rows * n_cols, n_bases)

    x_final = x_feat.reshape((n_rows, n_cols, n_bases))
    return x_final
Ejemplo n.º 4
0
class SplineWeight1D(Layer):
    """Up- or down-weight positions in the activation array of 1D convolutions:

    `x^{out}_{ijk} = x^{in}_{ijk} + f_S^k(j) \;,`
    where f_S is the spline transformation.

    # Arguments
        n_bases: int; Number of spline bases used for the positional effect.
        l2_smooth: (float) L2 regularization strength for the second
    order differences in positional bias' smooth splines. (GAM smoothing regularization)
        l2: (float) L2 regularization strength for the spline base coefficients.
        use_bias: boolean; should we add a bias to the transition
        bias_initializer: bias initializer - from `keras.initializers`
    """
    def __name__(self):
        return "SplineWeight1D"

    def __init__(
            self,
            # spline type
            n_bases=10,
            spline_degree=3,
            share_splines=False,
            # regularization
            l2_smooth=0,
            l2=0,
            use_bias=False,
            bias_initializer='zeros',
            **kwargs):
        self.n_bases = n_bases
        self.spline_degree = spline_degree
        self.share_splines = share_splines
        self.l2 = l2
        self.l2_smooth = l2_smooth
        self.use_bias = use_bias
        self.bias_initializer = initializers.get(bias_initializer)

        super(SplineWeight1D, self).__init__(**kwargs)

    def build(self, input_shape):
        # input_shape = (None, steps, filters)

        start = 0
        end = input_shape[1]
        filters = input_shape[2]

        if self.share_splines:
            n_spline_tracks = 1
        else:
            n_spline_tracks = filters

        # setup the bspline object
        self.bs = BSpline(start,
                          end - 1,
                          n_bases=self.n_bases,
                          spline_order=self.spline_degree)

        # create X_spline,
        self.positions = np.arange(end)
        self.X_spline = self.bs.predict(
            self.positions, add_intercept=False)  # shape = (end, self.n_bases)

        # convert to the right precision and K.constant
        self.X_spline_K = K.constant(K.cast_to_floatx(self.X_spline))

        # add weights - all set to 0
        self.kernel = self.add_weight(shape=(self.n_bases, n_spline_tracks),
                                      initializer='zeros',
                                      name='kernel',
                                      regularizer=GAMRegularizer(
                                          self.n_bases, self.spline_degree,
                                          self.l2_smooth, self.l2),
                                      trainable=True)

        if self.use_bias:
            self.bias = self.add_weight((n_spline_tracks, ),
                                        initializer=self.bias_initializer,
                                        name='bias',
                                        regularizer=None)

        super(SplineWeight1D,
              self).build(input_shape)  # Be sure to call this somewhere!

    def call(self, x):

        spline_track = K.dot(self.X_spline_K, self.kernel)

        if self.use_bias:
            spline_track = K.bias_add(spline_track, self.bias)

        # if self.spline_exp:
        #     spline_track = K.exp(spline_track)
        # else:
        spline_track = spline_track + 1

        # multiply together the two coefficients
        output = spline_track * x

        return output

    def compute_output_shape(self, input_shape):
        return input_shape

    def get_config(self):
        config = {
            'n_bases': self.n_bases,
            'spline_degree': self.spline_degree,
            'share_splines': self.share_splines,
            # 'spline_exp': self.spline_exp,
            'l2_smooth': self.l2_smooth,
            'l2': self.l2,
            'use_bias': self.use_bias,
            'bias_initializer': initializers.serialize(self.bias_initializer),
        }
        base_config = super(SplineWeight1D, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

    def positional_effect(self):
        w = self.get_weights()[0]
        pos_effect = np.dot(self.X_spline, w)
        return {"positional_effect": pos_effect, "positions": self.positions}

    def plot(self, *args, **kwargs):
        pe = self.positional_effect()
        plt.plot(pe["positions"], pe["positional_effect"], *args, **kwargs)
        plt.xlabel("Position")
        plt.ylabel("Positional effect")