可変長疎ベクトル var_len_vec
可変長の疎ベクトルをつくってみた.
機械学習とかでは,
特徴量の数が最初から決まってないことがあって,
学習の途中で追加なんてこともあります.
key-value型でデータを保存するようにして,
keyに特徴量の情報を入れられると.
ソースは,bitbucketに置きました.
https://bitbucket.org/ryoma_kawajiri/var_len_vec
templateを使ったheaderだけのコードです.
使い方
unordered_mapとかmapを継承して,
四則演算のoperatorとかを追加して実装しているだけなので,
親のmember functionとかももちろんそのまま使えちゃいます.
keyの型には色々使えます.
var_len_vec<double> v1, v2; v1[1] = 1.0; v1["-1<x<=0"] = (-1 < x && x <= 0) ? 1:0; v1["0<x<=1"] = (0 < x && x <= 1) ? 1:0; v1["gauss:mu=0:sigma=1"] = exp(-x*x / sigma); var_len_vec<double> v3 = v1 * v2; double d1 = inner_product(v1 * v2); double d2 = v1.sum();
あとは,testコードとかも見てもらえばいいと思います.
仕組み
keyの型が何でもいいのは,
implicit conversion (暗黙的変換?)を使って,
stringに変換しているから.
一意に変換出来れば,どんな方法でも大丈夫.
こんなクラスを作った.
class common_key: public std::string{ public: // implicit conversion template<class Any> common_key(const Any & any): std::string(to_string(any)) {} private: template<class Any> std::string to_string(const Any & any) const { std::stringstream ss; int status = 0; ss << abi::__cxa_demangle(typeid(any).name(), 0, 0, &status) // ss << __PRETTY_FUNCTION__ << " " << any; return ss.str(); } };
あとは,mapとかunordered_mapで使えるように,
hashとかequal_toとかの関数を定義してあげれば良いと.
serializationとかも使えるかと思ったけど,
バージョン情報とかを埋め込まれちゃうから,
一意に決まらないことも.
ただ,typeidでRTTIを使ってて効率が悪い.
型はコンパイル時にわかるからいい方法がないかな?
__PRETTY_FUNCTION__とか使うと,
余計なものがたくさん付いちゃうし悩ましいところ.
特徴量作るときだけだから,とりあえず仕方ない.
最後に
keyを文字列にしてるので,
最近,流行りのTRIE木とかの実装をラップすると,
効率が良くなるかな.
あと,RTTIを使わないでいい方法を考えてみる.
boostのserializationとかはどうやっているんだろう?