SHOGUN
v2.0.0
|
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 * Written (W) 1999-2009 Soeren Sonnenburg 00008 * Written (W) 2012 Heiko Strathmann 00009 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society 00010 */ 00011 00012 #ifndef _CUSTOMKERNEL_H___ 00013 #define _CUSTOMKERNEL_H___ 00014 00015 #include <shogun/mathematics/Math.h> 00016 #include <shogun/lib/common.h> 00017 #include <shogun/kernel/Kernel.h> 00018 #include <shogun/features/Features.h> 00019 00020 namespace shogun 00021 { 00033 class CCustomKernel: public CKernel 00034 { 00035 void init(); 00036 00037 public: 00039 CCustomKernel(); 00040 00046 CCustomKernel(CKernel* k); 00047 00055 CCustomKernel(SGMatrix<float64_t> km); 00056 00064 CCustomKernel(SGMatrix<float32_t> km); 00065 00069 virtual ~CCustomKernel(); 00070 00083 virtual bool dummy_init(int32_t rows, int32_t cols); 00084 00093 virtual bool init(CFeatures* l, CFeatures* r); 00094 00096 virtual void cleanup(); 00097 00099 void cleanup_custom(); 00100 00105 inline virtual EKernelType get_kernel_type() { return K_CUSTOM; } 00106 00111 inline virtual EFeatureType get_feature_type() { return F_ANY; } 00112 00117 inline virtual EFeatureClass get_feature_class() { return C_ANY; } 00118 00123 virtual const char* get_name() const { return "CustomKernel"; } 00124 00136 bool set_triangle_kernel_matrix_from_triangle( 00137 SGVector<float64_t> tri_kernel_matrix) 00138 { 00139 if (m_row_subset_stack->has_subsets() || m_col_subset_stack->has_subsets()) 00140 { 00141 SG_ERROR("%s::set_triangle_kernel_matrix_from_triangle not" 00142 " possible with subset. Remove first\n", get_name()); 00143 } 00144 return set_triangle_kernel_matrix_from_triangle_generic(tri_kernel_matrix); 00145 } 00146 00158 template <class T> 00159 bool set_triangle_kernel_matrix_from_triangle_generic( 00160 SGVector<T> tri_kernel_matrix) 00161 { 00162 if (m_row_subset_stack->has_subsets() || m_col_subset_stack->has_subsets()) 00163 { 00164 SG_ERROR("%s::set_triangle_kernel_matrix_from_triangle_generic " 00165 "not possible with subset. Remove first\n", get_name()); 00166 } 00167 ASSERT(tri_kernel_matrix.vector); 00168 00169 int64_t len = tri_kernel_matrix.vlen; 00170 int64_t cols = (int64_t) floor(-0.5 + CMath::sqrt(0.25+2*len)); 00171 00172 if (cols*(cols+1)/2 != len) 00173 { 00174 SG_ERROR("km should be a vector containing a lower triangle matrix, with len=cols*(cols+1)/2 elements\n"); 00175 return false; 00176 } 00177 00178 cleanup_custom(); 00179 SG_DEBUG( "using custom kernel of size %dx%d\n", cols,cols); 00180 00181 kmatrix=SGMatrix<float32_t>(SG_MALLOC(float32_t, len), cols, cols); 00182 upper_diagonal=true; 00183 00184 for (int64_t i=0; i<len; i++) 00185 kmatrix.matrix[i]=tri_kernel_matrix.vector[i]; 00186 00187 dummy_init(cols,cols); 00188 return true; 00189 } 00190 00200 inline bool set_triangle_kernel_matrix_from_full( 00201 SGMatrix<float64_t> full_kernel_matrix) 00202 { 00203 return set_triangle_kernel_matrix_from_full_generic(full_kernel_matrix); 00204 } 00205 00213 template <class T> 00214 bool set_triangle_kernel_matrix_from_full_generic( 00215 SGMatrix<T> full_kernel_matrix) 00216 { 00217 if (m_row_subset_stack->has_subsets() || m_col_subset_stack->has_subsets()) 00218 { 00219 SG_ERROR("%s::set_triangle_kernel_matrix_from_full_generic " 00220 "not possible with subset. Remove first\n", get_name()); 00221 } 00222 00223 int32_t rows = full_kernel_matrix.num_rows; 00224 int32_t cols = full_kernel_matrix.num_cols; 00225 ASSERT(rows==cols); 00226 00227 cleanup_custom(); 00228 SG_DEBUG( "using custom kernel of size %dx%d\n", cols,cols); 00229 00230 kmatrix=SGMatrix<float32_t>(SG_MALLOC(float32_t, cols*(cols+1)/2), rows, cols); 00231 upper_diagonal = true; 00232 00233 for (int64_t row=0; row<rows; row++) 00234 { 00235 for (int64_t col=row; col<cols; col++) 00236 { 00237 int64_t idx=row * cols - row*(row+1)/2 + col; 00238 kmatrix.matrix[idx] = full_kernel_matrix.matrix[col*rows+row]; 00239 } 00240 } 00241 00242 dummy_init(rows, cols); 00243 return true; 00244 } 00245 00254 bool set_full_kernel_matrix_from_full( 00255 SGMatrix<float32_t> full_kernel_matrix) 00256 { 00257 if (m_row_subset_stack->has_subsets() || m_col_subset_stack->has_subsets()) 00258 { 00259 SG_ERROR("%s::set_full_kernel_matrix_from_full " 00260 "not possible with subset. Remove first\n", get_name()); 00261 } 00262 00263 cleanup_custom(); 00264 kmatrix=full_kernel_matrix; 00265 dummy_init(kmatrix.num_rows, kmatrix.num_cols); 00266 return true; 00267 } 00268 00277 bool set_full_kernel_matrix_from_full( 00278 SGMatrix<float64_t> full_kernel_matrix) 00279 { 00280 if (m_row_subset_stack->has_subsets() || m_col_subset_stack->has_subsets()) 00281 { 00282 SG_ERROR("%s::set_full_kernel_matrix_from_full " 00283 "not possible with subset. Remove first\n", get_name()); 00284 } 00285 00286 cleanup_custom(); 00287 int32_t rows=full_kernel_matrix.num_rows; 00288 int32_t cols=full_kernel_matrix.num_cols; 00289 SG_DEBUG( "using custom kernel of size %dx%d\n", rows,cols); 00290 00291 kmatrix=SGMatrix<float32_t>(rows,cols); 00292 upper_diagonal = false; 00293 00294 for (int64_t i=0; i<int64_t(rows) * cols; i++) 00295 kmatrix.matrix[i]=full_kernel_matrix.matrix[i]; 00296 00297 dummy_init(kmatrix.num_rows, kmatrix.num_cols); 00298 return true; 00299 } 00300 00306 virtual void add_row_subset(SGVector<index_t> subset); 00307 00310 virtual void remove_row_subset(); 00311 00314 virtual void remove_all_row_subsets(); 00315 00317 virtual void row_subset_changed_post(); 00318 00324 virtual void add_col_subset(SGVector<index_t> subset); 00325 00328 virtual void remove_col_subset(); 00329 00332 virtual void remove_all_col_subsets(); 00333 00335 virtual void col_subset_changed_post(); 00336 00343 virtual inline int32_t get_num_vec_lhs() 00344 { 00345 return m_row_subset_stack->has_subsets() 00346 ? m_row_subset_stack->get_size() : num_lhs; 00347 } 00348 00355 virtual inline int32_t get_num_vec_rhs() 00356 { 00357 return m_col_subset_stack->has_subsets() 00358 ? m_col_subset_stack->get_size() : num_rhs; 00359 } 00360 00367 virtual inline bool has_features() 00368 { 00369 return (get_num_vec_lhs()>0) && (get_num_vec_rhs()>0); 00370 } 00371 00376 void print_kernel_matrix(const char* prefix="") const; 00377 00382 SGMatrix<float32_t> get_float32_kernel_matrix() 00383 { 00384 return kmatrix; 00385 } 00386 00387 protected: 00388 00397 inline virtual float64_t compute(int32_t row, int32_t col) 00398 { 00399 ASSERT(kmatrix.matrix); 00400 00401 index_t real_row=m_row_subset_stack->subset_idx_conversion(row); 00402 index_t real_col=m_col_subset_stack->subset_idx_conversion(col); 00403 00404 if (upper_diagonal) 00405 { 00406 if (real_row <= real_col) 00407 { 00408 int64_t r=real_row; 00409 return kmatrix.matrix[r*kmatrix.num_rows - r*(r+1)/2 + real_col]; 00410 } 00411 else 00412 { 00413 int64_t c=real_col; 00414 return kmatrix.matrix[c*kmatrix.num_cols - c*(c+1)/2 + real_row]; 00415 } 00416 } 00417 else 00418 { 00419 int64_t r=real_row; 00420 return kmatrix.matrix[r*kmatrix.num_cols+real_col]; 00421 } 00422 } 00423 00424 protected: 00425 00427 SGMatrix<float32_t> kmatrix; 00428 00430 bool upper_diagonal; 00431 00433 CSubsetStack* m_row_subset_stack; 00435 CSubsetStack* m_col_subset_stack; 00436 00438 bool m_free_km; 00439 }; 00440 00441 } 00442 #endif /* _CUSTOMKERNEL_H__ */