/********************************************************************** * MSE Class ***********************************************************************/ double MSE::cost(cube pred, cube y){ dbg_assert(y.n_cols == 1 && y.n_slices == 1); pred.reshape(pred.n_elem,1,1); y.reshape(y.n_elem,1,1); double retn = 0.0f; for(int i=0; i < y.n_elem; i++) { retn += pow(pred(i,0,0) - y(i,0,0),2); } retn /= y.n_elem; retn *= 0.5f; //return(retn); return(0.5 * mean(mean(square(pred.slice(0) - y.slice(0))))); }
cube ConvLayer::backward(cube delta) { // NOTE: delta may come from a linear layer delta.reshape(_a.n_rows, _a.n_cols, _a.n_slices); if(!_prev) { dbg_print("null pointer to _prev in ConvLayer::backward"); return zeros<cube>(0,0,0); } // Compute Weight Updates cube input = addPadding(_prev->getActivationCube(), _ksize); for(int i = 0; i < _units; i++){ // dz_dw for(int j=0; j < input.n_slices; j++) { _dw(i).slice(j) = conv2d(input.slice(j), delta.slice(i)); } // dz_db _db(0,0,i) = accu(delta.slice(i)); } // Compute next delta int nr = _prev->getActivationCube().n_rows; int nc = _prev->getActivationCube().n_cols; int ns = _prev->getActivationCube().n_slices; delta = addPadding(delta, _ksize); cube next_delta = zeros<cube>(nr,nc,ns); for(int i=0; i < ns; i++){ for(int j=0; j < _units; j++) { next_delta.slice(i) += conv2d( delta.slice(j), fliplr(flipud(_w(j).slice(i))) ); } } if(_prev) { return(_prev->backward(next_delta)); } return(next_delta); }