このようなデータを当てはめてみることにします。
このようになります。高い表現力があることがわかります。
コードはこちら。行列計算にはmeschというライブラリを使いました。
// kernelRegression // x:data // dimention: x's dimention // y: label of x // num: number of data // result: coeffience double *kernelRegression(double **x,int dimention,double *y,int num,double gamma,double regilarization){ VEC *label; MAT *gram,*ident,*inv; int i,j; double *result; ident = m_get(num,num); label = v_get(num); memcpy(label->ve,y,sizeof(double)*num); gram = m_get(num,num); ident = m_get(num,num); for(i=0;i<num;i++){ for(j=0;j<num;j++){ gram->me[i][j]=kernel(x[i],x[j],dimention,gamma); } } inv=m_add(gram,sm_mlt(regilarization,m_ident(ident),NULL),NULL); inv=m_inverse(inv,NULL); VEC *coefficient=v_get(num); mv_mlt(inv,label,coefficient); result=malloc(sizeof(double)*num); memcpy(result,coefficient->ve,sizeof(double)*num); m_free(ident); m_free(gram); m_free(inv); v_free(label); v_free(coefficient); return result; }}カーネルがこちら。
double kernel(double *x1,double *x2,int num,double gamma){ VEC *xVector,*yVector,*diffVector; int i; xVector=v_get(num); memcpy(xVector->ve,x1,sizeof(double)*num); yVector=v_get(num); memcpy(yVector->ve,x2,sizeof(double)*num); diffVector=v_sub(xVector,yVector,NULL); double sum=0.0; for(i=0;i<num;i++){ sum+=diffVector->ve[i]*diffVector->ve[i]; } v_free(diffVector); v_free(xVector); v_free(yVector); return exp(-gamma*sum); }全ソースはgithubに上げています。
https://github.com/y-mitsui/kernelRegression
このように高い表現力を持つカーネル回帰ですが、多項式の次数がサンプル数と同じなのでサンプル数が増えると計算量が増えます。
また、線形の回帰分析と同様、誤差関数に二乗誤差を用いているので外れ値の影響を受けやすく、外れ値に対して積極的に当てはめようと するので、他のデータの当てはまりが悪ることがあります。
これらの問題を抑制させる回帰分析がサポートベクトル回帰で、そちらのほうがよく使われるように思います。