Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <shogun/kernel/ProductKernel.h>
00013 #include <shogun/kernel/CustomKernel.h>
00014
00015 using namespace shogun;
00016
00017 CProductKernel::CProductKernel(int32_t size)
00018 : CKernel(size)
00019 {
00020 init();
00021
00022 SG_INFO("Product kernel created (%p)\n", this) ;
00023 }
00024
00025 CProductKernel::~CProductKernel()
00026 {
00027 cleanup();
00028 SG_UNREF(kernel_list);
00029
00030 SG_INFO("Product kernel deleted (%p).\n", this);
00031 }
00032
00033
00034 bool CProductKernel::init(CFeatures* l, CFeatures* r)
00035 {
00036 CKernel::init(l,r);
00037 ASSERT(l->get_feature_class()==C_COMBINED);
00038 ASSERT(r->get_feature_class()==C_COMBINED);
00039 ASSERT(l->get_feature_type()==F_UNKNOWN);
00040 ASSERT(r->get_feature_type()==F_UNKNOWN);
00041
00042 CFeatures* lf=NULL;
00043 CFeatures* rf=NULL;
00044 CKernel* k=NULL;
00045
00046 bool result=true;
00047
00048 CListElement* lfc = NULL;
00049 CListElement* rfc = NULL;
00050 lf=((CCombinedFeatures*) l)->get_first_feature_obj(lfc);
00051 rf=((CCombinedFeatures*) r)->get_first_feature_obj(rfc);
00052 CListElement* current = NULL;
00053 k=get_first_kernel(current);
00054
00055 while ( result && k )
00056 {
00057
00058 if (k->get_kernel_type() != K_CUSTOM)
00059 {
00060 if (!lf || !rf)
00061 {
00062 SG_UNREF(lf);
00063 SG_UNREF(rf);
00064 SG_UNREF(k);
00065 SG_ERROR( "ProductKernel: Number of features/kernels does not match - bailing out\n");
00066 }
00067
00068 SG_DEBUG( "Initializing 0x%p - \"%s\"\n", this, k->get_name());
00069 result=k->init(lf,rf);
00070 SG_UNREF(lf);
00071 SG_UNREF(rf);
00072
00073 lf=((CCombinedFeatures*) l)->get_next_feature_obj(lfc) ;
00074 rf=((CCombinedFeatures*) r)->get_next_feature_obj(rfc) ;
00075 }
00076 else
00077 {
00078 SG_DEBUG( "Initializing 0x%p - \"%s\" (skipping init, this is a CUSTOM kernel)\n", this, k->get_name());
00079 if (!k->has_features())
00080 SG_ERROR("No kernel matrix was assigned to this Custom kernel\n");
00081 if (k->get_num_vec_lhs() != num_lhs)
00082 SG_ERROR("Number of lhs-feature vectors (%d) not match with number of rows (%d) of custom kernel\n", num_lhs, k->get_num_vec_lhs());
00083 if (k->get_num_vec_rhs() != num_rhs)
00084 SG_ERROR("Number of rhs-feature vectors (%d) not match with number of cols (%d) of custom kernel\n", num_rhs, k->get_num_vec_rhs());
00085 }
00086
00087 SG_UNREF(k);
00088 k=get_next_kernel(current) ;
00089 }
00090
00091 if (!result)
00092 {
00093 SG_INFO( "ProductKernel: Initialising the following kernel failed\n");
00094 if (k)
00095 k->list_kernel();
00096 else
00097 SG_INFO( "<NULL>\n");
00098 return false;
00099 }
00100
00101 if ((lf!=NULL) || (rf!=NULL) || (k!=NULL))
00102 {
00103 SG_UNREF(lf);
00104 SG_UNREF(rf);
00105 SG_UNREF(k);
00106 SG_ERROR( "ProductKernel: Number of features/kernels does not match - bailing out\n");
00107 }
00108
00109 initialized=true;
00110 return true;
00111 }
00112
00113
00114 void CProductKernel::remove_lhs()
00115 {
00116 CListElement* current = NULL ;
00117 CKernel* k=get_first_kernel(current);
00118
00119 while (k)
00120 {
00121 if (k->get_kernel_type() != K_CUSTOM)
00122 k->remove_lhs();
00123
00124 SG_UNREF(k);
00125 k=get_next_kernel(current);
00126 }
00127 CKernel::remove_lhs();
00128
00129 num_lhs=0;
00130 }
00131
00132
00133 void CProductKernel::remove_rhs()
00134 {
00135 CListElement* current = NULL ;
00136 CKernel* k=get_first_kernel(current);
00137
00138 while (k)
00139 {
00140 if (k->get_kernel_type() != K_CUSTOM)
00141 k->remove_rhs();
00142 SG_UNREF(k);
00143 k=get_next_kernel(current);
00144 }
00145 CKernel::remove_rhs();
00146
00147 num_rhs=0;
00148 }
00149
00150
00151 void CProductKernel::remove_lhs_and_rhs()
00152 {
00153 CListElement* current = NULL ;
00154 CKernel* k=get_first_kernel(current);
00155
00156 while (k)
00157 {
00158 if (k->get_kernel_type() != K_CUSTOM)
00159 k->remove_lhs_and_rhs();
00160 SG_UNREF(k);
00161 k=get_next_kernel(current);
00162 }
00163
00164 CKernel::remove_lhs_and_rhs();
00165
00166 num_lhs=0;
00167 num_rhs=0;
00168 }
00169
00170
00171 void CProductKernel::cleanup()
00172 {
00173 CListElement* current = NULL ;
00174 CKernel* k=get_first_kernel(current);
00175
00176 while (k)
00177 {
00178 k->cleanup();
00179 SG_UNREF(k);
00180 k=get_next_kernel(current);
00181 }
00182
00183 CKernel::cleanup();
00184
00185 num_lhs=0;
00186 num_rhs=0;
00187 }
00188
00189
00190 void CProductKernel::list_kernels()
00191 {
00192 CKernel* k;
00193
00194 SG_INFO( "BEGIN PRODUCT KERNEL LIST - ");
00195 this->list_kernel();
00196
00197 CListElement* current = NULL ;
00198 k=get_first_kernel(current);
00199 while (k)
00200 {
00201 k->list_kernel();
00202 SG_UNREF(k);
00203 k=get_next_kernel(current);
00204 }
00205 SG_INFO( "END PRODUCT KERNEL LIST - ");
00206 }
00207
00208
00209 float64_t CProductKernel::compute(int32_t x, int32_t y)
00210 {
00211 float64_t result=1;
00212 CListElement* current = NULL ;
00213 CKernel* k=get_first_kernel(current);
00214 while (k)
00215 {
00216 result *= k->get_combined_kernel_weight() * k->kernel(x,y);
00217 SG_UNREF(k);
00218 k=get_next_kernel(current);
00219 }
00220
00221 return result;
00222 }
00223
00224
00225
00226 bool CProductKernel::precompute_subkernels()
00227 {
00228 CKernel* k = get_first_kernel();
00229
00230 if (!k)
00231 return false;
00232
00233 CList* new_kernel_list = new CList(true);
00234
00235 while(k)
00236 {
00237 new_kernel_list->append_element(new CCustomKernel(k));
00238 SG_UNREF(k);
00239 k = get_next_kernel();
00240 }
00241
00242 SG_UNREF(kernel_list);
00243 kernel_list=new_kernel_list;
00244 SG_REF(kernel_list);
00245
00246 return true;
00247 }
00248
00249 void CProductKernel::init()
00250 {
00251 initialized=false;
00252
00253 properties = KP_NONE;
00254 kernel_list=new CList(true);
00255 SG_REF(kernel_list);
00256
00257 SG_ADD((CSGObject**) &kernel_list, "kernel_list", "List of kernels.",
00258 MS_AVAILABLE);
00259 SG_ADD(&initialized, "initialized", "Whether kernel is ready to be used.",
00260 MS_NOT_AVAILABLE);
00261 }
00262
00263 SGMatrix<float64_t> CProductKernel::get_parameter_gradient(TParameter* param,
00264 CSGObject* obj, index_t index)
00265 {
00266
00267 CListElement* current = NULL ;
00268 CKernel* k = get_first_kernel(current);
00269 SGMatrix<float64_t> temp_kernel = k->get_kernel_matrix();
00270
00271 bool found_derivative = false;
00272
00273 for (index_t g = 0; g < temp_kernel.num_rows; g++)
00274 {
00275 for (int h = 0; h < temp_kernel.num_cols; h++)
00276 temp_kernel(g,h) = 1.0;
00277 }
00278
00279 while(k)
00280 {
00281 SGMatrix<float64_t> cur_matrix = k->get_kernel_matrix();
00282 SGMatrix<float64_t> derivative =
00283 k->get_parameter_gradient(param, obj, index);
00284
00285 if (derivative.num_cols*derivative.num_rows > 0)
00286 {
00287 found_derivative = true;
00288 for (index_t g = 0; g < derivative.num_rows; g++)
00289 {
00290 for (index_t h = 0; h < derivative.num_cols; h++)
00291 temp_kernel(g,h) *= derivative(g,h);
00292 }
00293
00294 }
00295
00296 else
00297 {
00298 for (index_t g = 0; g < cur_matrix.num_rows; g++)
00299 {
00300 for (index_t h = 0; h < cur_matrix.num_cols; h++)
00301 temp_kernel(g,h) *= cur_matrix(g,h);
00302 }
00303
00304 }
00305
00306 SG_UNREF(k);
00307 k = get_next_kernel(current);
00308 }
00309
00310 if (found_derivative)
00311 return temp_kernel;
00312
00313 else
00314 return SGMatrix<float64_t>();
00315 }