たまには std::valarray のことも思い出してあげよう

多クラス分類器をカーネル化してみたら,訓練速度が劇的に低下してガックリしたので,手持ちの二値分類器に多クラス分類器を追加実装してみた(というより,もともとそのつもりで多クラス分類器を実装していた,という方が正しいかも).その際,コードの肥大化を抑えるため,可能な限り二値分類器(素性の重みは double)とコードを共有しようと,素性の重みに演算子オーバーロードされている std::valarray (std::valarray ) を使ったら,多値分類器用のコードをほとんど書かなくて済んで非常に楽だった.std::valarray 便利過ぎる.今までその存在自体は知ってはいたものの, std::vector で充分という場面がほとんどで使うことがなかったが,今回の用途には完璧に嵌った.
と,std::valarray の便利さに感心する一方で,あっちこっちで std::valarray が仕掛けた地雷にも嵌った*1のでそれにも触れておく.まず,コンストラクタの引数の順序が std::vector と逆(初期値,サイズの順; なんでだろう,これ).次に,演算をする valarray 間でサイズが異なると悲惨なことになる(例外も返さないので,デバッグに valgrind を使ったり).他にも resize () のようにSTL コンテナと同じような名前なの実際の動作が異なるメソッドがあったり(valarray の resize () は初期化相当),一部の演算子の動作が直感と合わなかったりと(operator== で各次元を比較した bool 列が返されるとか.std::valarray 間の演算は返り値が std::valarray ),STL コンテナに馴れたプログラマほど嵌りやすい罠が多い気がする.その他,std::slice で valarray の一部を切り出して参照するだけだと問題ないが,別の演算子を適用すると(オブジェクトのコピーが発生するのか)猛烈に処理が遅くなった orz.
しかし,こんな便利なのに(もちろん最初の段落を指す),間違った時代に生まれた orphan だと言われて放置され,C++11 でもコンストラクタ周りの対応(初期化リスト,移動コンストラクタ)と begin () / end (), std::swap の特殊化が追加されただけとは残念だな.せめてコンパイラが,例外の代わりに assert を仕込んでくれたら (-DNDEBUG で無効化できるし) 良かったのではないかな.
以下日記*2.今日は大学に来るのが遅かったのでたまには残業するかと思って,仕事をして帰ったらひどいめにあった(通勤時間 1.4h ぐらいかかるため,普段は昼前に大学来て,6時前に帰る生活をしている).まず,伏線として充電ケーブルを忘れて iPhone の充分がほとんど無い状態だった.湘南新宿ラインの終電(新宿11時半過ぎ)で池袋で(この時点では)座れず,相棒を聴きながら出ないな〜,と思っていたら宇都宮線で人身事故だった.そのまま40分池袋に足止め.最初の10分ぐらいで,iPhone の電源が切れ,20分ぐらいで手持ちの論文数本も読み終わり,立っているだけになった.さらに,赤羽でも座れず,大宮の手前でホームが電車で渋滞して20分ぐらいさらに遅延.大宮でなんとか座れたが,自宅の駅に着いたのは一時半と予定時間の一時間以上後だった.座れなかっただけに,11月終わった - ny23の日記 よりぐったり感が強いな.

*1:というより,STL コンテナを常用することで自分自身に仕掛けられた地雷に std::valarray が嵌っている感じかもしれない.悪いのは自分であって,std::valarray ではない.

*2:もともと,終電で鞭打たれてあんまりだったのでこちらだけで日記を書いていたが,余計に疲れてきたので前半部を追加.