Module dimdrop.models
Source code
from .param_tsne import ParametricTSNE
from .autoencoder import Autoencoder
from .deepcluster import DeepCluster
from .vasc import VASC
from .dec import DEC
__all__ = [
'ParametricTSNE', 'Autoencoder', 'DeepCluster', 'VASC', 'DEC'
]
Sub-modules
dimdrop.models.autoencoder
dimdrop.models.dec
dimdrop.models.deepcluster
dimdrop.models.param_tsne
dimdrop.models.vasc
-
Code adapted from https://github.com/wang-research/VASC
Classes
class Autoencoder (in_dim, out_dim, layer_sizes=[2000, 1000, 500], lr=0.01, scale=True, log=False, batch_size=100, patience=3, epochs=1000, regularizer=None, pretrain_method='rbm', decay=True, verbose=0)
-
A deep autoencoder model as baseline for other autoencoder based dimensionality reduction methods.
The defaults are set to the parameters explained in a paper of Geoffrey Hinton.
Parameters
in_dim
:int
- The input dimension
out_dim
:int
- The output dimension
layer_sizes
:array
ofint
, optional- The sizes of the layers of the network, is mirrored over encoder and
decoder parts, default
[2000, 1000, 500]
lr
:float
, optional- The learning rate of the network, default
0.01
log
:boolean
, optional- Whether log-transformation should be performed, default
False
scale
:boolean
, optional- Whether scaling (making values within [0,1]) should be performed,
default
True
batch_size
:int
, optional- The batch size of the network, default
100
patience
:int
, optional- The amount of epochs without improvement before the network stops
training, default
3
epochs
:int
, optional- The maximum amount of epochs, default
1000
regularizer
:keras
regularizer
, optional- A regularizer to use for the middle layer of the autoencoder.
None
or instance ofKMeansRegularizer
,dimdrop.regularizers.GMMRegularizer
,TSNERegularizer
. pretrain_method
:string
, optional- The pretrain method to use.
None
,'rbm'
or'stacked'
decay
:bool
, optional- Whether to decay the learning rate during training, default
True
. verbose
:int
, optional- The verbosity of the network, default
0
Attributes
model
:keras
model
- The autoencoder model
encoder
:keras
model
- The encoder model
layers
:array
ofkeras
layers
- The layers of the network
data_transform
:Transform
object
- The transformation to apply on the data before using it
References
- G E Hinton and R R Salakhutdinov. Reducing the dimensionality of data with neural networks. Science, 313(5786):504–507, July 2006.
Source code
class Autoencoder: """ A deep autoencoder model as baseline for other autoencoder based dimensionality reduction methods. The defaults are set to the parameters explained in a paper of Geoffrey Hinton. Parameters ---------- in_dim : int The input dimension out_dim : int The output dimension layer_sizes : array of int, optional The sizes of the layers of the network, is mirrored over encoder and decoder parts, default `[2000, 1000, 500]` lr : float, optional The learning rate of the network, default `0.01` log : boolean, optional Whether log-transformation should be performed, default `False` scale : boolean, optional Whether scaling (making values within [0,1]) should be performed, default `True` batch_size : int, optional The batch size of the network, default `100` patience : int, optional The amount of epochs without improvement before the network stops training, default `3` epochs : int, optional The maximum amount of epochs, default `1000` regularizer : keras regularizer, optional A regularizer to use for the middle layer of the autoencoder. `None` or instance of `dimdrop.regularizers.KMeansRegularizer`, `dimdrop.regularizers.GMMRegularizer`, `dimdrop.regularizers.TSNERegularizer`. pretrain_method : string, optional The pretrain method to use. `None`, `'rbm'` or `'stacked'` decay : bool, optional Whether to decay the learning rate during training, default `True`. verbose : int, optional The verbosity of the network, default `0` Attributes ---------- model : keras model The autoencoder model encoder : keras model The encoder model layers : array of keras layers The layers of the network data_transform : Transform object The transformation to apply on the data before using it References ---------- - G E Hinton and R R Salakhutdinov. Reducing the dimensionality of data with neural networks. *Science*, 313(5786):504–507, July 2006. """ def __init__( self, in_dim, out_dim, layer_sizes=[2000, 1000, 500], lr=0.01, scale=True, log=False, batch_size=100, patience=3, epochs=1000, regularizer=None, pretrain_method='rbm', decay=True, verbose=0 ): self.in_dim = in_dim self.out_dim = out_dim self.layer_sizes = layer_sizes self.lr = lr self.data_transform = Transform(scale, log) self.batch_size = batch_size self.patience = patience self.epochs = epochs self.regularizer = regularizer self.pretrain_method = pretrain_method self.decay = decay self.verbose = verbose self.__pretrainers = {'rbm': self.__pretrain_rbm, 'stacked': self.__pretrain_stacked} self.__init_network() def __init_network(self): activation = 'sigmoid' if self.pretrain_method == 'rbm' else 'relu' self.layers = [Dense( self.layer_sizes[0], activation=activation, input_shape=(self.in_dim,) )] self.layers += [Dense(size, activation=activation) for size in self.layer_sizes[1:]] self.layers += [Dense( self.out_dim, activity_regularizer=self.regularizer )] if self.regularizer else [Dense(self.out_dim)] self.layers += [Dense(size, activation=activation) for size in self.layer_sizes[::-1]] self.layers += [Dense(self.in_dim)] self.model = Sequential( self.layers ) self.model.compile( loss='mse', optimizer=Adam(lr=self.lr, decay=self.lr / self.epochs if self.decay else 0.0) ) self.encoder = Sequential( self.layers[:len(self.layers) // 2] ) def __pretrain_rbm(self, data): rbms = [BernoulliRBM( batch_size=self.batch_size, learning_rate=self.lr, n_components=num, n_iter=20, verbose=self.verbose ) for num in self.layer_sizes + [self.out_dim]] current = data for i, rbm in enumerate(rbms): if self.verbose: print('Training RBM {}/{}'.format(i + 1, len(rbms))) rbm.fit(current) current = rbm.transform(current) dec_layer = self.layers[len(self.layers) - 1 - i] enc_layer = self.layers[i] dec_layer.set_weights( [rbm.components_, dec_layer.get_weights()[1]]) enc_layer.set_weights( [np.transpose(rbm.components_), enc_layer.get_weights()[1]]) def __pretrain_stacked(self, data): num_layers = len(self.layers) cur_data = data early_stopping = EarlyStopping(monitor="loss", patience=self.patience) input_shapes = [(el,) for el in [self.in_dim] + self.layer_sizes] for i in range(num_layers // 2): if self.verbose: print('Training Stack {}/{}'.format(i+1, num_layers // 2)) stack = Sequential([ Dropout(0.2, input_shape=input_shapes[i]), self.layers[i], Dropout(0.2), self.layers[num_layers - i - 1] ]) input_layer = Input(shape=input_shapes[i]) encoder_layer = self.layers[i](input_layer) stack_encode = Model(input_layer, encoder_layer) stack.compile( loss='mse', optimizer=Adam(lr=self.lr, decay=self.lr / self.epochs if self.decay else 0.0) ) stack.fit( cur_data, cur_data, epochs=self.epochs, callbacks=[early_stopping], batch_size=self.batch_size, verbose=self.verbose ) cur_data = stack_encode.predict(cur_data) def fit(self, data): """ Fit the given data to the model. Parameters ---------- data : array Array of training samples where each sample is of size `in_dim` """ data = self.data_transform(data) if self.pretrain_method: self.__pretrainers[self.pretrain_method](data) early_stopping = EarlyStopping(monitor='loss', patience=self.patience) callbacks = [early_stopping] if self.regularizer: self.regularizer.init_fit(self.encoder, data) callbacks.append(self.regularizer) self.model.fit(data, data, epochs=self.epochs, callbacks=callbacks, batch_size=self.batch_size, verbose=self.verbose) def transform(self, data): """ Transform the given data Parameters ---------- data : array Array of samples to be transformed, where each sample is of size `in_dim` Returns ------- array Transformed samples, where each sample is of size `out_dim` """ data = self.data_transform(data) return self.encoder.predict(data, verbose=self.verbose) def fit_transform(self, data): """ Fit the given data to the model and return its transformation Parameters ---------- data : array Array of training samples where each sample is of size `in_dim` Returns ------- array Transformed samples, where each sample is of size `out_dim` """ self.fit(data) return self.transform(data)
Subclasses
Methods
def fit(self, data)
-
Fit the given data to the model.
Parameters
data
:array
- Array of training samples where each sample is of size
in_dim
Source code
def fit(self, data): """ Fit the given data to the model. Parameters ---------- data : array Array of training samples where each sample is of size `in_dim` """ data = self.data_transform(data) if self.pretrain_method: self.__pretrainers[self.pretrain_method](data) early_stopping = EarlyStopping(monitor='loss', patience=self.patience) callbacks = [early_stopping] if self.regularizer: self.regularizer.init_fit(self.encoder, data) callbacks.append(self.regularizer) self.model.fit(data, data, epochs=self.epochs, callbacks=callbacks, batch_size=self.batch_size, verbose=self.verbose)
def fit_transform(self, data)
-
Fit the given data to the model and return its transformation
Parameters
data
:array
- Array of training samples where each sample is of size
in_dim
Returns
array
- Transformed samples, where each sample is of size
out_dim
Source code
def fit_transform(self, data): """ Fit the given data to the model and return its transformation Parameters ---------- data : array Array of training samples where each sample is of size `in_dim` Returns ------- array Transformed samples, where each sample is of size `out_dim` """ self.fit(data) return self.transform(data)
def transform(self, data)
-
Transform the given data
Parameters
data
:array
- Array of samples to be transformed, where each sample is of size
in_dim
Returns
array
- Transformed samples, where each sample is of size
out_dim
Source code
def transform(self, data): """ Transform the given data Parameters ---------- data : array Array of samples to be transformed, where each sample is of size `in_dim` Returns ------- array Transformed samples, where each sample is of size `out_dim` """ data = self.data_transform(data) return self.encoder.predict(data, verbose=self.verbose)
class DEC (in_dim, out_dim, k, layer_sizes=[500, 500, 2000], epochs=1000, lr=0.1, scale=True, log=False, batch_size=256, patience=3, tol=0.01, decay=True, verbose=0)
-
Deep Embedded Clustering model
References
- Junyuan Xie, Ross B. Girshick, and Ali Farhadi. Unsupervised deep embedding for clustering analysis. CoRR, abs/1511.06335, 2015.
Source code
class DEC(Autoencoder): """ Deep Embedded Clustering model References ---------- * Junyuan Xie, Ross B. Girshick, and Ali Farhadi. Unsupervised deep embedding for clustering analysis. *CoRR*, abs/1511.06335, 2015. """ def __init__( self, in_dim, out_dim, k, layer_sizes=[500, 500, 2000], epochs=1000, lr=0.1, scale=True, log=False, batch_size=256, patience=3, tol=0.01, decay=True, verbose=0): super().__init__( in_dim, out_dim, layer_sizes=layer_sizes, lr=lr, scale=scale, log=log, batch_size=batch_size, patience=patience, epochs=epochs, regularizer=None, pretrain_method='stacked', decay=decay, verbose=verbose ) self.k = k self.tol = tol def fit(self, data): super().fit(data) data = self.data_transform(data) clustering_layer = ClusteringLayer( self.k, name='clustering')(self.encoder.output) if self.verbose: print('Initializing cluster centers') kmeans = KMeans(n_clusters=self.k, n_init=20) y_pred = kmeans.fit_predict(self.encoder.predict(data)) self.clustering_model = Model(inputs=self.encoder.input, outputs=clustering_layer) self.clustering_model.get_layer(name='clustering').set_weights( [kmeans.cluster_centers_]) self.clustering_model.compile( optimizer=Adam(self.lr, decay=self.lr / self.epochs), loss='kld' ) sequence = DECSequence(data, self.clustering_model, self.batch_size) early_stopping = EarlyStopping(monitor='loss', patience=self.patience) if self.verbose: print('Clustering optimization') self.clustering_model.fit_generator( sequence, math.ceil(data.shape[0] / self.batch_size), epochs=self.epochs, callbacks=[early_stopping], verbose=self.verbose ) def soft_cluster_assignments(self, data): """Get the soft cluster assignments of the clustering layer of the DEC network for the input data. Parameters ---------- data : array The input data Returns ------- array of cluster assignments """ return np.apply_along_axis( np.argmax, 1, self.clustering_model.predict(data) )
Ancestors
Methods
def soft_cluster_assignments(self, data)
-
Get the soft cluster assignments of the clustering layer of the DEC network for the input data.
Parameters
data
:array
- The input data
Returns
array
ofcluster
assignments
Source code
def soft_cluster_assignments(self, data): """Get the soft cluster assignments of the clustering layer of the DEC network for the input data. Parameters ---------- data : array The input data Returns ------- array of cluster assignments """ return np.apply_along_axis( np.argmax, 1, self.clustering_model.predict(data) )
Inherited members
class DeepCluster (in_dim, out_dim, k, layer_sizes=[2000, 1000, 500], lr=0.01, scale=True, log=False, batch_size=100, patience=3, epochs=1000, regularizer='kmeans', regularizer_weight=0.5, decay=True, verbose=0)
-
DeepCluster model
References
- Kai Tian, Shuigeng Zhou, and Jihong Guan. Deepcluster: A general clustering framework based on deep learning. In Michelangelo Ceci, Jaakko Hollmén, Ljupčo Todorovski, Celine Vens, and Sašo Džeroski, editors, Machine Learning and Knowledge Discovery in Databases, pages 809–825, Cham, 2017. Springer International Publishing.
Source code
class DeepCluster(Autoencoder): """ DeepCluster model References ---------- * Kai Tian, Shuigeng Zhou, and Jihong Guan. Deepcluster: A general clustering framework based on deep learning. In Michelangelo Ceci, Jaakko Hollmén, Ljupčo Todorovski, Celine Vens, and Sašo Džeroski, editors, *Machine Learning and Knowledge Discovery in Databases*, pages 809–825, Cham, 2017. Springer International Publishing. """ def __init__( self, in_dim, out_dim, k, layer_sizes=[2000, 1000, 500], lr=0.01, scale=True, log=False, batch_size=100, patience=3, epochs=1000, regularizer='kmeans', regularizer_weight=0.5, decay=True, verbose=0 ): if regularizer == 'kmeans': regularizer_obj = KMeansRegularizer( np.random.rand(k, out_dim), weight=regularizer_weight) elif regularizer == 'gmm': # TODO add gmm cluster regularizer regularizer_obj = None else: raise AttributeError super().__init__( in_dim, out_dim, layer_sizes=layer_sizes, lr=lr, scale=scale, log=log, batch_size=batch_size, patience=patience, epochs=epochs, regularizer=regularizer_obj, pretrain_method=None, decay=decay, verbose=verbose ) def get_cluster_centers(self): """Get the cluster centers generated by the last fit operation. Returns: -------- Array of cluster centers """ return self.regularizer.cluster_centers def get_cluster_assignments(self): """Get the cluster assignments for the data of the last fit operation Returns: -------- Array of cluster assignments """ return self.regularizer.cluster_assignments
Ancestors
Methods
def get_cluster_assignments(self)
-
Get the cluster assignments for the data of the last fit operation
Returns:
Array of cluster assignments
Source code
def get_cluster_assignments(self): """Get the cluster assignments for the data of the last fit operation Returns: -------- Array of cluster assignments """ return self.regularizer.cluster_assignments
def get_cluster_centers(self)
-
Get the cluster centers generated by the last fit operation.
Returns:
Array of cluster centers
Source code
def get_cluster_centers(self): """Get the cluster centers generated by the last fit operation. Returns: -------- Array of cluster centers """ return self.regularizer.cluster_centers
Inherited members
class ParametricTSNE (in_dim, out_dim, layer_sizes=[500, 500, 2000], lr=0.01, log=False, scale=True, batch_size=100, pretrain=False, perplexity=30, tol=1e-05, patience=3, epochs=1000, decay=True, verbose=0)
-
Implementation of the parametric variant of t-distributed neighborhood embedding.
Parameters
in_dim
:int
- The input dimension
out_dim
:int
- The output dimension
layer_sizes
:array
, optional- sizes of each layer in the neural network, default is the structure
proposed in the original paper, namely:
[500, 2000, 2000]
lr
:float
, optional- The learning rate of the network, default
0.01
log
:boolean
, optional- Whether log-transformation should be performed, default
False
scale
:boolean
, optional- Whether scaling (making values within [0,1]) should be performed,
default
True
batch_size
:int
, optional- The batch size of the network, default
100
pretrain
:int
, optional- Whether to perform pretraining using Restricted Boltzmann Machines,
default
False
perplexity
:int
, optional- Perplexity parameter in the t-SNE formula, controls how many neighbors
are considered in the local neighborhood, default
30
tol
:float
, optional- Tolerance of the perplexity, default
1e-5
patience
:int
, optional- The amount of epochs without improvement before fitting will stop
early, default
3
epochs
:int
, optional- Maximum amount of epochs, default
1000
decay
:bool
, optional- Whether to decay the learning rate during training, default
True
. verbose
:int
, optional- Controls the verbosity of the model, default
0
Attributes
model
:keras
Sequential
model
- The neural network
layers
:keras
layers
- The layers of the neural network
data_transform
:Transform
object
- The transformation to apply on data before using it
References
- Laurens van der Maaten. Learning a parametric embedding by preserving local structure. In David van Dyk and Max Welling, editors, Proceedings of the Twelth International Conference on Artificial Intelligence and Statistics, volume 5 of Proceedings of Machine Learning Research, pages 384–391, Hilton Clearwater Beach Resort, Clearwater Beach, Florida USA, 16–18 Apr 2009. PMLR.
Source code
class ParametricTSNE: """ Implementation of the parametric variant of t-distributed neighborhood embedding. Parameters ---------- in_dim : int The input dimension out_dim : int The output dimension layer_sizes : array, optional sizes of each layer in the neural network, default is the structure proposed in the original paper, namely: `[500, 2000, 2000]` lr : float, optional The learning rate of the network, default `0.01` log : boolean, optional Whether log-transformation should be performed, default `False` scale : boolean, optional Whether scaling (making values within [0,1]) should be performed, default `True` batch_size : int, optional The batch size of the network, default `100` pretrain : int, optional Whether to perform pretraining using Restricted Boltzmann Machines, default `False` perplexity : int, optional Perplexity parameter in the t-SNE formula, controls how many neighbors are considered in the local neighborhood, default `30` tol : float, optional Tolerance of the perplexity, default `1e-5` patience : int, optional The amount of epochs without improvement before fitting will stop early, default `3` epochs : int, optional Maximum amount of epochs, default `1000` decay : bool, optional Whether to decay the learning rate during training, default `True`. verbose : int, optional Controls the verbosity of the model, default `0` Attributes ---------- model : keras Sequential model The neural network layers : keras layers The layers of the neural network data_transform : Transform object The transformation to apply on data before using it References ---------- - Laurens van der Maaten. Learning a parametric embedding by preserving local structure. In David van Dyk and Max Welling, editors, *Proceedings of the Twelth International Conference on Artificial Intelligence and Statistics*, volume 5 of *Proceedings of Machine Learning Research*, pages 384–391, Hilton Clearwater Beach Resort, Clearwater Beach, Florida USA, 16–18 Apr 2009. PMLR. """ def __init__( self, in_dim, out_dim, layer_sizes=[500, 500, 2000], lr=0.01, log=False, scale=True, batch_size=100, pretrain=False, perplexity=30, tol=1e-5, patience=3, epochs=1000, decay=True, verbose=0): self.in_dim = in_dim self.out_dim = out_dim self.layer_sizes = layer_sizes self.lr = lr self.data_transform = Transform(scale, log) self.batch_size = batch_size self.pretrain = pretrain self.perplexity = perplexity self.tol = tol self.patience = patience self.epochs = epochs self.verbose = verbose self.decay = decay self.__init_network() def __init_network(self): if self.pretrain: self.rbms = [BernoulliRBM( batch_size=self.batch_size, learning_rate=self.lr, n_components=num, n_iter=20, verbose=self.verbose ) for num in self.layer_sizes + [self.out_dim]] activation = 'sigmoid' else: activation = 'relu' self.layers = [] for i, num in enumerate(self.layer_sizes): if i == 0: self.layers.append(Dense( num, activation=activation, input_shape=(self.in_dim,) )) else: self.layers.append(Dense(num, activation=activation)) self.layers.append(Dense(self.out_dim)) self.model = Sequential(self.layers) optimizer = SGD(lr=self.lr, decay=self.lr / self.epochs if self.decay else 0.0) loss = TSNELoss(self.in_dim, self.batch_size) self.model.compile( optimizer=optimizer, loss=loss ) if self.verbose: self.model.summary() def __pretrain(self, data): current = data for i, rbm in enumerate(self.rbms): if self.verbose: print('Training RBM {}/{}'.format(i + 1, len(self.rbms))) rbm.fit(current) current = rbm.transform(current) self.layers[i].set_weights( [np.transpose(rbm.components_), rbm.intercept_hidden_]) def fit(self, data): """ Fit the given data to the model. Parameters ---------- data : array Array of training samples where each sample is of size `in_dim` """ # make data length be a multiple of batch size data = data[:(data.shape[0] // self.batch_size) * self.batch_size] data = self.data_transform(data) if self.pretrain: if self.verbose: print('Pretraining network') self.__pretrain(data) early_stopping = EarlyStopping(monitor='loss', patience=self.patience) P = compute_joint_probabilities( data, batch_size=self.batch_size, d=self.out_dim, perplexity=self.perplexity, tol=self.tol, verbose=self.verbose ) y_train = P.reshape(data.shape[0], -1) self.model.fit( data, y_train, epochs=self.epochs, callbacks=[early_stopping], batch_size=self.batch_size, shuffle=False, verbose=self.verbose ) def transform(self, data): """ Transform the given data Parameters ---------- data : array Array of samples to be transformed, where each sample is of size `in_dim` Returns ------- array Transformed samples, where each sample is of size `out_dim` """ data = self.data_transform(data) return self.model.predict(data, verbose=self.verbose) def fit_transform(self, data): """ Fit the given data to the model and return its transformation Parameters ---------- data : array Array of training samples where each sample is of size `in_dim` Returns ------- array Transformed samples, where each sample is of size `out_dim` """ self.fit(data) return self.transform(data)
Methods
def fit(self, data)
-
Fit the given data to the model.
Parameters
data
:array
- Array of training samples where each sample is of size
in_dim
Source code
def fit(self, data): """ Fit the given data to the model. Parameters ---------- data : array Array of training samples where each sample is of size `in_dim` """ # make data length be a multiple of batch size data = data[:(data.shape[0] // self.batch_size) * self.batch_size] data = self.data_transform(data) if self.pretrain: if self.verbose: print('Pretraining network') self.__pretrain(data) early_stopping = EarlyStopping(monitor='loss', patience=self.patience) P = compute_joint_probabilities( data, batch_size=self.batch_size, d=self.out_dim, perplexity=self.perplexity, tol=self.tol, verbose=self.verbose ) y_train = P.reshape(data.shape[0], -1) self.model.fit( data, y_train, epochs=self.epochs, callbacks=[early_stopping], batch_size=self.batch_size, shuffle=False, verbose=self.verbose )
def fit_transform(self, data)
-
Fit the given data to the model and return its transformation
Parameters
data
:array
- Array of training samples where each sample is of size
in_dim
Returns
array
- Transformed samples, where each sample is of size
out_dim
Source code
def fit_transform(self, data): """ Fit the given data to the model and return its transformation Parameters ---------- data : array Array of training samples where each sample is of size `in_dim` Returns ------- array Transformed samples, where each sample is of size `out_dim` """ self.fit(data) return self.transform(data)
def transform(self, data)
-
Transform the given data
Parameters
data
:array
- Array of samples to be transformed, where each sample is of size
in_dim
Returns
array
- Transformed samples, where each sample is of size
out_dim
Source code
def transform(self, data): """ Transform the given data Parameters ---------- data : array Array of samples to be transformed, where each sample is of size `in_dim` Returns ------- array Transformed samples, where each sample is of size `out_dim` """ data = self.data_transform(data) return self.model.predict(data, verbose=self.verbose)
class VASC (in_dim, out_dim, layer_sizes=[512, 128, 32], epochs=1000, patience=3, batch_size=100, lr=0.01, var=False, log=False, scale=True, decay=True, verbose=0)
-
VASC: variational autoencoder for scRNA-seq datasets
Parameters
in_dim
:int
- The input dimension
out_dim
:int
- The output dimension
layer_sizes
:array
- sizes of each layer in the neural network, default is the structure
proposed in the original paper, namely:
[512, 128, 32]
epochs
:int
, optional- Maximum number of epochs, default
5000
patience
:int
, optional- The amount of epochs without improvement before the network stops
training, default
3
batch_size
:int
, optional- The batch size for stochastic optimization, default
100
lr
:float
, optional- The learning rate of the network, default
0.01
var
:boolean
, optional- Whether to estimate the variance parameters, default
False
log
:boolean
, optional- Whether log-transformation should be performed, default
False
scale
:boolean
, optional- Whether scaling (making values within [0,1]) should be performed,
default
True
decay
:bool
, optional- Whether to decay the learning rate during training, default
True
. verbose
:int
, optional- Controls the verbosity of the model, default
0
Attributes
ae
:keras
model
- Partial model used for generating the embbeddings
vae
:keras
model
- The variational autoencoder
References
- Dongfang Wang and Jin Gu. Vasc: dimension reduction and visualization of single cell rna sequencing data by deep variational autoencoder. bioRxiv, 2017.
Source code
class VASC: """ VASC: variational autoencoder for scRNA-seq datasets Parameters ---------- in_dim : int The input dimension out_dim : int The output dimension layer_sizes : array sizes of each layer in the neural network, default is the structure proposed in the original paper, namely: `[512, 128, 32]` epochs: int, optional Maximum number of epochs, default `5000` patience: int, optional The amount of epochs without improvement before the network stops training, default `3` batch_size: int, optional The batch size for stochastic optimization, default `100` lr : float, optional The learning rate of the network, default `0.01` var: boolean, optional Whether to estimate the variance parameters, default `False` log: boolean, optional Whether log-transformation should be performed, default `False` scale: boolean, optional Whether scaling (making values within [0,1]) should be performed, default `True` decay : bool, optional Whether to decay the learning rate during training, default `True`. verbose : int, optional Controls the verbosity of the model, default `0` Attributes ---------- ae : keras model Partial model used for generating the embbeddings vae : keras model The variational autoencoder References ---------- * Dongfang Wang and Jin Gu. Vasc: dimension reduction and visualization of single cell rna sequencing data by deep variational autoencoder. *bioRxiv*, 2017. """ def __init__( self, in_dim, out_dim, layer_sizes=[512, 128, 32], epochs=1000, patience=3, batch_size=100, lr=0.01, var=False, log=False, scale=True, decay=True, verbose=0): self.in_dim = in_dim self.out_dim = out_dim self.layer_sizes = layer_sizes self.epochs = epochs self.patience = patience self.batch_size = batch_size self.lr = lr self.var = var self.data_transform = Transform(scale, log) self.verbose = verbose self.decay = decay self.__init_network() def __init_network(self): in_dim = self.in_dim expr_in = Input(shape=(self.in_dim,)) # The first part of model to recover the expr. h0 = Dropout(0.5)(expr_in) # Encoder layers last_layer = h0 for i, layer_size in enumerate(self.layer_sizes): if i == 0: last_layer = Dense( units=layer_size, name='encoder_{}'.format(i + 1), kernel_regularizer=regularizers.l1(0.01) )(last_layer) else: last_layer = Dense( units=layer_size, name='encoder_{}'.format(i + 1) )(last_layer) last_layer = Activation('relu')(last_layer) z_mean = Dense(units=self.out_dim, name='z_mean')(last_layer) z_log_var = None if self.var: z_log_var = Dense(units=2, name='z_log_var')(last_layer) z_log_var = Activation('softplus')(z_log_var) # sampling new samples z = Lambda(sampling, output_shape=( self.out_dim,))([z_mean, z_log_var]) else: z = Lambda(sampling, output_shape=(self.out_dim,))([z_mean]) # Decoder layers last_layer = z for i, layer_size in enumerate(self.layer_sizes[::-1]): last_layer = Dense( units=layer_size, name='decoder_{}'.format(i + 1))(last_layer) last_layer = Activation('relu')(last_layer) expr_x = Dense(units=self.in_dim, activation='sigmoid')( last_layer) expr_x_drop = Lambda(lambda x: -x ** 2)(expr_x) expr_x_drop_p = Lambda(lambda x: K.exp(x))(expr_x_drop) expr_x_nondrop_p = Lambda(lambda x: 1-x)(expr_x_drop_p) expr_x_nondrop_log = Lambda(lambda x: K.log(x+1e-20))(expr_x_nondrop_p) expr_x_drop_log = Lambda(lambda x: K.log(x+1e-20))(expr_x_drop_p) expr_x_drop_log = Reshape(target_shape=( self.in_dim, 1))(expr_x_drop_log) expr_x_nondrop_log = Reshape(target_shape=( self.in_dim, 1))(expr_x_nondrop_log) logits = concatenate( [expr_x_drop_log, expr_x_nondrop_log], axis=-1) temp_in = Input(shape=(self.in_dim,)) temp_ = RepeatVector(2)(temp_in) temp_ = Permute((2, 1))(temp_) samples = Lambda(gumbel_softmax, output_shape=( self.in_dim, 2,))([logits, temp_]) samples = Lambda(lambda x: x[:, :, 1])(samples) samples = Reshape(target_shape=(self.in_dim,))(samples) out = multiply([expr_x, samples]) vae = Model(inputs=[expr_in, temp_in], outputs=out) loss_func = VAELoss(in_dim, z_log_var, z_mean) opt = RMSprop(lr=self.lr, decay=self.lr / self.epochs if self.decay else 0.0) vae.compile(optimizer=opt, loss=loss_func) ae = Model(inputs=[expr_in, temp_in], outputs=[ z_mean, z, samples, out]) self.vae = vae self.ae = ae if self.verbose: self.vae.summary() def fit(self, data): """ Fit the given data to the model. Parameters ---------- data : array Array of training samples where each sample is of size `in_dim` """ data = self.data_transform(data) tau_in = np.ones(data.shape, dtype='float32') early_stopping = EarlyStopping(monitor='loss', patience=self.patience) self.vae.fit( [data, tau_in], data, epochs=self.epochs, batch_size=self.batch_size, shuffle=True, verbose=self.verbose, callbacks=[early_stopping] ) def fit_transform(self, data): """ Fit the given data to the model and return its transformation Parameters ---------- data : array Array of training samples where each sample is of size `in_dim` Returns ------- array Transformed samples, where each sample is of size `out_dim` """ self.fit(data) return self.transform(data) def transform(self, data): """ Transform the given data Parameters ---------- data : array Array of samples to be transformed, where each sample is of size `in_dim` Returns ------- array Transformed samples, where each sample is of size `out_dim` """ data = self.data_transform(data) return self.ae.predict([data, np.ones(data.shape, dtype='float32')])[0]
Methods
def fit(self, data)
-
Fit the given data to the model.
Parameters
data
:array
- Array of training samples where each sample is of size
in_dim
Source code
def fit(self, data): """ Fit the given data to the model. Parameters ---------- data : array Array of training samples where each sample is of size `in_dim` """ data = self.data_transform(data) tau_in = np.ones(data.shape, dtype='float32') early_stopping = EarlyStopping(monitor='loss', patience=self.patience) self.vae.fit( [data, tau_in], data, epochs=self.epochs, batch_size=self.batch_size, shuffle=True, verbose=self.verbose, callbacks=[early_stopping] )
def fit_transform(self, data)
-
Fit the given data to the model and return its transformation
Parameters
data
:array
- Array of training samples where each sample is of size
in_dim
Returns
array
- Transformed samples, where each sample is of size
out_dim
Source code
def fit_transform(self, data): """ Fit the given data to the model and return its transformation Parameters ---------- data : array Array of training samples where each sample is of size `in_dim` Returns ------- array Transformed samples, where each sample is of size `out_dim` """ self.fit(data) return self.transform(data)
def transform(self, data)
-
Transform the given data
Parameters
data
:array
- Array of samples to be transformed, where each sample is of size
in_dim
Returns
array
- Transformed samples, where each sample is of size
out_dim
Source code
def transform(self, data): """ Transform the given data Parameters ---------- data : array Array of samples to be transformed, where each sample is of size `in_dim` Returns ------- array Transformed samples, where each sample is of size `out_dim` """ data = self.data_transform(data) return self.ae.predict([data, np.ones(data.shape, dtype='float32')])[0]