1
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from tqdm.auto import tqdm
from torch.nn import functional as F
import numpy as np
import matplotlib.pyplot as plt
import datetime
import os
import pandas as pd
from sklearn.preprocessing import StandardScaler


# VAE model
class VAE(nn.Module):
    def __init__(self, image_size, hidden_size_1, hidden_size_2, latent_size):
        super(VAE, self).__init__()

        self.fc1 = nn.Linear(image_size, hidden_size_1)
        self.fc2 = nn.Linear(hidden_size_1, hidden_size_2)
        self.fc31 = nn.Linear(hidden_size_2, latent_size)
        self.fc32 = nn.Linear(hidden_size_2, latent_size)

        self.fc4 = nn.Linear(latent_size, hidden_size_2)
        self.fc5 = nn.Linear(hidden_size_2, hidden_size_1)
        self.fc6 = nn.Linear(hidden_size_1, image_size)

    def encode(self, x):
        h1 = F.relu(self.fc1(x))
        h2 = F.relu(self.fc2(h1))
        return self.fc31(h2), self.fc32(h2)

    def reparameterize(self, mu, logvar):
        std = torch.exp(0.5 * logvar)
        eps = torch.randn_like(std)
        return mu + std * eps

    def decode(self, z):
        h3 = F.relu(self.fc4(z))
        h4 = F.relu(self.fc5(h3))
        return torch.sigmoid(self.fc6(h4))

    def forward(self, x):
        mu, logvar = self.encode(x)
        z = self.reparameterize(mu, logvar)
        return self.decode(z), mu, logvar


class TensorDataset:

    def __init__(self, data, label, x_dtype = torch.float32, y_dtype = torch.float32):
        self.data = data
        self.label = label
        self.x_dtype = x_dtype
        self.y_dtype = y_dtype
        self.convert_to_Tensor()

    def __getitem__(self, index):
        data = self.data[index]
        label = self.label[index]
        return data, label

    def __len__(self):
        return len(self.data)

    def convert_to_Tensor(self):
        self.data = torch.tensor(self.data, dtype=self.x_dtype)
        self.label = torch.tensor(self.label, dtype=self.y_dtype)


def loss_function(recon_x, x, mu, logvar):
    BCE = F.binary_cross_entropy(recon_x, x, reduction = 'sum')
    KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())
    return BCE + KLD


def gen_latent(normal_array):
    normal_dataset = TensorDataset(normal_array, normal_array)
    normal_dataloader = DataLoader(normal_dataset,
                                   batch_size=len(normal_dataset),
                                   shuffle=False)
    normal_iter = iter(normal_dataloader)
    normal_data, _ = next(normal_iter)
    return normal_data


if __name__=="__main__":

    # Parameters
    EPOCHS = 50
    BATCH_SIZE = 200  

    # Cuda check
    USE_CUDA = torch.cuda.is_available()
    DEVICE = torch.device("cuda" if USE_CUDA else "cpu")
    print("사용하는 Device : ", DEVICE)

    # Data
    drop_cols = ['site', 'sid', 'ldate', 'leaktype']
    normal_df = pd.read_csv('data/5.정상음(normal-training).csv').drop(drop_cols, axis=1)
    abnormal_out_df = pd.read_csv('data/1.옥외누수(out-training).csv').drop(drop_cols, axis=1)
    abnormal_in_df = pd.read_csv('data/2.옥내누수(in-training).csv').drop(drop_cols, axis=1)
    all_array = pd.concat([normal_df, abnormal_out_df, abnormal_in_df], axis=0).values
    scaler = StandardScaler()
    all_array = scaler.fit_transform(all_array)

    # DataLoader
    dataset = TensorDataset(all_array, all_array)
    dataloader = DataLoader(dataset,
                            batch_size=128,
                            shuffle=True)

    # About mode  
    VAE_model = VAE(535, 256, 32, 2).to(DEVICE)
    optimizer = optim.Adam(VAE_model.parameters(), lr=0.001)

    # Train
    train_losses = []
    for epoch in range(EPOCHS):

        VAE_model.train()
        train_loss = 0 
        for i, (data, _) in enumerate(dataloader):
            # zero grad
            optimizer.zero_grad()
            # apply device to data
            data = data.to(DEVICE)
            # calculate
            recon_batch, mu, logvar = VAE_model(data)
            # cal loss
            loss = loss_function(recon_batch, data, mu, logvar)
            # backward
            loss.backward()
            train_loss += loss.item()
            # step
            optimizer.step()

        train_losses.append(train_loss)

        print("======> Epoch: {} Average loss: {:.4f}".format(
            epoch, train_loss / len(dataloader.dataset)
        ))

    #
    normal_array = pd.read_csv('data/5.정상음(normal-training).csv').drop(drop_cols, axis=1).values
    abnormal_out_array = pd.read_csv('data/1.옥외누수(out-training).csv').drop(drop_cols, axis=1).values
    abnormal_in_array = pd.read_csv('data/2.옥내누수(in-training).csv').drop(drop_cols, axis=1).values

    #
    normal_data = gen_latent(normal_array)
    abnormal_out_data = gen_latent(abnormal_out_array)
    abnormal_in_data = gen_latent(abnormal_in_array)

    #
    def return_z_vae(normal_data):
        a, b = VAE_model.encode(normal_data)
        z = VAE_model.reparameterize(a, b)
        return z.detach().numpy()

    z_normal = return_z_vae(normal_data)
    z_abnormal_out = return_z_vae(abnormal_out_data)
    z_abnormal_in = return_z_vae(abnormal_in_data)

    # Plot
    plt.scatter(z_normal[:, 0], z_normal[:, 1], color='blue', s=1, label='normal')
    plt.scatter(z_abnormal_out[:, 0], z_abnormal_out[:, 1], color='red', s=1, label='abnormal_out')
    plt.scatter(z_abnormal_in[:, 0], z_abnormal_in[:, 1], color='green', s=1, label='abnormal_in')
    plt.legend()

This code is to encode(similar to PCA) the data with 535 columns with VAE model. I don't know the problem with this code. The average loss is too big, and also increasing. average loss

My data is FFT-transformed water pipeline signal data. It has about 500 columns of Hz and leaktype(out-building leak, in-building leak, normal signal data - out, in, normal).

data head

(I dropped the site, sid, ldate, and leaktype for feature data set)

0 Answers0