| 85 | return g; |
| 86 | } |
| 87 | MatrixXf featureGradient( const MatrixXf & a, const MatrixXf & b ) const { |
| 88 | if (ntype_ == NO_NORMALIZATION ) |
| 89 | return kernelGradient( a, b ); |
| 90 | else if (ntype_ == NORMALIZE_SYMMETRIC ) { |
| 91 | MatrixXf fa = lattice_.compute( a*norm_.asDiagonal(), true ); |
| 92 | MatrixXf fb = lattice_.compute( b*norm_.asDiagonal() ); |
| 93 | MatrixXf ones = MatrixXf::Ones( a.rows(), a.cols() ); |
| 94 | VectorXf norm3 = norm_.array()*norm_.array()*norm_.array(); |
| 95 | MatrixXf r = kernelGradient( 0.5*( a.array()*fb.array() + fa.array()*b.array() ).matrix()*norm3.asDiagonal(), ones ); |
| 96 | return - r + kernelGradient( a*norm_.asDiagonal(), b*norm_.asDiagonal() ); |
| 97 | } |
| 98 | else if (ntype_ == NORMALIZE_AFTER ) { |
| 99 | MatrixXf fb = lattice_.compute( b ); |
| 100 | |
| 101 | MatrixXf ones = MatrixXf::Ones( a.rows(), a.cols() ); |
| 102 | VectorXf norm2 = norm_.array()*norm_.array(); |
| 103 | MatrixXf r = kernelGradient( ( a.array()*fb.array() ).matrix()*norm2.asDiagonal(), ones ); |
| 104 | return - r + kernelGradient( a*norm_.asDiagonal(), b ); |
| 105 | } |
| 106 | else /*if (ntype_ == NORMALIZE_BEFORE )*/ { |
| 107 | MatrixXf fa = lattice_.compute( a, true ); |
| 108 | |
| 109 | MatrixXf ones = MatrixXf::Ones( a.rows(), a.cols() ); |
| 110 | VectorXf norm2 = norm_.array()*norm_.array(); |
| 111 | MatrixXf r = kernelGradient( ( fa.array()*b.array() ).matrix()*norm2.asDiagonal(), ones ); |
| 112 | return -r+kernelGradient( a, b*norm_.asDiagonal() ); |
| 113 | } |
| 114 | } |
| 115 | public: |
| 116 | DenseKernel(const MatrixXf & f, KernelType ktype, NormalizationType ntype):f_(f), ktype_(ktype), ntype_(ntype) { |
| 117 | if (ktype_ == DIAG_KERNEL) |