29 KiB
29 KiB
In [1]:
import autograd.numpy as np # We need to use this numpy wrapper to make automatic differentiation work later
from sklearn import datasets
import matplotlib.pyplot as plt
from sklearn.metrics import accuracy_score
# Defining some activation functions
def ReLU(z):
return np.where(z > 0, z, 0)
def sigmoid(z):
return 1 / (1 + np.exp(-z))
def softmax(z):
"""Compute softmax values for each set of scores in the rows of the matrix z.
Used with batched input data."""
e_z = np.exp(z - np.max(z, axis=0))
return e_z / np.sum(e_z, axis=1)[:, np.newaxis]
def softmax_vec(z):
"""Compute softmax values for each set of scores in the vector z.
Use this function when you use the activation function on one vector at a time"""
e_z = np.exp(z - np.max(z))
return e_z / np.sum(e_z)In [2]:
np.random.seed(2024)
x = np.random.randn(2) # network input. This is a single input with two features
W1 = np.random.randn(4, 2) # first layer weightsIn [3]:
b1 = ...In [4]:
z1 = ...In [5]:
a1 = ...In [6]:
sol1 = np.array([0.60610368, 4.0076268, 0.0, 0.56469864])
print(np.allclose(a1, sol1))[0;31m---------------------------------------------------------------------------[0m [0;31mTypeError[0m Traceback (most recent call last) Cell [0;32mIn[6], line 3[0m [1;32m 1[0m sol1 [38;5;241m=[39m np[38;5;241m.[39marray([[38;5;241m0.60610368[39m, [38;5;241m4.0076268[39m, [38;5;241m0.0[39m, [38;5;241m0.56469864[39m]) [0;32m----> 3[0m [38;5;28mprint[39m([43mnp[49m[38;5;241;43m.[39;49m[43mallclose[49m[43m([49m[43ma1[49m[43m,[49m[43m [49m[43msol1[49m[43m)[49m) File [0;32m~/miniforge3/envs/myenv/lib/python3.9/site-packages/autograd/tracer.py:48[0m, in [0;36mprimitive.<locals>.f_wrapped[0;34m(*args, **kwargs)[0m [1;32m 46[0m [38;5;28;01mreturn[39;00m new_box(ans, trace, node) [1;32m 47[0m [38;5;28;01melse[39;00m: [0;32m---> 48[0m [38;5;28;01mreturn[39;00m [43mf_raw[49m[43m([49m[38;5;241;43m*[39;49m[43margs[49m[43m,[49m[43m [49m[38;5;241;43m*[39;49m[38;5;241;43m*[39;49m[43mkwargs[49m[43m)[49m File [0;32m~/miniforge3/envs/myenv/lib/python3.9/site-packages/numpy/core/numeric.py:2241[0m, in [0;36mallclose[0;34m(a, b, rtol, atol, equal_nan)[0m [1;32m 2170[0m [38;5;129m@array_function_dispatch[39m(_allclose_dispatcher) [1;32m 2171[0m [38;5;28;01mdef[39;00m [38;5;21mallclose[39m(a, b, rtol[38;5;241m=[39m[38;5;241m1.e-5[39m, atol[38;5;241m=[39m[38;5;241m1.e-8[39m, equal_nan[38;5;241m=[39m[38;5;28;01mFalse[39;00m): [1;32m 2172[0m [38;5;250m [39m[38;5;124;03m"""[39;00m [1;32m 2173[0m [38;5;124;03m Returns True if two arrays are element-wise equal within a tolerance.[39;00m [1;32m 2174[0m [0;32m (...)[0m [1;32m 2239[0m [1;32m 2240[0m [38;5;124;03m """[39;00m [0;32m-> 2241[0m res [38;5;241m=[39m [38;5;28mall[39m([43misclose[49m[43m([49m[43ma[49m[43m,[49m[43m [49m[43mb[49m[43m,[49m[43m [49m[43mrtol[49m[38;5;241;43m=[39;49m[43mrtol[49m[43m,[49m[43m [49m[43matol[49m[38;5;241;43m=[39;49m[43matol[49m[43m,[49m[43m [49m[43mequal_nan[49m[38;5;241;43m=[39;49m[43mequal_nan[49m[43m)[49m) [1;32m 2242[0m [38;5;28;01mreturn[39;00m [38;5;28mbool[39m(res) File [0;32m~/miniforge3/envs/myenv/lib/python3.9/site-packages/numpy/core/numeric.py:2348[0m, in [0;36misclose[0;34m(a, b, rtol, atol, equal_nan)[0m [1;32m 2345[0m dt [38;5;241m=[39m multiarray[38;5;241m.[39mresult_type(y, [38;5;241m1.[39m) [1;32m 2346[0m y [38;5;241m=[39m asanyarray(y, dtype[38;5;241m=[39mdt) [0;32m-> 2348[0m xfin [38;5;241m=[39m [43misfinite[49m[43m([49m[43mx[49m[43m)[49m [1;32m 2349[0m yfin [38;5;241m=[39m isfinite(y) [1;32m 2350[0m [38;5;28;01mif[39;00m [38;5;28mall[39m(xfin) [38;5;129;01mand[39;00m [38;5;28mall[39m(yfin): [0;31mTypeError[0m: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
In [ ]:
W2 = ...
b2 = ...In [ ]:
z2 = ...
a2 = ...In [ ]:
print(
np.allclose(np.exp(len(a2)), 2980.9579870417283)
) # This should evaluate to True if a2 has the correct shape :)In [ ]:
def create_layers(network_input_size, layer_output_sizes):
layers = []
i_size = network_input_size
for layer_output_size in layer_output_sizes:
W = ...
b = ...
layers.append((W, b))
i_size = layer_output_size
return layersIn [ ]:
def feed_forward_all_relu(layers, input):
a = input
for W, b in layers:
z = ...
a = ...
return aIn [ ]:
input_size = ...
layer_output_sizes = [...]
x = np.random.rand(input_size)
layers = ...
predict = ...
print(predict)In [ ]:
def feed_forward(input, layers, activation_funcs):
a = input
for (W, b), activation_func in zip(layers, activation_funcs):
z = ...
a = ...
return aIn [ ]:
network_input_size = ...
layer_output_sizes = [...]
activation_funcs = [ReLU, ReLU, sigmoid]
layers = ...
x = np.random.randn(network_input_size)
feed_forward(x, layers, activation_funcs)In [ ]:
def create_layers_batch(network_input_size, layer_output_sizes):
layers = []
i_size = network_input_size
for layer_output_size in layer_output_sizes:
W = ...
b = ...
layers.append((W, b))
i_size = layer_output_size
return layersIn [ ]:
inputs = np.random.rand(1000, 4)
def feed_forward_batch(inputs, layers, activation_funcs):
a = inputs
for (W, b), activation_func in zip(layers, activation_funcs):
z = ...
a = ...
return aIn [ ]:
network_input_size = ...
layer_output_sizes = [...]
activation_funcs = [...]
layers = create_layers_batch(network_input_size, layer_output_sizes)
x = np.random.randn(network_input_size)
feed_forward_batch(inputs, layers, activation_funcs)In [ ]:
iris = datasets.load_iris()
_, ax = plt.subplots()
scatter = ax.scatter(iris.data[:, 0], iris.data[:, 1], c=iris.target)
ax.set(xlabel=iris.feature_names[0], ylabel=iris.feature_names[1])
_ = ax.legend(
scatter.legend_elements()[0], iris.target_names, loc="lower right", title="Classes"
)In [ ]:
inputs = iris.data
# Since each prediction is a vector with a score for each of the three types of flowers,
# we need to make each target a vector with a 1 for the correct flower and a 0 for the others.
targets = np.zeros((len(iris.data), 3))
for i, t in enumerate(iris.target):
targets[i, t] = 1
def accuracy(predictions, targets):
one_hot_predictions = np.zeros(predictions.shape)
for i, prediction in enumerate(predictions):
one_hot_predictions[i, np.argmax(prediction)] = 1
return accuracy_score(one_hot_predictions, targets)In [ ]:
...
layers = ...In [ ]:
predictions = feed_forward_batch(inputs, layers, activation_funcs)In [ ]:
print(accuracy(predictions, targets))In [ ]:
def cross_entropy(predict, target):
return np.sum(-target * np.log(predict))
def cost(input, layers, activation_funcs, target):
predict = feed_forward_batch(input, layers, activation_funcs)
return cross_entropy(predict, target)In [ ]:
from autograd import grad
gradient_func = grad(
cost, 1
) # Taking the gradient wrt. the second input to the cost function, i.e. the layersIn [ ]:
layers_grad = gradient_func(
inputs, layers, activation_funcs, targets
) # Don't change thisIn [ ]:
def train_network(
inputs, layers, activation_funcs, targets, learning_rate=0.001, epochs=100
):
for i in range(epochs):
layers_grad = gradient_func(inputs, layers, activation_funcs, targets)
for (W, b), (W_g, b_g) in zip(layers, layers_grad):
W -= ...
b -= ...In [ ]:
...