HI, MY NAME IS ROSY.🌹
INORDER TO STUDY NEURAL NET, THESE DAYS ROSY IS TRYING TO CREATE ITEMS THOSE COULD SOVEL SOME PROBELM.
HERE ROSY'LL GIVE YOU A SIMPLE EXAMPLE, WHICH MAY HELP YOU GET SOME INTERESTING IDEARS DURING RUNNING-TIME.
THE CODE HAVES THE DETAIL NOTE.
IF THERE ARE SOME PROBLEM, TELL ME, I'LL REPLY YOU.
THANKS! 🌹
# -*- coding: utf-8 -*-
"""
Title: Denoising VAE for Noise_COS_WAVE
@author: Rosy_Willa
"""
# Call the relative library function
import torch
import torch.nn as nn
import torch.optim as optim
from torch.autograd import Variable
import numpy as np
import matplotlib.pyplot as plt
import torch.nn.functional as F
from scipy.stats import poisson
from torchvision import datasets, transforms
from torch.utils.data import DataLoader, TensorDataset
import random
# Clean up GPU memory
import gc
gc.collect()
torch.cuda.empty_cache()
# Selection of the GPU OR CPU
'''Check if there is a GPU available'''
if torch.cuda.is_available():
flag = True
else:
flag = False
'''if choose "True" means U want to Use GPU,else,"False"means U want to Use CPU
Attention: Only flag and memory_select both defined as "True",the device uses GPU'''
memory_select=False
if flag and memory_select:
device = torch.device('cuda')
print('Using GPU')
else:
device=torch.device('cpu')
print('Using CPU')
# Generate the signals
class SignalsGenerator:
'''
input:Amplitude,Frequency,Initial_Phase,Duration,Flag_show
output:Time_Vector,Cos_Wave
'''
def __init__(self,Amplitude,Frequency,Initial_Phase,Duration,Flag_show):
self.Amplitude = Amplitude
self.Frequency = Frequency
self.Initial_Phase = Initial_Phase
self.Duration = Duration
self.Time_Step = int(self.Frequency*self.Duration)
self.Flag_show = Flag_show
def generate_initial_signalssignals(self):
'''Create A Time Vector'''
Time_Vector = torch.linspace(0, self.Duration,self.Time_Step)
'''Generate Initial Cosine Signal'''
Cos_Wave = self.Amplitude * torch.cos(2 * np.pi * self.Frequency * Time_Vector + self.Initial_Phase)
return Time_Vector,Cos_Wave
def showplot(self):
if self.Flag_show:
Time_Vector,Initial_Wave = self.generate_initial_signalssignals()
plt.figure(figsize = (10,4))
plt.plot(Time_Vector.numpy(),Initial_Wave.numpy())
plt.title('Initial Signal')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.grid(True)
plt.show()
# Add noisy
class AddNoise:
'''Provide 10 types of different noise'''
def __init__(self,signals):
self.signals=signals
def add_gaussion_noise(self,mean=0,std=1):
noise = torch.randn(self.signals.shape) * std + mean
noise_signal = noise + self.signals
return noise_signal
def add_salt_and_pepper_noise(self,noise_density = 0.05 , salt_vs_pepper = 0.5):
'''Calculate the number of points that need to be replaced '''
num_noise_points = int(len(self.signals) * noise_density)
'''Randomly select the index of the replacement point'''
noise_index = torch.randperm(len(self.signals))[:num_noise_points]
'''Copy the initial signals'''
copy_signal=self.signals
'''For the each selected Index, Randomly certen the type of the noisy about "salt"or"pepeer",and replace it'''
for index in noise_index:
if random.random()<salt_vs_pepper:
'''add salt noise,Set the Maximum Value of the signals'''
copy_signal[index] = self.signals.max()
else:
'''add pepper noise,Set the Maximum Value of the signals'''
copy_signal[index] = self.signals.min()
noise_signal = copy_signal
return noise_signal
def add_poisson_noise(self,lam = 1):# SOME PROBLEMS EXIT,IF YOU WANT TO USE IT, ADJUST IT.
'''lam: means the number of happened events '''
noise = torch.poisson(lam,self.signals.shape)
noise_signal = noise + self.signals
return noise_signal
def add_centered_uniform_noise(self,a=-1,b=1):
noise = torch.rand(self.signals.shape) * (b - a) + a
noise_signal = noise + self.signals
return noise_signal
def add_uniform_noise(self,a=0,b=1):
noise = torch.rand(self.signals.shape) * (b - a) + a
noise_signal = noise + self.signals
return noise_signal
def add_impulse_noise(self,Amplitude = 0.01, probability = 0.01):
noise = torch.zeros_like(self.signals)
noise_index = torch.rand(self.signals.shape) < probability
noise[noise_index] = Amplitude * (2*torch.rand(noise_index.sum())-1)
noise_signal = noise + self.signals
return noise_signal
def add_binary_noise(self,probability = 0.05):
noise = torch.zeros_like(self.signals)
binary_index = torch.rand(self.signals.shape) < probability
noise[binary_index] = 1
noise_signal = noise + self.signals
return noise_signal
def add_colored_noise(self,Amplitude = 0.01, alpha=1.0):
freq = torch.fft.fftfreq(self.signals.shape[-1])
noise_spectrum = Amplitude * torch.randn(self.signals.shape[-1], dtype=self.signals.dtype)
'''Avoid dividing by zero'''
colored_noise_spectrum = noise_spectrum / (freq**alpha + 1e-8)
colored_noise = torch.fft.ifft(colored_noise_spectrum)
noise_signal = colored_noise + self.signals
return noise_signal
def add_flicker_noise(self,Amplitude = 0.01, beta = 1.0):
freq = torch.fft.fftfreq(self.signals.shape[-1])
'''Avoid dividing by zero'''
flicker_noise_spectrum = Amplitude / (freq**beta + 1e-8)
'''Generate random complex noise spectrum, real and imaginary parts obey standard normal distribution'''
noise_spectrum = torch.randn(self.signals.shape[-1], dtype=torch.cfloat)
'''Applying the characteristics of the frequency spactrum of flicker noise'''
colored_noise_spectrum = flicker_noise_spectrum * noise_spectrum
colored_noise = torch.fft.ifft(colored_noise_spectrum)
noise_signals = colored_noise + self.signals
return noise_signals
# Show and Plot
class showitplot:
def __init__(self,Time_Vector):
super(showitplot,self).__init__()
self.Time_Vector = Time_Vector
'''Allow single type of signal can be plotted'''
def forward(self,Signals):
plt.figure(figsize = (10,4))
plt.plot(self.Time_Vector.numpy(),Signals.detach().numpy())
plt.title('Signal')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.grid(True)
plt.show()
# VAE1
class VAE1(nn.Module):
def __init__(self,Linear_Num):
super(VAE1,self).__init__()
self.Linear_Num = Linear_Num
# Encoder
self.Encoder1_Conv1d = nn.Conv1d(in_channels = 1, out_channels = 4, kernel_size = 4, stride = 2, padding = 2)
self.Encoder2_Conv1d = nn.Conv1d(in_channels = 4, out_channels = 8, kernel_size = 4, stride = 2, padding = 2)
self.Encoder3_Conv1d = nn.Conv1d(in_channels = 8, out_channels = 16, kernel_size = 4, stride = 2, padding = 2)
self.Encoder4_Linear = nn.Linear(129*16, self.Linear_Num)
self.Encoder5_Linear = nn.Linear(129*16, self.Linear_Num)
# Decoder
self.Decoder1_Linear = nn.Linear(self.Linear_Num,129*16)
self.Decoder2_TConv1d = nn.ConvTranspose1d(in_channels = 16, out_channels = 8, kernel_size = 4,stride = 2, padding = 2)
self.Decoder3_TConv1d = nn.ConvTranspose1d(in_channels = 8, out_channels = 4, kernel_size = 3,stride = 2, padding = 0)
self.Decoder4_TConv1d = nn.ConvTranspose1d(in_channels = 4, out_channels = 1, kernel_size = 4,stride = 2, padding = 2)
def Encoder(self,Input):
Input = Input.reshape(Input.size(0),1,Input.size(1))
Encoder1 = F.relu(self.Encoder1_Conv1d(Input))
Encoder2 = F.relu(self.Encoder2_Conv1d(Encoder1))
Encoder3 = F.relu(self.Encoder3_Conv1d(Encoder2))
mid=Encoder3.view(Encoder3.size(0),-1)
Encoder4 = F.relu(self.Encoder4_Linear(mid))
Encoder5 = F.relu(self.Encoder5_Linear(mid))
mean = Encoder4
logvar = Encoder5
return mean, logvar
def Decoder(self,z):
Decoder1 = F.relu(self.Decoder1_Linear(z))
mid=Decoder1.view(Decoder1.size(0),16,-1)
Decoder2 = F.relu(self.Decoder2_TConv1d(mid))
Decoder3 = F.relu(self.Decoder3_TConv1d(Decoder2))
Decoder4 = F.relu(self.Decoder4_TConv1d(Decoder3))
output = torch.sigmoid(Decoder4)
return output
def reparameter(self,mean,logvar):
std = torch.exp(0.5*logvar)
eps = torch.randn_like(std)
z = eps * std +mean
return z
def forward(self,Input):
mean, logvar = self.Encoder(Input)
z = self.reparameter(mean, logvar)
output = self.Decoder(z)
return mean, logvar, output
def loss_Function(self, output, Input, mean, logvar):
output = output.view(output.size(0),output.size(2))
recon_loss=F.cross_entropy(output, F.softmax(Input))#F.cross_entropy(output, torch.sigmoid(Input))#F.cross_entropy(output, F.softmax(Input))
kld_loss=-0.5*torch.sum(1+logvar-mean.pow(2)-logvar.exp())
loss = recon_loss + kld_loss
return loss
'''User input parameters'''
Amplitude = float(1)
Frequency = float(1024)
Initial_Phase = float(90)
Duration = float(1)
'''
Amplitude = float(input("Enter the amplitude of the sine wave: "))
Frequency = float(input("Enter the sampling rate (Hz): "))
Initial_Phase = float(input("Enter the initial phase (radians): "))
Duration = float(input("Enter the duration of the sine wave (seconds): "))
'''
'''IF show the initial signals'''
Flag_show = True
# Instantiation
'''Get Initial Signals'''
GenerateSignalsClass = SignalsGenerator(Amplitude, Frequency, Initial_Phase, Duration, Flag_show)
Time_Vector,Cos_Wave= GenerateSignalsClass.generate_initial_signalssignals()
AddNoiseClass = AddNoise(Cos_Wave)
Noise_signals = AddNoiseClass.add_impulse_noise()
Plots = showitplot(Time_Vector)
Linear_Num = 100
batchsize = 100
Input = torch.zeros(batchsize,len(Time_Vector))
COS_INPUT = torch.zeros(batchsize,len(Time_Vector))
for epoch in range(batchsize):
Input[epoch] = AddNoiseClass.add_centered_uniform_noise()
COS_INPUT[epoch] = Cos_Wave
Input = torch.sigmoid(Input)
''' Place the parameters into the device'''
Input = Input.to(device)
Net = VAE1(Linear_Num).to(device)
# Optimizer
learning_rate = 0.01
optimizer=torch.optim.Adam(Net.parameters(),lr=learning_rate)
# Train
epoch_num = 500
for epoch in range(epoch_num):
optimizer.zero_grad()
mean, logvar, output = Net(Input)
loss = Net.loss_Function(output, Input, mean, logvar)
#loss.requires_grad_(True)
loss.backward()
optimizer.step()
pp=output.view(output.size(0),output.size(2))
# Plots.forward(torch.sigmoid(Input[epoch]))
Plots.forward(pp[0])
#Plots.forward(torch.sigmoid(Input[epoch]-Cos_Wave))
print(f'Epoch [{epoch + 1}/{epoch_num}], Loss: {loss.item()}')