I am trying to build an intuition on what really a feature is. I created a toy example as following. In my mind a scalar feature should be enough to represent my data. Couldn't the model in this case learn a mapping from binary numbers to decimal? For example, the scalar feature for [0,0,0] = 0, [0,0,1] = 1, [0,1,0] = 2 etc. I know feature space is continuous but I could draw the same assumption for continuous feature values. I.e, [0,0,0] belongs to the [-0.5, 0.5) feature space range, [0,0,1] to [0.5, 1.5) etc.
In my example, the autoencoder predicts [0,0,0] for every input? Is my intuition just wrong about the meaning of features? If so, how would you explain it?
import torch
import torch.utils.data
from torch import nn
import tqdm
# This autoencoder has only one feature as latent space
class AE(nn.Module):
def __init__(self):
super().__init__()
self.encoder = nn.Sequential(nn.Linear(3, 1, bias=False), nn.ReLU())
self.decoder = nn.Sequential(nn.Linear(1, 3, bias=False), nn.ReLU())
def forward(self, x):
z = self.encoder(x)
xhat = self.decoder(z)
return xhat
class dummyData(torch.utils.data.Dataset):
def __init__(self):
self.samples = [[0, 0, 0],
[0, 0, 1],
[0, 1, 0],
[0, 1, 1],
[1, 0, 0],
[1, 0, 1],
[1, 1, 0],
[1, 1, 1]]
def __getitem__(self, item):
return torch.tensor(self.samples[item]).type(torch.float32)
def __len__(self):
return len(self.samples)
autoencoder = AE()
optimizer = torch.optim.Adam(autoencoder.parameters())
dummyDataset = dummyData()
dataloader = torch.utils.data.DataLoader(dummyDataset, batch_size=2, shuffle=False)
criterion = nn.MSELoss()
for epoch in tqdm.tqdm(range(10000)):
for sample in dataloader:
pred = autoencoder(sample)
loss = criterion(pred, sample)
loss.backward()
optimizer.step()
optimizer.zero_grad()
print("TEST")
autoencoder.eval()
print(autoencoder.encoder(torch.tensor([0., 0., 0.])))
print(autoencoder(torch.tensor([0., 0., 0.])))
print(autoencoder.encoder(torch.tensor([0., 0., 1.])))
print(autoencoder(torch.tensor([0., 0., 1.])))
print(autoencoder.encoder(torch.tensor([0., 1., 1.])))
print(autoencoder(torch.tensor([0., 1., 1.])))
print(autoencoder.encoder(torch.tensor([1., 0., 0.])))
print(autoencoder(torch.tensor([1., 0., 0.])))
´´´