[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
vigra/random_forest_hdf5_impex.hxx | ![]() |
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 2009 by Rahul Nair and Ullrich Koethe */ 00004 /* */ 00005 /* This file is part of the VIGRA computer vision library. */ 00006 /* The VIGRA Website is */ 00007 /* http://hci.iwr.uni-heidelberg.de/vigra/ */ 00008 /* Please direct questions, bug reports, and contributions to */ 00009 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00010 /* vigra@informatik.uni-hamburg.de */ 00011 /* */ 00012 /* Permission is hereby granted, free of charge, to any person */ 00013 /* obtaining a copy of this software and associated documentation */ 00014 /* files (the "Software"), to deal in the Software without */ 00015 /* restriction, including without limitation the rights to use, */ 00016 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00017 /* sell copies of the Software, and to permit persons to whom the */ 00018 /* Software is furnished to do so, subject to the following */ 00019 /* conditions: */ 00020 /* */ 00021 /* The above copyright notice and this permission notice shall be */ 00022 /* included in all copies or substantial portions of the */ 00023 /* Software. */ 00024 /* */ 00025 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00026 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00027 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00028 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00029 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00030 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00031 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00032 /* OTHER DEALINGS IN THE SOFTWARE. */ 00033 /* */ 00034 /************************************************************************/ 00035 00036 #ifndef VIGRA_RANDOM_FOREST_IMPEX_HDF5_HXX 00037 #define VIGRA_RANDOM_FOREST_IMPEX_HDF5_HXX 00038 00039 #include "config.hxx" 00040 #include "random_forest.hxx" 00041 #include "hdf5impex.hxx" 00042 #include <string> 00043 00044 namespace vigra 00045 { 00046 00047 static const char *const rf_hdf5_options = "_options"; 00048 static const char *const rf_hdf5_ext_param = "_ext_param"; 00049 static const char *const rf_hdf5_labels = "labels"; 00050 static const char *const rf_hdf5_topology = "topology"; 00051 static const char *const rf_hdf5_parameters = "parameters"; 00052 static const char *const rf_hdf5_tree = "Tree_"; 00053 static const char *const rf_hdf5_version_group = "."; 00054 static const char *const rf_hdf5_version_tag = "vigra_random_forest_version"; 00055 static const double rf_hdf5_version = 0.1; 00056 00057 namespace detail 00058 { 00059 00060 VIGRA_EXPORT void options_import_HDF5(HDF5File &, RandomForestOptions &, 00061 const std::string &); 00062 00063 VIGRA_EXPORT void options_export_HDF5(HDF5File &, const RandomForestOptions &, 00064 const std::string &); 00065 00066 VIGRA_EXPORT void dt_import_HDF5(HDF5File &, detail::DecisionTree &, 00067 const std::string &); 00068 00069 VIGRA_EXPORT void dt_export_HDF5(HDF5File &, const detail::DecisionTree &, 00070 const std::string &); 00071 00072 template<class X> 00073 void rf_import_HDF5_to_map(HDF5File & h5context, X & param, 00074 const char *const ignored_label = 0) 00075 { 00076 // read a map containing all the double fields 00077 typedef typename X::map_type map_type; 00078 typedef std::pair<typename map_type::iterator, bool> inserter_type; 00079 typedef typename map_type::value_type value_type; 00080 typedef typename map_type::mapped_type mapped_type; 00081 00082 map_type serialized_param; 00083 bool ignored_seen = ignored_label == 0; 00084 00085 std::vector<std::string> names = h5context.ls(); 00086 std::vector<std::string>::const_iterator j; 00087 for (j = names.begin(); j != names.end(); ++j) 00088 { 00089 if (ignored_label && *j == ignored_label) 00090 { 00091 ignored_seen = true; 00092 continue; 00093 } 00094 // get sort of an iterator to a new empty array vector in the map ... 00095 inserter_type new_array 00096 = serialized_param.insert(value_type(*j, mapped_type())); 00097 // ... and read the data into that place. 00098 h5context.readAndResize(*j, (*(new_array.first)).second); 00099 } 00100 vigra_precondition(ignored_seen, "rf_import_HDF5_to_map(): " 00101 "labels are missing."); 00102 param.make_from_map(serialized_param); 00103 } 00104 00105 template<class T> 00106 void problemspec_import_HDF5(HDF5File & h5context, ProblemSpec<T> & param, 00107 const std::string & name) 00108 { 00109 h5context.cd(name); 00110 rf_import_HDF5_to_map(h5context, param, rf_hdf5_labels); 00111 // load_class_labels 00112 ArrayVector<T> labels; 00113 h5context.readAndResize(rf_hdf5_labels, labels); 00114 param.classes_(labels.begin(), labels.end()); 00115 h5context.cd_up(); 00116 } 00117 00118 template<class X> 00119 void rf_export_map_to_HDF5(HDF5File & h5context, const X & param) 00120 { 00121 typedef typename X::map_type map_type; 00122 map_type serialized_param; 00123 // get a map containing all the double fields 00124 param.make_map(serialized_param); 00125 typename map_type::const_iterator j; 00126 for (j = serialized_param.begin(); j != serialized_param.end(); ++j) 00127 h5context.write(j->first, j->second); 00128 } 00129 00130 template<class T> 00131 void problemspec_export_HDF5(HDF5File & h5context, ProblemSpec<T> const & param, 00132 const std::string & name) 00133 { 00134 h5context.cd_mk(name); 00135 rf_export_map_to_HDF5(h5context, param); 00136 h5context.write(rf_hdf5_labels, param.classes); 00137 h5context.cd_up(); 00138 } 00139 00140 struct padded_number_string_data; 00141 class VIGRA_EXPORT padded_number_string 00142 { 00143 private: 00144 padded_number_string_data* padded_number; 00145 protected: 00146 padded_number_string(const padded_number_string &); 00147 void operator=(const padded_number_string &); 00148 public: 00149 padded_number_string(int n); 00150 std::string operator()(int k) const; 00151 ~padded_number_string(); 00152 }; 00153 00154 inline std::string get_cwd(HDF5File & h5context) 00155 { 00156 return h5context.get_absolute_path(h5context.pwd()); 00157 } 00158 00159 } // namespace detail 00160 00161 /** \brief Save a random forest to an HDF5File object into a specified HDF5 00162 group. 00163 00164 The random forest is saved as a set of HDF5 datasets, groups, and 00165 attributes below a certain HDF5 group (default: current group of the 00166 HDF5File object). No additional data should be stored in that group. 00167 00168 \param rf Random forest object to be exported 00169 \param h5context HDF5File object to use 00170 \param pathname If empty or not supplied, save the random forest to the 00171 current group of the HDF5File object. Otherwise, save to a 00172 new-created group specified by the path name, which may 00173 be either relative or absolute. 00174 */ 00175 template<class T, class Tag> 00176 void rf_export_HDF5(const RandomForest<T, Tag> & rf, 00177 HDF5File & h5context, 00178 const std::string & pathname = "") 00179 { 00180 std::string cwd; 00181 if (pathname.size()) { 00182 cwd = detail::get_cwd(h5context); 00183 h5context.cd_mk(pathname); 00184 } 00185 // version attribute 00186 h5context.writeAttribute(rf_hdf5_version_group, rf_hdf5_version_tag, 00187 rf_hdf5_version); 00188 // save serialized options 00189 detail::options_export_HDF5(h5context, rf.options(), rf_hdf5_options); 00190 // save external parameters 00191 detail::problemspec_export_HDF5(h5context, rf.ext_param(), 00192 rf_hdf5_ext_param); 00193 // save trees 00194 int tree_count = rf.options_.tree_count_; 00195 detail::padded_number_string tree_number(tree_count); 00196 for (int i = 0; i < tree_count; ++i) 00197 detail::dt_export_HDF5(h5context, rf.tree(i), 00198 rf_hdf5_tree + tree_number(i)); 00199 00200 if (pathname.size()) 00201 h5context.cd(cwd); 00202 } 00203 00204 /** \brief Save a random forest to a named HDF5 file into a specified HDF5 00205 group. 00206 00207 The random forest is saved as a set of HDF5 datasets, groups, and 00208 attributes below a certain HDF5 group (default: root). No additional data 00209 should be stored in that group. 00210 00211 \param rf Random forest object to be exported 00212 \param filename Name of an HDF5 file to open 00213 \param pathname If empty or not supplied, save the random forest to the 00214 root group of the HDF5 file. Otherwise, save to a 00215 new-created group specified by the path name (relative 00216 to the root group). 00217 */ 00218 template<class T, class Tag> 00219 void rf_export_HDF5(const RandomForest<T, Tag> & rf, 00220 const std::string & filename, 00221 const std::string & pathname = "") 00222 { 00223 HDF5File h5context(filename , HDF5File::Open); 00224 rf_export_HDF5(rf, h5context, pathname); 00225 } 00226 00227 /** \brief Read a random forest from an HDF5File object's specified group. 00228 00229 The random forest is read from a certain HDF5 group (default: current group 00230 of the HDF5File object) as a set of HDF5 datasets, groups, and 00231 attributes. No additional data should be present in that group. 00232 00233 \param rf Random forest object to be imported 00234 \param h5context HDF5File object to use 00235 \param pathname If empty or not supplied, read from the random forest 00236 from the current group of the HDF5File object. Otherwise, 00237 use the group specified by the path name, which may 00238 be either relative or absolute. 00239 */ 00240 template<class T, class Tag> 00241 bool rf_import_HDF5(RandomForest<T, Tag> & rf, 00242 HDF5File & h5context, 00243 const std::string & pathname = "") 00244 { 00245 std::string cwd; 00246 if (pathname.size()) { 00247 cwd = detail::get_cwd(h5context); 00248 h5context.cd(pathname); 00249 } 00250 // version attribute 00251 if (h5context.existsAttribute(rf_hdf5_version_group, rf_hdf5_version_tag)) 00252 { 00253 double read_version; 00254 h5context.readAttribute(rf_hdf5_version_group, rf_hdf5_version_tag, 00255 read_version); 00256 vigra_precondition(read_version <= rf_hdf5_version, 00257 "rf_import_HDF5(): unexpected file format version."); 00258 } 00259 // get serialized options 00260 detail::options_import_HDF5(h5context, rf.options_, rf_hdf5_options); 00261 // get external parameters 00262 detail::problemspec_import_HDF5(h5context, rf.ext_param_, 00263 rf_hdf5_ext_param); 00264 // get all groups in base path 00265 // no check for the rf_hdf5_tree prefix... 00266 std::vector<std::string> names = h5context.ls(); 00267 std::vector<std::string>::const_iterator j; 00268 for (j = names.begin(); j != names.end(); ++j) 00269 { 00270 if ((*j->rbegin() == '/') && (*j->begin() != '_')) // skip the above 00271 { 00272 rf.trees_.push_back(detail::DecisionTree(rf.ext_param_)); 00273 detail::dt_import_HDF5(h5context, rf.trees_.back(), *j); 00274 } 00275 } 00276 if (pathname.size()) 00277 h5context.cd(cwd); 00278 return true; 00279 } 00280 00281 /** \brief Read a random forest from a named HDF5 file's specified group. 00282 00283 The random forest is read from a certain HDF5 group (default: root group 00284 of the HDF5 file) as a set of HDF5 datasets, groups, and attributes. 00285 No additional data should be present in that group. 00286 00287 \param rf Random forest object to be imported 00288 \param filename Name of an HDF5 file to open 00289 \param pathname If empty or not supplied, read from the random forest 00290 from the current group of the HDF5 file. Otherwise, 00291 use the group specified by the path name, which may 00292 be either relative or absolute. 00293 */ 00294 template<class T, class Tag> 00295 bool rf_import_HDF5(RandomForest<T, Tag> & rf, 00296 const std::string & filename, 00297 const std::string & pathname = "") 00298 { 00299 HDF5File h5context(filename, HDF5File::Open); 00300 return rf_import_HDF5(rf, h5context, pathname); 00301 } 00302 00303 } // namespace vigra 00304 00305 #endif // VIGRA_RANDOM_FOREST_HDF5_IMPEX_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|