| 189 | } |
| 190 | |
| 191 | pub fn derivatives(&self, examples: &Matrix<f64>, targets: &Matrix<f64>) -> Vec<Matrix<f64>> { |
| 192 | |
| 193 | assert!(self.layers.len() >= 2, "At least two layers are required."); |
| 194 | assert!(examples.rows() == targets.rows(), "Number of examples and labels mismatch."); |
| 195 | assert!(examples.cols() == self.input_size(), "Dimension of input vector does not match."); |
| 196 | assert!(self.output_size() == targets.cols(), "Dimension of target values mismatch."); |
| 197 | |
| 198 | // create accumulator for the deltas |
| 199 | let mut acc_d = self.params.iter().map(|ref m| Matrix::fill(0.0, m.rows(), m.cols())).collect(); |
| 200 | |
| 201 | // x = example |
| 202 | // t = target vector |
| 203 | for (x, t) in examples.row_iter().zip(targets.row_iter()) { |
| 204 | |
| 205 | let (av, zv) = self.feedforward(x); |
| 206 | let deltas = self.backprop(&av.last().unwrap().clone(), t, &(av.clone(), zv)); |
| 207 | self.update(&mut acc_d, &deltas, &av); |
| 208 | } |
| 209 | |
| 210 | for i in &mut acc_d { |
| 211 | i.idiv_scalar(examples.rows() as f64); |
| 212 | } |
| 213 | acc_d |
| 214 | // TODO tests |
| 215 | } |
| 216 | |
| 217 | /// Updates the parameters of the network. |
| 218 | /// |