ProductKernel.cpp

Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of the GNU General Public License as published by
00004  * the Free Software Foundation; either version 3 of the License, or
00005  * (at your option) any later version.
00006  *
00007  * Copyright (C) 2012 Jacob Walker
00008  * 
00009  * Code adapted from CCombinedKernel
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 //Adapted from CCombinedKernel
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         // skip over features - the custom kernel does not need any
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 //Adapted from CCombinedKernel
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 //Adapted from CCombinedKernel
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 //Adapted from CCombinedKernel
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 //Adapted from CCombinedKernel
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 //Adapted from CCombinedKernel
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 //Adapted from CCombinedKernel
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 //Adapted from CCombinedKernel
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation