SHOGUN
v3.2.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 virtual EKernelType get_kernel_type() { return K_CUSTOM; } 00106 00111 virtual EFeatureType get_feature_type() { return F_ANY; } 00112 00117 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 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 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 bool has_features() 00368 { 00369 return (get_num_vec_lhs()>0) && (get_num_vec_rhs()>0); 00370 } 00371 00376 SGMatrix<float32_t> get_float32_kernel_matrix() 00377 { 00378 REQUIRE(!m_row_subset_stack, "%s::get_float32_kernel_matrix(): " 00379 "Not possible with row subset active! If you want to" 00380 " create a %s from another one with a subset, use " 00381 "get_kernel_matrix() and the SGMatrix constructor!\n", 00382 get_name(), get_name()); 00383 00384 REQUIRE(!m_col_subset_stack, "%s::get_float32_kernel_matrix(): " 00385 "Not possible with collumn subset active! If you want to" 00386 " create a %s from another one with a subset, use " 00387 "get_kernel_matrix() and the SGMatrix constructor!\n", 00388 get_name(), get_name()); 00389 00390 return kmatrix; 00391 } 00392 00393 protected: 00394 00403 virtual float64_t compute(int32_t row, int32_t col) 00404 { 00405 REQUIRE(kmatrix.matrix, "%s::compute(%d, %d): No kenrel matrix " 00406 "set!\n", get_name(), row, col); 00407 00408 index_t real_row=m_row_subset_stack->subset_idx_conversion(row); 00409 index_t real_col=m_col_subset_stack->subset_idx_conversion(col); 00410 00411 if (upper_diagonal) 00412 { 00413 if (real_row <= real_col) 00414 { 00415 int64_t r=real_row; 00416 return kmatrix.matrix[r*kmatrix.num_rows - r*(r+1)/2 + real_col]; 00417 } 00418 else 00419 { 00420 int64_t c=real_col; 00421 return kmatrix.matrix[c*kmatrix.num_cols - c*(c+1)/2 + real_row]; 00422 } 00423 } 00424 else 00425 return kmatrix(real_row, real_col); 00426 } 00427 00428 protected: 00429 00431 SGMatrix<float32_t> kmatrix; 00432 00434 bool upper_diagonal; 00435 00437 CSubsetStack* m_row_subset_stack; 00439 CSubsetStack* m_col_subset_stack; 00440 00442 bool m_free_km; 00443 }; 00444 00445 } 00446 #endif /* _CUSTOMKERNEL_H__ */