...
/Defining Activation Functions and The Loss Function
Defining Activation Functions and The Loss Function
Understand the concepts of activation functions and loss function and practice generating samples using a basic GAN.
We'll cover the following...
We will be only using NumPy to calculate and train our GAN model (and optionally using Matplotlib to visualize the signals). All of the following code can be placed in a simple .py
file (such as simple_
gan.py
). Let’s look at the code step by step:
Import the
numpy
library:
import numpy as np
Define a few constant variables that are needed in our model:
Z_DIM = 1G_HIDDEN = 10X_DIM = 10D_HIDDEN = 10step_size_G = 0.01step_size_D = 0.01ITER_NUM = 50000GRADIENT_CLIP = 0.2WEIGHT_CLIP = 0.25
Define the real sine samples (with
numpy.sin
) that we want to estimate:
def get_samples(random=True):if random:x0 = np.random.uniform(0, 1)freq = np.random.uniform(1.2, 1.5)mult = np.random.uniform(0.5, 0.8)else:x0 = 0freq = 0.2mult = 1signal = [mult * np.sin(x0+freq*i) for i in range(X_DIM)]return np.array(signal)
In the previous snippet, we use a bool
variable named random
to introduce randomness into the real samples, as real-life data has. The real samples look like this (50 samples with random=True
):
Define the activation functions and their derivatives. If you're not familiar with the concept of activation functions, just remember that their jobs are to adjust the outputs of a layer so that its next layer can have a better understanding of these output values:
def ReLU(x):return np.maximum(x, 0.)def dReLU(x):return ReLU(x)def LeakyReLU(x, k=0.2):return np.where(x >= 0, x, x * k)def dLeakyReLU(x, k=0.2):return np.where(x >= 0, 1., k)def Tanh(x):return np.tanh(x)def dTanh(x):return 1. - Tanh(x)**2def Sigmoid(x):return 1. / (1. + np.exp(-x))def dSigmoid(x):return Sigmoid(x) * (1. - Sigmoid(x))
Define a helper function to initialize the layer parameters:
def weight_initializer(in_channels, out_channels):scale = np.sqrt(2. / (in_channels + out_channels))return np.random.uniform(-scale, scale, (in_channels,out_channels))
Define the loss function (both forward and backward):
class LossFunc(object):def __init__(self):self.logit = Noneself.label = Nonedef forward(self, logit, label):if logit[0, 0] < 1e-7:logit[0, 0] = 1e-7if 1. - logit[0, 0] < 1e-7:logit[0, 0] = 1. - 1e-7self.logit = logitself.label = labelreturn - (label * np.log(logit) + (1-label) * np.log(1- logit))def backward(self):return (1-self.label) / (1-self.logit) - self.label/self.logit
This is called binary cross-entropy, which is typically used in binary classification problems (in which a sample either belongs to class A or class B). Sometimes, one of the networks is trained too well so that the sigmoid output of the discriminator might be either too close to 0 or 1. Both of the scenarios lead to numerical errors of the log function. Therefore, we need to restrain the maximum and minimum values of the output value.
Working on forward pass and backpropagation
Now, let's create our generator and discriminator networks. We put the ...