Module dimdrop.models.param_tsne
Source code
from keras.layers import Dense
from keras.models import Sequential
from keras.optimizers import SGD
from keras.callbacks import EarlyStopping
from sklearn.neural_network import BernoulliRBM
import numpy as np
from ..losses import TSNELoss
from ..util.tsne import compute_joint_probabilities
from ..util import Transform
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)
Classes
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)