import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
# Cosine similarity
def cos_sim(a, b):
numerator = np.multiply(a, b).sum()
denomitor = np.linalg.norm(a) * np.linalg.norm(b)
if denomitor == 0:
return 0
else:
return numerator / denomitor
# Data matrix Two classification problems -------> X dim=3
X = np.array([
[1, 1, 2],
[1, 2, 2],
[3, 2, 1],
[-1, 1, 1],
[-2, 1, 1],
[-1, 2, 2],
[1, -1, 2],
[2, -1, 3],
[1, -1, 1]
])
# Label matrix Two classification problems -------> Y
y = np.array([0, 0, 0, 1, 1, 1, 2, 2, 2])
# Find the representative vector of each label. method = mean()
zero_X = np.mean(np.array(X[0:3, :]), axis = 0) # label----> 0
one_X = np.mean(np.array(X[3:6, :]), axis = 0) # label----> 1
two_X = np.mean(np.array(X[6:, :]), axis = 0) # label----> 2
# Data dimensionality reduction using variational self encoder
def loss_function(recon_x, x, mu, logvar):
"""
:param recon_x: generated image
:param x: original image
:param mu: latent mean of z
:param logvar: latent log variance of z
"""
MSELoss = nn.MSELoss()
reconstruction_loss = MSELoss(recon_x, x)
#KL_divergence = -0.5 * torch.sum(1+logvar-torch.exp(logvar)-mu**2)
KLD_ele = mu.pow(2).add_(logvar.exp()).mul_(-1).add_(1).add_(logvar)
KLD = torch.sum(KLD_ele).mul_(-0.5)
#print(reconstruction_loss.data, KLD.data)
return reconstruction_loss + KLD
class VAE(nn.Module):
def __init__(self):
super(VAE, self).__init__()
self.fc1 = nn.Linear(3, 4)
self.fc2_mean = nn.Linear(4, 2)
self.fc2_logvar = nn.Linear(4, 2)
self.fc3 = nn.Linear(2, 4)
self.fc4 = nn.Linear(4, 3)
def encode(self, x):
h1 = F.relu(self.fc1(x))
return self.fc2_mean(h1), self.fc2_logvar(h1)
def reparametrization(self, mu, logvar):
# sigma = 0.5*exp(log(sigma^2))= 0.5*exp(log(var))
std = 0.5 * torch.exp(logvar)
# N(mu, std^2) = N(0, 1) * std + mu
z = torch.randn(std.size()) * std + mu
return z
def decode(self, z):
h3 = F.relu(self.fc3(z))
return torch.sigmoid(self.fc4(h3))
def forward(self, x):
mu, logvar = self.encode(x)
z = self.reparametrization(mu, logvar)
return z, self.decode(z), mu, logvar
vae = VAE()
optimizer = torch.optim.Adam(vae.parameters(), lr=0.001)
all_loss = 0
X = torch.tensor(X).float()
y = torch.tensor(y)
for i in range(5000):
inputs, targets = X, y
real_data = X
# Train Discriminator
_, gen_data, mu, logvar = vae(real_data)
loss = loss_function(gen_data, real_data, mu, logvar)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print('Epoch {}, loss: {:.6f}'.format(i, loss.data))
# Take out the data after dimension reduction
z, _, _, _ = vae(X)
print(z)
print(z.shape)
z = z.detach().numpy()
# Find the representative vector of each label. method = mean()
zero_z = np.mean(np.array(z[0:3, :]), axis = 0) # label----> 0
one_z = np.mean(np.array(z[3:6, :]), axis = 0) # label----> 1
two_z = np.mean(np.array(z[6:, :]), axis = 0) # label----> 2
# Match with cosine formula ----->test
k = torch.tensor([
[1, 2, 8],
[-1, 0.1, 0.5],
[1, -1, 5]
]).float()
k_z, _, _, _ = vae(k)
k_z = k_z.detach().numpy()
score = []
for i in range(k.shape[0]):
score.append(abs(cos_sim(k_z[i], z[i])))
print(score)