Spaces:
No application file
No application file
File size: 3,490 Bytes
027680f | 1 2 3 4 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 105 106 107 108 109 110 111 112 | import numpy as np
from abc import ABC, abstractmethod
class Layer(ABC):
def __init__(self, input_size, output_size):
self.input = None
self.output = None
self.input_size = input_size
self.output_size = output_size
self.weights = np.random.randn(input_size, output_size) * np.sqrt(2. / input_size)
self.bias = np.zeros((1, output_size))
@staticmethod
def activate(z, activation: str):
if activation == 'sigmoid':
return 1 / (1 + np.exp(-z))
elif activation == 'relu':
return np.maximum(0, z)
else:
print("Undefined activation type")
return None
@staticmethod
def derivative(activation: str, z):
if activation == 'sigmoid':
return z * (1 - z)
elif activation == 'relu':
return np.where(z > 0, 1, 0)
else:
print("Undefined activation type")
return None
@abstractmethod
def feedforward(self, x_train):
pass
@abstractmethod
def backpropagation(self, x_train, y_train, learning_rate):
pass
class Dense(Layer):
def __init__(self, input_size, output_size, activation: str):
super().__init__(input_size, output_size)
self.activation = activation
def feedforward(self, input):
self.input = input
z = np.dot(self.input, self.weights) + self.bias
self.output = self.activate(z, self.activation)
return self.output
def backpropagation(self, error, learning_rate):
d = self.derivative(self.activation, self.output)
db = np.sum(error * d, axis=0, keepdims=True)
dW = np.dot(self.input.T, error * d)
input_error = np.dot(error * d, self.weights.T)
self.weights -= learning_rate * dW
self.bias -= learning_rate * db
return input_error
class MLP:
def __init__(self):
self.layers = []
@staticmethod
def loss_MSE(y_train, yhat):
loss = np.mean(np.square(yhat - y_train))
return loss
@staticmethod
def loss_cross(y_train, yhat):
epsilon = 1e-9 # avoid log(0)
loss = -np.sum(y_train * np.log(yhat + epsilon)) / y_train.shape[0]
return loss
def addlayer(self, layer: Dense):
self.layers.append(layer)
def predict(self, input):
for layer in self.layers:
input = layer.feedforward(input)
return input
def fit(self, x_train, y_train, learning_rate=0.01, batch_size=8, epochs=10, loss_type: str = 'MSE'):
num_samples = x_train.shape[0]
for epoch in range(epochs):
indices = np.arange(num_samples)
np.random.shuffle(indices)
x_train = x_train[indices]
y_train = y_train[indices]
loss = 0
for i in range(0, num_samples, batch_size):
x_batch = x_train[i: i + batch_size]
y_batch = y_train[i: i + batch_size]
output = self.predict(input=x_batch)
error = output - y_batch
if loss_type == 'MSE':
loss += self.loss_MSE(y_batch, output)
else:
loss += self.loss_cross(y_batch, output)
for layer in reversed(self.layers):
error = layer.backpropagation(error, learning_rate)
print(f'Epoch {epoch + 1}/{epochs}, Loss: {loss / (num_samples // batch_size)}')
|