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 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
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
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")
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")