typename std::enable_if<has_public_member_grad<T>::value>::type apply_grad(cube<real>& g, const cube<real>& f, const T& fn) noexcept { real* gp = g.data(); const real* fp = f.data(); size_t n = g.num_elements(); for ( size_t i = 0; i < n; ++i ) gp[i] *= fn.grad(fp[i]); }
inline void convolve_constant( cube<T> const & a, identity_t<T> b, cube<T> & r) noexcept { ZI_ASSERT(size(a)==size(r)); T const * ap = a.data(); T * rp = r.data(); for ( size_t i = 0; i < r.num_elements(); ++i ) rp[i] = ap[i] * b; }
inline T convolve_constant_flipped( cube<T> const & a, cube<T> const & b ) noexcept { ZI_ASSERT(size(a)==size(b)); T r = 0; T const * ap = a.data(); T const * bp = b.data(); for ( size_t i = 0; i < a.num_elements(); ++i ) r += ap[i] * bp[i]; return r; }
// performs inplace dropout backward inline void dropout_backward(cube<real> & g) { ZI_ASSERT(mask_); size_t s = g.num_elements(); for ( size_t i = 0; i < s; ++i ) { if ( mask_->data()[i] ) g.data()[i] *= scale(); else g.data()[i] = static_cast<real>(0); } // Should we reset mask_ here? }
void apply(cube<real>& v, real bias) noexcept override { real* d = v.data(); size_t n = v.num_elements(); for ( size_t i = 0; i < n; ++i ) d[i] = f_(d[i] + bias); }
inline cube_p<T> convolve_sparse( cube<T> const & a, cube<T> const & b, vec3i const & s ) { if ( s == vec3i::one ) { return convolve(a,b); } vec3i as = size(a); vec3i bs = size(b); vec3i rs = size(a) - (size(b) - vec3i::one) * s; cube_p<T> r = get_cube<T>(rs); int a_strides[3] = { s[2], as[2]*s[1], as[2]*as[1]*s[0] }; int r_strides[3] = { s[2], rs[2]*s[1], rs[2]*rs[1]*s[0] }; // sparseness for (int xs=0; xs<s[0]; xs++) for (int ys=0; ys<s[1]; ys++) for (int zs=0; zs<s[2]; zs++) { vec3i in_size( (as[0]-1)/s[0] + (xs == 0 ? 1 : 0), (as[1]-1)/s[1] + (ys == 0 ? 1 : 0), (as[2]-1)/s[2] + (zs == 0 ? 1 : 0) ); const T* in_ptr = &(a[xs][ys][zs]); T* out_ptr = &((*r)[xs][ys][zs]); #ifdef ZNN_USE_FLOATS int status = vslsConvExec( conv_plans.get(in_size, bs), in_ptr, a_strides, b.data(), NULL, out_ptr, r_strides); #else int status = vsldConvExec( conv_plans.get(in_size, bs), in_ptr, a_strides, b.data(), NULL, out_ptr, r_strides); #endif } return r; }
// performs inplace dropout and returns dropout mask inline void dropout_forward(cube<real>& f) { if ( !mask_ ) { mask_ = get_cube<bool>(size(f)); } // new random mask bernoulli_init<bool>(ratio_).initialize(mask_); size_t s = f.num_elements(); for ( size_t i = 0; i < s; ++i ) { // dropout if ( mask_->data()[i] ) f.data()[i] *= scale(); else f.data()[i] = static_cast<real>(0); } }
inline void convolve_inverse( cube<T> const & a, cube<T> const & b, cube<T> const & r) noexcept { ZI_ASSERT(size(r)==(size(a)+size(b)-vec3i::one)); auto tmp = get_copy(b); flip(*tmp); #ifdef ZNN_USE_FLOATS int status = vslsConvExec(conv_plans.get_inv(size(a),size(b)), a.data(), NULL, tmp->data(), NULL, r.data(), NULL); #else int status = vsldConvExec(conv_plans.get_inv(size(a),size(b)), a.data(), NULL, tmp->data(), NULL, r.data(), NULL); }
void forward( cube<real>& in, cube<complex>& out ) { ZI_ASSERT(size(out)==fft_complex_size(in)); ZI_ASSERT(size(in)==sz); fft_plan plan = fft_plans.get_forward( vec3i(in.shape()[0],in.shape()[1],in.shape()[2])); MKL_LONG status; # ifdef MEASURE_FFT_RUNTIME zi::wall_timer wt; # endif status = DftiComputeForward(*plan, reinterpret_cast<real*>(in.data()), reinterpret_cast<real*>(out.data())); # ifdef MEASURE_FFT_RUNTIME fft_stats.add(wt.elapsed<real>()); # endif }
static void backward( cube<complex>& in, cube<real>& out ) { ZI_ASSERT(in.shape()[0]==out.shape()[0]); ZI_ASSERT(in.shape()[1]==out.shape()[1]); ZI_ASSERT((out.shape()[2]/2+1)==in.shape()[2]); fft_plan plan = fft_plans.get_backward( vec3i(out.shape()[0],out.shape()[1],out.shape()[2])); MKL_LONG status; # ifdef MEASURE_FFT_RUNTIME zi::wall_timer wt; # endif status = DftiComputeBackward(*plan, reinterpret_cast<real*>(in.data()), reinterpret_cast<real*>(out.data())); # ifdef MEASURE_FFT_RUNTIME fft_stats.add(wt.elapsed<real>()); # endif }
std::tuple<real,real,cube_p<real>> square_loss( cube<real> const & cprop, cube<real> const & clab ) { std::tuple<real,real,cube_p<real>> ret; std::get<0>(ret) = 0; std::get<1>(ret) = 0; std::get<2>(ret) = get_copy(cprop); real* grad = std::get<2>(ret)->data(); const real* lab = clab.data(); long_t n = clab.num_elements(); for ( long_t i = 0; i < n; ++i ) { std::get<1>(ret) += ( grad[i] > 0.5 ? ( lab[i] > 0.5 ? 0 : 1 ) : ( lab[i] > 0.5 ? 1 : 0 ) ); grad[i] -= lab[i]; std::get<0>(ret) += grad[i]*grad[i]; grad[i] *= 2; } return ret; }
inline void convolve( cube<T> const & a, cube<T> const & b, cube<T> & r) noexcept { ZI_ASSERT(size(r)==(vec3i::one+size(a)-size(b))); #ifdef ZNN_USE_FLOATS int status = vslsConvExec(conv_plans.get(size(a),size(b)), a.data(), NULL, b.data(), NULL, r.data(), NULL); #else int status = vsldConvExec(conv_plans.get(size(a),size(b)), a.data(), NULL, b.data(), NULL, r.data(), NULL); #endif }