Fully connected layer of a neural network
The weight initialisations are dependant on the activation function.
-
If the activation function is LeakyReLU, then the weights are initialised from a He-Normal distribution - see: http://proceedings.mlr.press/v9/glorot10a.html
-
If the activation function is softmax, then the weights are initialised from a Glorot/Xavier normal distribution - see: https://arxiv.org/abs/1502.01852
Parameters:
Name |
Type |
Description |
Default |
input_n |
int
|
The amount of inputs to the DenseLayer |
required
|
output_n |
int
|
The amount of outputs to the DenseLayer |
required
|
activation |
str
|
The activation function to use for all of the neurons in the DenseLayer, either 'leaky_relu' or 'softmax' |
required
|
Source code in mlproject/neural_net/_dense_layer.py
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 | class DenseLayer:
"""Fully connected layer of a neural network
The weight initialisations are dependant on the activation function.
* If the activation function is LeakyReLU, then the weights are initialised from a He-Normal distribution - see: http://proceedings.mlr.press/v9/glorot10a.html
* If the activation function is softmax, then the weights are initialised from a Glorot/Xavier normal distribution - see: https://arxiv.org/abs/1502.01852
Parameters
----------
input_n : int
The amount of inputs to the DenseLayer
output_n : int
The amount of outputs to the DenseLayer
activation : str
The activation function to use for all of the neurons in the DenseLayer, either 'leaky_relu' or 'softmax'
"""
def __init__(self, input_n: int, output_n: int, activation: str):
self.output_n, self.input_n = output_n, input_n
self.z = None
self.biases = np.zeros(shape=(output_n))
if activation == "leaky_relu":
self.activation = leaky_relu
# He initiliasation of weights
# see https://keras.io/api/layers/initializers/#henormal-class
stddev = np.sqrt(2 / input_n)
self.weights = np.random.normal(
loc=0, scale=stddev, size=(input_n, output_n)
)
elif activation == "softmax" or activation == "stable_softmax":
# Glorot/Xavier initiliasation of weights
# see https://keras.io/api/layers/initializers/#glorotnormal-class
stddev = np.sqrt(2 / (input_n + output_n))
self.weights = np.random.normal(
loc=0, scale=stddev, size=(input_n, output_n)
)
self.activation = stable_softmax
else:
raise NotImplementedError(
f"{activation} not implemented yet. Choose from ['leaky_relu', 'stable_softmax']"
)
def forward(self, X):
"""Computes a single forward pass of the DenseLayer
Parameters
----------
X : 2d ndarray
An n x p matrix of data points
where n is the number of data points and p is the number of features.
Returns
-------
2d ndarray
An n x output_n numpy array where n is the number of samples
and output_n is the number of neurons in the DenseLayer
"""
self.z = X.dot(self.weights) + self.biases
return self.activation(self.z)
def _out_neurons(self):
"""Return the number of output neurons in the DenseLayer
Returns
-------
int
The total number of output neurons in the DenseLayer
"""
return self.output_n
def _in_neurons(self):
"""Return the number of input neurons in the DenseLayer
Returns
-------
int
The total number of input neurons in the DenseLayer
"""
return self.input_n
def activation_function(self):
"""Return a string representing the activation function of the given DenseLayer
Returns
-------
string
string representing the activation function of the given DenseLayer
"""
if self.activation == stable_softmax:
return "softmax"
elif self.activation == leaky_relu:
return "leaky_relu"
|
activation_function()
Return a string representing the activation function of the given DenseLayer
Returns:
Type |
Description |
string
|
string representing the activation function of the given DenseLayer |
Source code in mlproject/neural_net/_dense_layer.py
93
94
95
96
97
98
99
100
101
102
103
104 | def activation_function(self):
"""Return a string representing the activation function of the given DenseLayer
Returns
-------
string
string representing the activation function of the given DenseLayer
"""
if self.activation == stable_softmax:
return "softmax"
elif self.activation == leaky_relu:
return "leaky_relu"
|
forward(X)
Computes a single forward pass of the DenseLayer
Parameters:
Name |
Type |
Description |
Default |
X |
2d ndarray
|
An n x p matrix of data points
where n is the number of data points and p is the number of features. |
required
|
Returns:
Type |
Description |
2d ndarray
|
An n x output_n numpy array where n is the number of samples
and output_n is the number of neurons in the DenseLayer |
Source code in mlproject/neural_net/_dense_layer.py
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 | def forward(self, X):
"""Computes a single forward pass of the DenseLayer
Parameters
----------
X : 2d ndarray
An n x p matrix of data points
where n is the number of data points and p is the number of features.
Returns
-------
2d ndarray
An n x output_n numpy array where n is the number of samples
and output_n is the number of neurons in the DenseLayer
"""
self.z = X.dot(self.weights) + self.biases
return self.activation(self.z)
|