Lecture 8 Notes Export
This commit is contained in:
parent
13087d2a0b
commit
85da8f42aa
BIN
lecture07/notes_07.pdf
Normal file
BIN
lecture07/notes_07.pdf
Normal file
Binary file not shown.
195
lecture07/notes_07.py
Normal file
195
lecture07/notes_07.py
Normal file
@ -0,0 +1,195 @@
|
||||
# %% [markdown]
|
||||
# # Previous Class Definitions
|
||||
# The previously defined Layer_Dense, Activation_ReLU, and Activation_Softmax
|
||||
|
||||
# %%
|
||||
# imports
|
||||
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):
|
||||
# Calculate the output values from inputs, weights, and biases
|
||||
self.output = np.dot(inputs, self.weights) + self.biases # Weights are already transposed
|
||||
|
||||
class Activation_ReLU:
|
||||
def forward(self, inputs):
|
||||
self.output = np.maximum(0, inputs)
|
||||
|
||||
class Activation_Softmax:
|
||||
def forward(self, inputs):
|
||||
# Get the unnormalized probabilities
|
||||
# Subtract max from the row to prevent larger numbers
|
||||
exp_values = np.exp(inputs - np.max(inputs, axis=1, keepdims=True))
|
||||
|
||||
# Normalize the probabilities with element wise division
|
||||
probabilities = exp_values / np.sum(exp_values, axis=1,keepdims=True)
|
||||
self.output = probabilities
|
||||
|
||||
# %% [markdown]
|
||||
# # Forward Pass with No Loss Consideration
|
||||
# 2 input neural network with 2 layers of 3 neurons each. ReLU activation in the first layer with Softmax in the second layer to normalize the outputs.
|
||||
|
||||
# %%
|
||||
# Create dataset
|
||||
X, y = spiral_data(samples=100, classes=3)
|
||||
# Create Dense layer with 2 input features and 3 output values
|
||||
dense1 = Layer_Dense(2, 3)
|
||||
# Create ReLU activation (to be used with Dense layer):
|
||||
activation1 = Activation_ReLU()
|
||||
# Create second Dense layer with 3 input features (as we take output
|
||||
# of previous layer here) and 3 output values
|
||||
dense2 = Layer_Dense(3, 3)
|
||||
# Create Softmax activation (to be used with Dense layer):
|
||||
activation2 = Activation_Softmax()
|
||||
|
||||
# Make a forward pass of our training data through this layer
|
||||
dense1.forward(X)
|
||||
|
||||
# Make a forward pass through activation function
|
||||
# it takes the output of first dense layer here
|
||||
activation1.forward(dense1.output)
|
||||
# Make a forward pass through second Dense layer
|
||||
# it takes outputs of activation function of first layer as inputs
|
||||
dense2.forward(activation1.output)
|
||||
# Make a forward pass through activation function
|
||||
# it takes the output of second dense layer here
|
||||
activation2.forward(dense2.output)
|
||||
# Let's see output of the first few samples:
|
||||
print(activation2.output[:5])
|
||||
|
||||
# %% [markdown]
|
||||
# # Calculating Network Error with Categorical Cross Entropy Loss
|
||||
# loss = negative sum of the expected output * log(neural network output)
|
||||
# loss = - sum(expected_i * log(nn_output_i)) for all i in outputs
|
||||
#
|
||||
# In the classification case, incorrect outputs do not end up mattering as the expected_i for the wrong class is 0.
|
||||
#
|
||||
|
||||
# %%
|
||||
nn_outputs = np.array([
|
||||
[0.7, 0.1, 0.2],
|
||||
[0.1, 0.5, 0.4],
|
||||
[0.02, 0.9, 0.08]])
|
||||
class_targets = [0, 1, 1]
|
||||
losses = -np.log(nn_outputs[range(len(nn_outputs)), class_targets])
|
||||
print(f"Losses: {losses}")
|
||||
print(f"Average Loss: {np.average(losses)}")
|
||||
|
||||
# %% [markdown]
|
||||
# ## Loss with One Hot Encoding
|
||||
# Classification typically has the expected output to be all zero except for the class the inputs belong too. This leads to simplfiying the cross entropy loss calculation.
|
||||
|
||||
# %%
|
||||
true_output = np.array([
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
[0, 1, 0]
|
||||
])
|
||||
|
||||
nn_output = np.array([
|
||||
[0.7, 0.2, 0.1],
|
||||
[0.1, 0.5, 0.4],
|
||||
[0.02, 0.9, 0.08]
|
||||
])
|
||||
|
||||
# Element by element multiplication "erases" the output terms corresponding with 0
|
||||
A = true_output*nn_output
|
||||
|
||||
# Sum the columns (ie, sum every element in row 0, then row 1, etc) because each row is a batch of output
|
||||
B = np.sum(A, axis = 1)
|
||||
|
||||
# Get the cross entropy loss
|
||||
C = -np.log(B)
|
||||
|
||||
print(f"Losses: {C}")
|
||||
print(f"Average Loss: {np.mean(C)}")
|
||||
|
||||
|
||||
# %% [markdown]
|
||||
# ## Implementing the Loss Class
|
||||
|
||||
# %%
|
||||
# Base class for Loss functions
|
||||
class Loss:
|
||||
'''Calculates the data and regularization losses given
|
||||
model output and ground truth values'''
|
||||
def calculate(self, output, y):
|
||||
sample_losses = self.forward(output, y)
|
||||
data_loss = np.average(sample_losses)
|
||||
return data_loss
|
||||
|
||||
# %% [markdown]
|
||||
# ## Implementing the Categorical Cross Entropy Loss Class
|
||||
|
||||
# %%
|
||||
class Loss_CategoricalCrossEntropy(Loss):
|
||||
def forward(self, y_pred, y_true):
|
||||
'''y_pred is the neural network output
|
||||
y_true is the ideal output of the neural network'''
|
||||
samples = len(y_pred)
|
||||
# Bound the predicted values
|
||||
y_pred_clipped = np.clip(y_pred, 1e-7, 1-1e-7)
|
||||
|
||||
if len(y_true.shape) == 1: # Categorically labeled
|
||||
correct_confidences = y_pred_clipped[range(samples), y_true]
|
||||
elif len(y_true.shape) == 2: # One hot encoded
|
||||
correct_confidences = np.sum(y_pred_clipped*y_true, axis=1)
|
||||
|
||||
# Calculate the losses
|
||||
negative_log_likelihoods = -np.log(correct_confidences)
|
||||
return negative_log_likelihoods
|
||||
|
||||
# %%
|
||||
nn_outputs = np.array([
|
||||
[0.7, 0.1, 0.2],
|
||||
[0.1, 0.5, 0.4],
|
||||
[0.02, 0.9, 0.08]])
|
||||
class_targets = np.array([
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
[0, 1, 0]])
|
||||
|
||||
loss_function = Loss_CategoricalCrossEntropy()
|
||||
losses = loss_function.calculate(nn_outputs, class_targets)
|
||||
print(f"Losses: {losses}")
|
||||
print(f"Average Loss: {np.average(losses)}")
|
||||
|
||||
# %% [markdown]
|
||||
# # Introducing Accuracy
|
||||
# In the simple example, if the highest value in the outputs align with the correct classification, then that accuracy is 1. Even if it was 51% red and 49% blue, and the true output is red, it would be considered fully accurate.
|
||||
|
||||
# %%
|
||||
nn_outputs = np.array([
|
||||
[0.7, 0.1, 0.2],
|
||||
[0.1, 0.5, 0.4],
|
||||
[0.02, 0.9, 0.08]])
|
||||
class_targets = np.array([
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
[0, 1, 0]])
|
||||
|
||||
# Calculate the losses
|
||||
loss_function = Loss_CategoricalCrossEntropy()
|
||||
losses = loss_function.calculate(nn_outputs, class_targets)
|
||||
print(f"Losses: {losses}")
|
||||
print(f"Average Loss: {np.average(losses)}")
|
||||
|
||||
# Calculate the accuracy
|
||||
predictions = np.argmax(nn_outputs, axis=1)
|
||||
# If targets are one-hot encoded - convert them
|
||||
if len(class_targets.shape) == 2:
|
||||
class_targets = np.argmax(class_targets, axis=1)
|
||||
# True evaluates to 1; False to 0
|
||||
accuracy = np.mean(predictions == class_targets)
|
||||
print(f"Accuracy: {accuracy}")
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user