import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
import torch
import torchvision
#from skleran.neural_network import MLPRegressor
torch.manual_seed(0)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)

# Leemos los datos
D = np.genfromtxt( "creditcard.csv", delimiter=',', skip_header=1, usecols=(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30), dtype=np.float32)
print( D.shape )

# De 0 a 27 son las características

rows=np.where( D[:,29]==0)
normales = D[rows]
A = StandardScaler().fit_transform( normales[:,28].reshape(-1,1) )
print(A.shape)
normales[:,28] = A[:,0]
print( "Normales:",  normales.shape )
#print( normales.shape )

#X_entrena, X_prueba = train_test_split(normales[:,0:29], test_size=0.2, random_state=42)
#print(X_entrena.shape)

#Datos_tensor = torch.from_numpy(X_entrena)
#Datos_tensor = Datos_tensor.to(device)

Datos_tensor_prueba = torch.from_numpy(normales)
Datos_tensor_prueba = Datos_tensor_prueba.to(device)

# Capa de entrada: 29 
# Capa oculta:     20 
# Capa salida:     14

class AE(torch.nn.Module):
    def __init__(self):
        super().__init__()
         
       
        self.encoder = torch.nn.Sequential(
            torch.nn.Linear(29, 20),
            torch.nn.Tanh(),
            torch.nn.Linear(20, 14),
            torch.nn.ReLU(),
        )
         
        self.decoder = torch.nn.Sequential(
            torch.nn.Linear(14, 20),
            torch.nn.Tanh(),
            torch.nn.Linear(20, 29),
            torch.nn.Tanh()
        )
 
    def forward(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return decoded


model = AE()

# model.load_state_dict(torch.load("Adam1270.pt", map_location=torch.device('cpu')))
model.load_state_dict(torch.load("adam00.pth", map_location=torch.device('cpu')))
model.to(device)

model.eval()
k = Datos_tensor_prueba.shape[0]
print( "Datos de prueba:", k )
error = 0
#for i in range(Datos_tensor_prueba.shape[0]):
for i in range(k):
    output = model(Datos_tensor_prueba[i,0:29])
    #print(output.shape)
    #print(output)
    #print(Datos_tensor_prueba[i,0:29].shape)
    #print(Datos_tensor_prueba[i,0:29])
    s = output - Datos_tensor_prueba[i,0:29]
    #print(s)
    e = torch.dot(s, s)
    #print(e)
    error += e

print(error.detach().numpy()/k)

