Autoencoders for Sparse dataset

hsekol-hub: <p>Hello,</p>
<p>Goal is to perform a dimensionality reduction without loss of information. This post is relating to autoencoders and its ability to reconstruct a sparse dataset.</p>
<p><strong>Input:</strong> is a 2D tensor (N, 512) where 512 is a frequency vector with discrete values only.<br>
Example: [[3, 0, 1, 0, 45, 0,………, 0, 0, 0, 2][……]]</p>
<p><strong>Expected output</strong> is a 2D tensor (N, 512) as close as possible to input (but only discrete)</p>
<p><strong>Loss functions used:</strong></p>
<ul>
<li>MSELoss</li>
<li>MSELoss + CosineEmbeddingLoss</li>
<li>L1 regularization</li>
<li>MSELoss + KL Divergence (from the theory of sparse autoencoders)</li>
</ul>
<p>Note:</p>
<ol>
<li>Dataset is highly sparse.</li>
<li>Latent dimension is 32</li>
<li>With all the above loss functions and different architectures the autoencoder’s training and validation loss values always decreases. Thus, based on these metrics it looks like the enoder and decoder is working fine.</li>
</ol>
<pre><code class="lang-auto">class SparseAutoEncoder(nn.Module):

    def __init__(self, original_dim: int, latent_dim: int):
        super(SparseAutoEncoder, self).__init__()
        self.enc1 = nn.Linear(in_features=original_dim, out_features=original_dim//2)
        self.enc2 = nn.Linear(in_features=original_dim//2, out_features=original_dim//4)
        self.enc3 = nn.Linear(in_features=original_dim//4, out_features=latent_dim)
        self.dec1 = nn.Linear(in_features=latent_dim, out_features=original_dim//4)
        self.dec2 = nn.Linear(in_features=original_dim//4, out_features=original_dim//2)
        self.dec3 = nn.Linear(in_features=original_dim//2, out_features=original_dim)


    def forward(self, x):

        x = F.relu(self.enc1(x))
        x = F.relu(self.enc2(x))
        encoded = F.relu(self.enc3(x))
        x = F.relu(self.dec1(encoded))
        x = F.relu(self.dec2(x))
        decoded = F.relu(self.dec3(x))
        return encoded, decoded
</code></pre>
<p>However, for qualitative analysis plotting is not the option (unlike in images) I take the absolute difference of these two tensors (np.abs(X - X_prime)) and compute the number of non-zero entries for each training sample. This is where the fault is observed: the autoenconder is partially able to reconstruct the input frequency vectors.</p>
<p><strong>Example:</strong><br>
If original vector is: X = [3, 1, 1, 1, 2] at non-zero indices = [0, 22, 26, 256, 264] and all other indices are 0. Such that len(X) is always 512.</p>
<p>The reconstructed vector is:  X _prime = [3, 0, 0, 1, 0] for indices [0, 22, 26, 256, 264] and all other indices 0. Such that len(X_prime) is also 512.</p>
<p>So, we have 5 non-zero entries in the original vector and the goal is to capture them as precise as possible and the autoencoder fails to achieve this. Similar pattern is observed for all the N samples where around ~50% of non-zero entries are correct.</p>
<p><strong>My questions would be:</strong></p>
<ol>
<li>Is autoencoder a right architecture to capture this kind of discrete input data?</li>
<li>Do I need to use some other loss function?  (A mean square error will always be low because most of the entries are 0 and the model correctly predicts the 0’s. It only fails to predict non-zero values (which are very few).</li>
<li>What other methods could be tried to perform this task of dimensionality reduction? Will PCA also face the same issue !</li>
</ol>
<p>Thanks for your help and suggestions <img src="https://discuss.pytorch.org/images/emoji/apple/grinning.png?v=10" title=":grinning:" class="emoji" alt=":grinning:"></p>
<p>Best,<br>
Sharma</p>