266 lines
6.5 KiB
Python
266 lines
6.5 KiB
Python
# %% [markdown]
|
|
# # Layer of Neurons and Batch of Data Using Numpy
|
|
# From lecture 1, 1 layer of 3 neurons
|
|
|
|
# %%
|
|
import numpy as np
|
|
|
|
inputs = [ # Batch of inputs
|
|
[1.0, 2.0, 3.0, 2.5],
|
|
[2.0, 5.0, -1.0, 2.0],
|
|
[-1.5, 2.7, 3.3, -0.8]
|
|
]
|
|
weights = np.array([
|
|
[0.2, 0.8, -0.5, 1],
|
|
[0.5, -0.91, 0.26, -0.5],
|
|
[-0.26, -0.27, 0.17, 0.87]
|
|
])
|
|
biases = [2.0, 3.0, 0.5]
|
|
|
|
outputs = np.dot(inputs, weights.T) + biases
|
|
# For every row of inputs, compute the dot of input set and weights
|
|
print(outputs)
|
|
|
|
# %% [markdown]
|
|
# # 2 Layers and Batch of Data Using Numpy
|
|
# 2 layers. Layer 1 and layer 2 have 3 neurons. Therefore, there are 3 final outputs.
|
|
#
|
|
# There are 3 batches of input data to generate 3 total output arrays.
|
|
|
|
# %%
|
|
import numpy as np
|
|
|
|
inputs = [[1, 2, 3, 2.5],
|
|
[2., 5., -1., 2],
|
|
[-1.5, 2.7, 3.3, -0.8]]
|
|
|
|
weights = [[0.2, 0.8, -0.5, 1],
|
|
[0.5, -0.91, 0.26, -0.5],
|
|
[-0.26, -0.27, 0.17, 0.87]]
|
|
|
|
biases = [2, 3, 0.5]
|
|
|
|
weights2 = [[0.1, -0.14, 0.5],
|
|
[-0.5, 0.12, -0.33],
|
|
[-0.44, 0.73, -0.13]]
|
|
|
|
biases2 = [-1, 2, -0.5]
|
|
|
|
# Make the lists np.arrays so we can transpose them
|
|
inputs_array = np.array(inputs)
|
|
weights_array = np.array(weights)
|
|
biases_array = np.array(biases)
|
|
weights2_array = np.array(weights2)
|
|
biases2_array = np.array(biases2)
|
|
|
|
# Get the output of the first layer
|
|
layer1_outputs = np.dot(inputs_array, weights_array.T) + biases_array
|
|
|
|
# Feed the output of the first layer into the second layer with their own weights
|
|
layer2_outputs = np.dot(layer1_outputs, weights2_array.T) + biases2_array
|
|
|
|
print(layer2_outputs)
|
|
|
|
# %% [markdown]
|
|
# # 4 Layers and Batch of Data Using Numpy
|
|
# Cascading neural network with 4 layers. Layer 1 has 4 neurons, layer 2 has 3, layer 3 has 2 and layer 4 has a single output.
|
|
|
|
# %%
|
|
import numpy as np
|
|
|
|
# Batch of inputs
|
|
inputs = [
|
|
[1, 2, 3, 2.5],
|
|
[2., 5., -1., 2],
|
|
[-1.5, 2.7, 3.3, -0.8]
|
|
]
|
|
|
|
# Weights are stored in a list of np.array
|
|
# index 0 = layer 1 weights and so on
|
|
weights = [
|
|
np.array([ # Layer 1
|
|
[0.2, 0.8, -0.5, 1], # Neuron 1.1
|
|
[0.5, -0.91, 0.26, -0.5], # Neuron 1.2
|
|
[-0.26, -0.27, 0.17, 0.87], # Neuron 1.3
|
|
[-0.27, 0.87, 0.2, 0.8], # Neuron 1.4
|
|
]),
|
|
np.array([ # Layer 2
|
|
[0.1, 0.65, -0.24, 1.2], # Neuron 2.1
|
|
[0.51, -0.21, 0.206, -0.05], # Neuron 2.2
|
|
[-0.46, -0.67, 0.14, 0.37], # Neuron 2.3
|
|
]),
|
|
np.array([ # Layer 3
|
|
[0.25, 0.4, -0.2], # Neuron 3.1
|
|
[0.58, -0.25, 0.26], # Neuron 3.2
|
|
]),
|
|
np.array([ # Layer 4
|
|
[0.3, 0.1], # Neuron 4.1
|
|
])
|
|
]
|
|
biases = [
|
|
[0.5, 2, 1, -2], # Layer 1
|
|
[0.2, -0.6, 1.3,], # Layer 2
|
|
[-1, 0.5,], # Layer 3
|
|
[0.28], # Layer 4
|
|
]
|
|
|
|
# Iterate through each layer, get the output of the layer, use it as the input for the next layer
|
|
layer_inputs = inputs
|
|
layer_outputs = np.array([])
|
|
for layer in range(len(weights)):
|
|
layer_weights = weights[layer]
|
|
layer_biases = biases[layer]
|
|
layer_outputs = np.dot(layer_inputs, layer_weights.T) + layer_biases
|
|
|
|
# Update the inputs for the next layer based on the outputs of this layer
|
|
layer_inputs = layer_outputs
|
|
# layer_outputs is left holding the final outputs of the network
|
|
|
|
print(layer_outputs)
|
|
|
|
# %% [markdown]
|
|
# # Generating Non Linear Training Data
|
|
# Generate 2D training data, x and y
|
|
|
|
# %%
|
|
from nnfs.datasets import spiral_data
|
|
import numpy as np
|
|
import nnfs
|
|
nnfs.init()
|
|
import matplotlib.pyplot as plt
|
|
X, y = spiral_data(samples=100, classes=3)
|
|
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='brg')
|
|
plt.show()
|
|
|
|
# %% [markdown]
|
|
# # Dense Layer Class
|
|
# Given number of neurons and inputs in the layer, predict the output by assigning weights and biases.
|
|
|
|
# %%
|
|
import numpy as np
|
|
import nnfs
|
|
from nnfs.datasets import spiral_data
|
|
nnfs.init()
|
|
|
|
class Layer_Dense:
|
|
def __init__(self, n_inputs, n_neurons):
|
|
# Initialize the weights and biases
|
|
self.weights = 0.01 * np.random.randn(n_inputs, n_neurons) # Normal distribution of weights
|
|
self.biases = np.zeros((1, n_neurons))
|
|
|
|
def forward(self, inputs):
|
|
# Calculat ethe output values from inputs, weights, and biases
|
|
self.output = np.dot(inputs, self.weights) + self.biases # Weights are already transposed
|
|
|
|
# Create a dataset
|
|
X, y = spiral_data(samples=100, classes=3)
|
|
# Create a dense layer with 2 inputs and 3 output values
|
|
dense1 = Layer_Dense(2, 3)
|
|
# Perform a forward pass of the dataset through the dense layer
|
|
dense1.forward(X)
|
|
|
|
# Print just the first few outputs
|
|
print(dense1.output[:5])
|
|
|
|
|
|
# %% [markdown]
|
|
# # Python Array Summation
|
|
|
|
# %%
|
|
import numpy as np
|
|
|
|
A = [
|
|
[1, 2, 3],
|
|
[4, 5, 6],
|
|
[7, 8, 9]
|
|
]
|
|
|
|
# Sum the elements in the array resulting in a scalar
|
|
print(np.sum(A))
|
|
|
|
# Sum the rows resulting in a row vector
|
|
'''
|
|
[1, 2, 3]
|
|
+ [4, 5, 6]
|
|
+ [7, 8, 9]
|
|
= [12, 15, 18]
|
|
'''
|
|
print(np.sum(A, axis=0))
|
|
|
|
# Sum the columns resulting in a column vector
|
|
'''
|
|
1 + 2 + 3 = 6
|
|
4 + 5 + 6 = 15
|
|
7 + 8 + 9 = 24
|
|
'''
|
|
print(np.sum(A, axis=1))
|
|
|
|
# keepdims will keep the dimension of A
|
|
print(np.sum(A, axis=0, keepdims=True))
|
|
print(np.sum(A, axis=1, keepdims=True))
|
|
|
|
# %% [markdown]
|
|
# # Python Array Broadcasting Rules
|
|
# Check if arrays are broadcastable by scanning right to left for their dimensions. If they share the sime size in that dimension, either of them is size 1, or one size does not exist, continue left.
|
|
#
|
|
# Given A is 3x3 and B is 3x3, check if it is broadcastable.
|
|
#
|
|
# 3 x 3
|
|
#
|
|
# 3 x 1
|
|
#
|
|
# Start by comparing 3 and 1. This is fine because B has size 1.
|
|
#
|
|
# Move to 3 and 3. This is fine because they are equal. The arrays are broadcastable.
|
|
#
|
|
# Once the arrays are deemed broadcastable, Python will maniupulate one or the other to perform the operation.
|
|
|
|
# %%
|
|
import numpy as np
|
|
|
|
A = np.array([
|
|
[1, 2, 3],
|
|
[4, 5, 6],
|
|
[7, 8, 9]
|
|
]) # 3 x 3
|
|
|
|
B = np.array([
|
|
[1],
|
|
[2],
|
|
[3]
|
|
]) # 3 x 1
|
|
|
|
print(A+B)
|
|
|
|
# Adding the arrays will broadcast B into a 3x3 in order to add them.
|
|
B_broadcast = np.array([
|
|
[1, 1, 1],
|
|
[2, 2, 2],
|
|
[3, 3, 3]
|
|
]) # 3 x 1
|
|
|
|
print(A+B_broadcast)
|
|
|
|
# Example
|
|
# Take each row and subtract the maximum value from the row
|
|
A = np.array([
|
|
[1, 2, 3],
|
|
[4, 5, 6],
|
|
[7, 8, 9]
|
|
]) # 3 x 3
|
|
|
|
# Gets the max value in each row by comparing the columns (axis1). Use keepdims so it is a column vector
|
|
result = A - np.max(A, axis=1, keepdims=True)
|
|
print(result)
|
|
|
|
|
|
# %% [markdown]
|
|
# # Activation Function: ReLU
|
|
# Rectified Linear Unit
|
|
#
|
|
|
|
# %%
|
|
|
|
|
|
|