Los frameworks
de deeplearning como Keras
y Pytorch
normalmente tienen una abstraccion llamada Capa
o Layer
que consiste un conjunto de tecnicas para el forward propagation
enpaquetadas en una API
simple con un metodo forward()
para llamarlos. Un ejemplo de esto sería una capa Lineal
:
import os
import sys
module_path = os.path.abspath(os.path.join('..'))
if module_path not in sys.path:
sys.path.append(module_path)
import numpy as np
from lightdlf_old.cpu.core import Tensor
class Layer(object):
def __init__(self):
self.parameters = list()
def get_parameters(self):
return self.parameters
class Linear(Layer):
def __init__(self, n_inputs, n_outputs):
super().__init__()
W = np.random.randn(n_inputs, n_outputs)*np.sqrt(2.0/(n_inputs))
self.weight = Tensor(W, autograd=True)
self.bias = Tensor(np.zeros(n_outputs), autograd=True)
self.parameters.append(self.weight)
self.parameters.append(self.bias)
def forward(self, input):
return Tensor.mm(input, self.weight) + self.bias.expand(0, len(input.data))
Notese que la clase Linear
inicializa automáticamente los pesos de la capa y tiene un nuevo Tensor, llamado bias
.
La clase Linear
hereda de la clase Layer
la cual solo contienen el método get_parameters
. Esta clase permite definir capaz más complejas (como capas conteniendo otras capas). Solo se necesita sobreescribir el metodo get_parameters
para controlar que tensores son pasados al optimizador (como SGD
)
Stackeando capas¶
class Sequential(Layer):
def __init__(self, layers=list()):
super().__init__()
self.layers = layers
def add(self, layer):
self.layers.append(layer)
def forward(self, input):
for layer in self.layers:
input = layer.forward(input)
return input
def get_parameters(self):
params = list()
for l in self.layers:
params += l.get_parameters()
return params
Creando el primer modelo secuencial lineal o también llamado Perceptron Multicapa
¶
from lightdlf_old.cpu.optimizers import SGD
np.random.seed(0)
data = Tensor(np.array([[0,0],[0,1],[1,0],[1,1]]), autograd=True) # (4,2)
target = Tensor(np.array([[0],[1],[0],[1]]), autograd=True) # (4,1)
model = Sequential([Linear(2,3), Linear(3,1)])
optim = SGD(model.get_parameters(), alpha=0.05)
for i in range(10):
# Predecir
pred = model.forward(data)
# Comparar
loss = ((pred - target) * (pred - target)).sum(0)
# Aprender
loss.backward(Tensor(np.ones_like(loss.data)))
optim.step()
print(loss)
Capa Mean Squared Error
¶
Se pueden crear capas que son funciones sobre las entradas, como la funcion de perdida Mean Squared Error
class MSELoss(Layer):
def __init__(self):
super().__init__()
def forward(self, pred, target):
return ((pred - target) * (pred - target)).sum(0)
from lightdlf_old.cpu.optimizers import SGD
np.random.seed(0)
data = Tensor(np.array([[0,0],[0,1],[1,0],[1,1]]), autograd=True) # (4,2)
target = Tensor(np.array([[0],[1],[0],[1]]), autograd=True) # (4,1)
model = Sequential([Linear(2,3), Linear(3,1)])
criterion = MSELoss()
optim = SGD(model.get_parameters(), alpha=0.05)
for i in range(10):
# Predecir
pred = model.forward(data)
# Comparar
loss = criterion.forward(pred, target)
# Aprender
loss.backward(Tensor(np.ones_like(loss.data)))
optim.step()
print(loss)