| 51 | |
| 52 | |
| 53 | class Dense(Layer, ParamMixin): |
| 54 | def __init__(self, output_dim, parameters=None): |
| 55 | """A fully connected layer. |
| 56 | |
| 57 | Parameters |
| 58 | ---------- |
| 59 | output_dim : int |
| 60 | """ |
| 61 | self._params = parameters |
| 62 | self.output_dim = output_dim |
| 63 | self.last_input = None |
| 64 | |
| 65 | if parameters is None: |
| 66 | self._params = Parameters() |
| 67 | |
| 68 | def setup(self, x_shape): |
| 69 | self._params.setup_weights((x_shape[1], self.output_dim)) |
| 70 | |
| 71 | def forward_pass(self, X): |
| 72 | self.last_input = X |
| 73 | return self.weight(X) |
| 74 | |
| 75 | def weight(self, X): |
| 76 | W = np.dot(X, self._params["W"]) |
| 77 | return W + self._params["b"] |
| 78 | |
| 79 | def backward_pass(self, delta): |
| 80 | dW = np.dot(self.last_input.T, delta) |
| 81 | db = np.sum(delta, axis=0) |
| 82 | |
| 83 | # Update gradient values |
| 84 | self._params.update_grad("W", dW) |
| 85 | self._params.update_grad("b", db) |
| 86 | return np.dot(delta, self._params["W"].T) |
| 87 | |
| 88 | def shape(self, x_shape): |
| 89 | return x_shape[0], self.output_dim |
| 90 | |
| 91 | |
| 92 | class Activation(Layer): |
no outgoing calls