00001 #include "mcal_sparse_basis_cost.h" 00002 //: 00003 // \file 00004 // \author Tim Cootes 00005 // \brief Cost function to promote sparse basis vectors 00006 00007 #include <vcl_cstdlib.h> 00008 #include <vcl_string.h> 00009 #include <vcl_cmath.h> 00010 #include <vcl_sstream.h> 00011 00012 #include <vsl/vsl_indent.h> 00013 #include <vsl/vsl_binary_io.h> 00014 #include <vul/vul_string.h> 00015 #include <mbl/mbl_parse_block.h> 00016 #include <mbl/mbl_read_props.h> 00017 #include <mbl/mbl_exception.h> 00018 00019 //======================================================================= 00020 // Constructors 00021 //======================================================================= 00022 00023 mcal_sparse_basis_cost::mcal_sparse_basis_cost() 00024 { 00025 alpha_ = 1.0; 00026 } 00027 00028 //======================================================================= 00029 // Destructor 00030 //======================================================================= 00031 00032 mcal_sparse_basis_cost::~mcal_sparse_basis_cost() 00033 { 00034 } 00035 00036 //: Weighting for sparseness penalty 00037 void mcal_sparse_basis_cost::set_alpha(double a) 00038 { 00039 alpha_ = a; 00040 } 00041 00042 //: Returns true since cost can be computed from the variance. 00043 bool mcal_sparse_basis_cost::can_use_variance() const 00044 { 00045 return true; 00046 } 00047 00048 //: Compute component of the cost function from given basis vector 00049 // \param[in] unit_basis Unit vector defining basis direction 00050 // \param[in] projections Projections of the dataset onto this basis vector 00051 double mcal_sparse_basis_cost::cost(const vnl_vector<double>& unit_basis, 00052 const vnl_vector<double>& projections) 00053 { 00054 double var = projections.squared_magnitude()/projections.size(); 00055 return cost_from_variance(unit_basis,var); 00056 } 00057 00058 //: Compute component of the cost function from given basis vector 00059 // Cost is log(variance) + alpha sum |e_i|. 00060 // \param[in] unit_basis Unit vector defining basis direction 00061 // \param[in] variance Variance of projections of the dataset onto this basis vector 00062 double mcal_sparse_basis_cost::cost_from_variance(const vnl_vector<double>& unit_basis, 00063 double variance) 00064 { 00065 return vcl_log(1e-8+variance) + alpha_ * unit_basis.one_norm(); 00066 } 00067 00068 00069 //======================================================================= 00070 // Method: is_a 00071 //======================================================================= 00072 00073 vcl_string mcal_sparse_basis_cost::is_a() const 00074 { 00075 return vcl_string("mcal_sparse_basis_cost"); 00076 } 00077 00078 //======================================================================= 00079 // Method: version_no 00080 //======================================================================= 00081 00082 short mcal_sparse_basis_cost::version_no() const 00083 { 00084 return 1; 00085 } 00086 00087 //======================================================================= 00088 // Method: clone 00089 //======================================================================= 00090 00091 mcal_single_basis_cost* mcal_sparse_basis_cost::clone() const 00092 { 00093 return new mcal_sparse_basis_cost(*this); 00094 } 00095 00096 //======================================================================= 00097 // Method: print 00098 //======================================================================= 00099 00100 void mcal_sparse_basis_cost::print_summary(vcl_ostream& os) const 00101 { 00102 os<<vsl_indent()<<"alpha: "<<alpha_; 00103 } 00104 00105 //======================================================================= 00106 // Method: save 00107 //======================================================================= 00108 00109 void mcal_sparse_basis_cost::b_write(vsl_b_ostream& bfs) const 00110 { 00111 vsl_b_write(bfs,version_no()); 00112 vsl_b_write(bfs,alpha_); 00113 } 00114 00115 //======================================================================= 00116 // Method: load 00117 //======================================================================= 00118 00119 void mcal_sparse_basis_cost::b_read(vsl_b_istream& bfs) 00120 { 00121 short version; 00122 vsl_b_read(bfs,version); 00123 switch (version) 00124 { 00125 case (1): 00126 vsl_b_read(bfs,alpha_); 00127 break; 00128 default: 00129 vcl_cerr << "mcal_sparse_basis_cost::b_read()\n" 00130 << "Unexpected version number " << version << vcl_endl; 00131 vcl_abort(); 00132 } 00133 } 00134 00135 //======================================================================= 00136 //: Read initialisation settings from a stream. 00137 // Parameters: 00138 // \verbatim 00139 // { 00140 // min_modes: 0 max_modes: 99 prop_modes: 0.99 00141 // // Maximum number of doubles to store in memory at once 00142 // max_d_in_memory: 1e8 00143 // // Indicate how to build from large amounts of data 00144 // use_chunks: false 00145 // } 00146 // \endverbatim 00147 // \throw mbl_exception_parse_error if the parse fails. 00148 void mcal_sparse_basis_cost::config_from_stream(vcl_istream & is) 00149 { 00150 vcl_string s = mbl_parse_block(is); 00151 00152 vcl_istringstream ss(s); 00153 mbl_read_props_type props = mbl_read_props_ws(ss); 00154 00155 if (!props["alpha"].empty()) 00156 { 00157 alpha_=vul_string_atof(props["alpha"]); 00158 } 00159 props.erase("alpha"); 00160 00161 try 00162 { 00163 mbl_read_props_look_for_unused_props( 00164 "mcal_sparse_basis_cost::config_from_stream", props); 00165 } 00166 catch(mbl_exception_unused_props &e) 00167 { 00168 throw mbl_exception_parse_error(e.what()); 00169 } 00170 }