Closed DiogenesAnalytics closed 11 months ago
Need to identify what are the parts that all autoencoders have in common (i.e. the intersection of all the autoencoder implementations).
layers
: autoencoder models possess 3 groups of layers: input
, encode
, and decode
layers.train
: must undergo training (in Keras
the fit()
method is used).predict
: the trained model is then used to predict given a target input.latent visualize
: the encoded layer (post training) can be used to visaulize the lower-dimensional data.predict visualize
: the predict()
method benefits from visual comparison between target/predict.loss visualize
: the training loss can be plotted and is invaluable to assessing model quality.Continuing from the previous comment, what are the common data attributes (i.e. class / instance variables) common between the different autoencoder implementation strategies?
input size
: the size (array length) of input to be fed to the input layer
.encoding dimension
: the size of the encoded representation (i.e. the encoded layer
).output size
: the size (array length) of the output decoded layer
(matches input size
).Asked ChatGPT
to build an Abstract Base Class for autoencoders.
"Can you build an abstract base class for autoencoders in Python 3?"
"Certainly! An abstract base class (ABC) in Python can be created using the ABC module from the abc package. Here's an example of how you might create an abstract base class for autoencoders in Python 3:"
from abc import ABC, abstractmethod
class Autoencoder(ABC):
def __init__(self):
super().__init__()
@abstractmethod
def encode(self, input_data):
"""
Encode input_data into a compressed representation.
Parameters:
- input_data: Input data to be encoded.
Returns:
Compressed representation of input_data.
"""
pass
@abstractmethod
def decode(self, encoded_data):
"""
Decode the encoded_data into its original form.
Parameters:
- encoded_data: Compressed representation to be decoded.
Returns:
Decoded version of the encoded_data.
"""
pass
@abstractmethod
def train(self, input_data):
"""
Train the autoencoder using the input_data.
Parameters:
- input_data: Training data for the autoencoder.
"""
pass
@abstractmethod
def save(self, model_path):
"""
Save the trained model to a file.
Parameters:
- model_path: Path where the model should be saved.
"""
pass
@abstractmethod
def load(self, model_path):
"""
Load a pre-trained model from a file.
Parameters:
- model_path: Path from where the model should be loaded.
"""
pass
"In this example, Autoencoder is an abstract base class with abstract methods encode, decode, train, save, and load. You would then create concrete classes that inherit from this base class and implement these methods according to the specific autoencoder architecture you are working with. For example, a denoising autoencoder, variational autoencoder, etc., would be different concrete classes that implement these methods in their own way."
Some problem points in generalizing the autencoder abstract base class.
While the more simple autoencoders only utilize the encoding_dimension to build their internal model layers, more complex architectures (e.g. convolutional autoencoders) introduce other dimensions to build their layers (e.g. kernel_size, stride, etc ...).^1 This makes the generalization process more challenging ... but there are some strategies for dealing with this.^2^4
"Regrettably, if the encoder and decoder are allowed too much capacity, this AE will fail to learn anything useful other than the ability to copy its input to its output ... In summary, using comparisons of the size of the hidden layer and the input layer, the basic AE structure can be divided into two categories: the narrow AE and wide AE (also known as under- complete and over-complete, respectively)."
^5
"Since in training, one may just get the identity operator for ๐ด and ๐ต, which keeps the achieved representation the same as the input, some additional regularization is required. The most common option is to make the dimension of the representation smaller than the input. This way, a ๐๐๐ก๐ก๐๐๐๐๐๐ is imposed. This option also directly serves the goal of getting a low dimensional representation of the data. This repre- sentation can be used for purposes such as data compression, feature extraction, etc."
^6
Upon studying the various autoencoder libraries and implementations in the above comment it is becoming more clear that there are fundamental types that rule ALL autoencoders.^1 Here these types will be explored/developed.
Here is the list:
Variational
^2Convolutional
^4Recurrent
^4Deep
: also known as fully connected
^4Minimal
: also known as vanilla
^1Sparse
^4Denoising
^4Contractive
^4An example of a concrete class that inherits from BaseAutoEncoder
.
"""A simple autoencoder to get you started."""
from dataclasses import dataclass
from typing import Any
from typing import ClassVar
from typing import Dict
from typing import Optional
from keras import layers
from .base import BaseAutoencoder
from .base import BaseLayerParams
from .base import DefaultParams
@dataclass
class MinimalLayerParams(BaseLayerParams):
"""Layer parameters class for minimal autoencoder."""
# setup default values
default_parameters: ClassVar[DefaultParams] = {
"l0": (layers.InputLayer, {"input_shape": (784,)}),
"l1": (layers.Dense, {"units": 32, "activation": "relu"}),
"l2": (layers.Dense, {"units": 784, "activation": "sigmoid"}),
}
# setup instance layer params
l0: Optional[Dict[str, Any]] = None
l1: Optional[Dict[str, Any]] = None
l2: Optional[Dict[str, Any]] = None
class MinimalAutoencoder(BaseAutoencoder):
"""A simple autoencoder to get you started."""
_default_config = MinimalLayerParams()
def __init__(self, model_config: Optional[MinimalLayerParams] = None) -> None:
"""Overrided base constructor to set the layer params class used."""
# call super
super().__init__(model_config=model_config)
Some issues working with keras.Sequential
...
Need to design an intelligent way to take the layer/parameters combos and not only combine them into a keras.Model
(i.e. probably using keras.Sequential
but also create specific "sub" models for the encoder and decoder.
Implemented with: 338fb8ca44e40c914f9701cf74e4690338935e24
Problem
Need to devise the initial approach to designing the class hierarchy for
autoencoder
.Solution
Tentative pseudo code for what the class hierarchy might look like (including any methods/attributes):
References