stMind

about Arsenal, Arsene Wenger, Tech, Computer vision and Machine learning

intが戻り値の関数でエラーを返すにはどうすればいいか

stackoverflow.com

例えば、ファイルに含まれる数の合計を計算する場合。

int DoSum(const std::string& file);

ファイルに含まれるのが正の値だけであれば、負の値でエラーを示すことができるが、正も負も含まれる場合には適用できない。

3つのやり方

1. 戻り値はエラーにして、合計は引数で指定された領域に格納
int DoSum(const std::string &file, int &sum)
{
    /* return value of zero indicates a sum has been computed
          other values indicate an error status
    */
}
2. エラーと合計を含むデータ構造を定義して戻り値とする
struct ReturnData
{
      int sum;
      int error_indicator;
};

struct ReturnData DoSum(const std::string &file)
{
}
3. 戻り値は合計で、エラーは例外で扱う
int DoSum(const std::string &file)
{
     /*  do calculations */
     if (error_has_occurred)
         throw some_appropriate_exception();
     else
         return calculated_sum;
}

1と2の場合、エラーが致命的でなければ呼び出し側で何もする必要がない一方で、エラー処理をしなくても動くので変な結果で処理が進んでしまうことがある。 3の場合、例外をcatchしなくても処理が異常終了するので変な結果が処理が進むことはないのに対し、この関数を使う全ての呼び出し側でcatchして適切に扱うようにしないといけない。

Googleのコード規模でということなので、自分たちのサイズで考える必要がありますが、既存のコードに対して、例外を導入するコストが高いので、 Google C++ Style Guideでは例外は使わないとしています。 ただ、自分たちの問題で考えてみても、関係する全てのコードで新しく例外処理を実装するのはやはり大変なので、1か2を使うことが多い印象です。

今こそ読みたいグーグルマップ誕生の舞台裏

NEVER LOST AGAIN グーグルマップ誕生 (世界を変えた地図)

NEVER LOST AGAIN グーグルマップ誕生 (世界を変えた地図)

中の人による、キーホール起業からグーグルによる買収、グーグルマップとグーグルアースの成功に向かう物語が書かれた内容は、とても興味深いものでした。個人的なハイライトは、ストリートビューがグーグル内部で始まった当時の描写と、グーグルマップを他社の地図データから自社データへと切り替えることになったGround Truthプロジェクトの章でした。

物理世界を検索可能にするストリートビュー

後にストリートビューとなるプロジェクトを担当していたのは、2004年に入社したLuc Vincent氏。入社した時は、グーグルブックスのチームに所属して世界の書籍をスキャンするタスクを担っていたが、ラリー・ペイジとのミーティングで構想を聞き、スタンフォード大学のMarc Levoy教授と既に始めていたストリートビューをリードする役割を任されたらしい。

最初の検証では、ラリー・ペイジセルゲイ・ブリンマリッサ・メイヤーとドライブしながら助手席でビデオカメラを回して撮った映像!を使ったようだが、Vincent氏はスタンフォード出身のエンジニアとインターン生とともに、撮影車両プロトタイプと360度画像をつなぎ合わせるソフトウェアツールを作り、撮影を行っていた。

何のロゴマークも書かれていない深緑色のシボレーのバンの上にはコンピュータ、カメラ、レーザーセンサーの複合体が取り付けてあり、時速16㎞以下のスピードで走行した。それ以上の速さだと撮影した画像がブレ、使い物にならないのだ。バンから何回か煙が上がったため、電力の安定供給のために今度はホンダのガソリン発電機も屋根に取り付けた。

このプロトタイプでは数々の問題が起こっていたようだが。

この撮影車両の性能は、驚くほど当てにならなかった。毎日、チームがその日の撮影作業を計画し、すべての機器を慎重につないで走行の準備を整える。そうしてインターン生がバンを走らせるのだが、毎日、1時間ほどでコンピュータがクラッシュしたり、他の不具合が起きたりして作業が中断した。少し走ってはマウンテンビューに連絡を入れ、母船に戻って何がうまくいかなかったかを調査するということの繰り返しだった。

それでも、2005年の夏頃には、マウンテンビューとパロアルトの撮影データセットを構築し、グーグルマップと統合したデモを完成させ、正式なプロジェクトに昇格。その後は、2007年にストリートビューアメリカ5都市のみ対応でローンチされ、自動運転のチームも加わった2007年の終わりにはアメリカ中の道路600万マイルのうち100万マイルを走破するまでになった。

Ground Truthプロジェクト

グーグルマップとグーグルアースが大ヒットするのに伴い、地図データのライセンス料の問題が無視できないものになっていた。

グーグルの地図プロダクトの爆発的な人気に伴い、地図データのライセンス料は急騰していた。その中でも最も高額だったのは交通網のデータベースだ。この業界は2社が市場を占領している。オランダに拠点を置くテレ・アトラスとアメリカのナブテックだ。

問題はライセンス料が高いということだけではなく、データをどう使うかまで制限されていたことだという。

彼らは毎年グーグルが支払うデータの利用料金を決定し、またグーグルがどのようにデータを使っていいかを指示していた。ナブテックとテレ・アトラスは、豊富な利益が得られるナビゲーション端末市場に影響がでないようにしたいと考えていた。彼らにとってパーソナルナビゲーション端末を何十億台と販売しているガーミン、トムトム、マゼランとのビジネスの方が重要だった。

当然、とはいえある意味無謀な、自分たちの交通網地図を作る方向に舵を切ることになる。それが、ストリートビューの画像から画像認識技術で交通データを抽出し、全世界の交通網の情報を書き出すプロジェクト「Ground Truth」。

このGround Truthのために内製したのが、地図作成ソフトウェアのアトラスで、2013年のGoogle I/Oスクリーンショットと合わせて紹介されている(下記リンク参照)。アトラスでは、空中写真、衛星写真ストリートビューの画像と、画像認識で自動抽出した道路標識や住所などの道路に付随する情報など、グーグルが持つ特定地域に関する全ての情報を1つの画面で見ることができる。さらに、例えば道路の両側で同じ進行方向の車が撮影されている画像があれば、アトラスがその道路を一方通行であると推測する機能も持っている。ただし、最後は、人間のオペレータがアトラスの解析したデータを確認し、修正して、正確な情報として公開する承認をする。

Google I/O 2013 - Project Ground Truth: Accurate Maps Via Algorithms and Elbow Grease - YouTube

2009年末には、利用料もなく、使用制限もない、グーグル製地図データへの切り替えが行われた。

感想

ユーザを第一に考え、世界の地理情報を整理してアクセス可能にするため、必要なリソースにちゃんと投資し、何十億というユーザが使う現在のグーグルマップを実現してきた裏側は、とても面白かった!

自社製地図データへの切り替えによって、使用用途制限がなくなったことにより、モバイル版グーグルマップで音声道案内が実現されたということを知ると、最近のグーグルマップの地図データ切り替えも、次の新しいユーザ体験の布石かもしれないと思うと、楽しみでなりません。

スーパーカーについて知っていること

最近、YoutubeでライブのPV見て、そこについてるコメントを見てなんか書いてみたくなった。

2005年に解散したスーパーカーは、自分の青春時代そのものだった気がする。当時はまだネットが一般的に使われる前だったし、スマホなんてものは当然なかったから、とにかくインタビューが掲載されている雑誌があれば購入し、スペシャで特集が放送されればビデオに録画して、頑張って東京までライブ見に行ったりしていた。

解散ライブも幸運にもチケット取れて、もしかしたらファーストアルバムの曲やらずに解散あるかも?と心配して行ったけど、creamsodaとかLuckyとか見れて最高に感慨深かった。まあ、MCゼロで歌声以外に声を発することなく終わって、しかもアンコールはなしだったのは、やっぱそうかーと思ったな。

スーパーカーは色々と変わったバンドだと思うんだけど、変わったエピソードといえば、このようなものを雑誌とかで読んだような気がする。でも、本当なのかどうかはわからないけど。

  • ジュンジくんがミキちゃんのバンドメンバー募集に反応したのは、メンバー募集の紙にクマの絵が書いてあったから
  • creamsodaのPVでメンバーが乗っているアメ車は所ジョージさん所有のもの
  • Luckyには当初サビがなかったが、シングルカットされることが決まって「ラッキーなのにね」のところが追加された
  • DRIVEにドラムがないのは、録音されたのがコーダイの加入前だったため
  • ナカコーの声が小さすぎてドラムの音にかき消されてしまうため、初期のライブの配置では真ん中にジュンジくん、両サイドにミキちゃんとナカコーのボーカルだった
  • ナカコーの歌声が無機質な感じなのは、ジュンジくんがナカコーに気持ちを込めて歌わないようにと言っていたため

そういえば、解散した後だったか、スーパーカーのラジオ「オールOK」が一夜限りで復活して、そのときに質問募集してたので、ネットで質問送ったらなんと採用されたという!それで、どう使っていいか分からない鉛筆みたいなのが送られてきたんだよね。でも、当時は会社の寮に住んでて、ラジオが聞けない環境で、どういう風に答えてくれたのか分かってないんだよなぁ... どこかに音源ないだろうかなぁ。

f:id:satojkovic:20181014210823j:plain:w300

Encountered errors while installing torch

ld: library not found for -lSystem
collect2: error: ld returned 1 exit status

Error: Build error: Failed compiling module lfs.so
ld: library not found for -lreadline
collect2: error: ld returned 1 exit status

Error: Build error: Failed compiling module readline.so
/Users/satojkovic/torch/extra/cutorch/lib/THC/THCHalf.cu(40): error: class "__half" has no member "x"

/Users/satojkovic/torch/extra/cutorch/lib/THC/THCHalf.cu(41): error: class "__half" has no member "x"

/Users/satojkovic/torch/extra/cutorch/lib/THC/THCHalf.cu(42): error: class "__half" has no member "x"

/Users/satojkovic/torch/extra/cutorch/lib/THC/THCHalf.cu(80): error: class "__half" has no member "x"

/Users/satojkovic/torch/extra/cutorch/lib/THC/THCHalf.cu(88): error: class "__half" has no member "x"

/Users/satojkovic/torch/extra/cutorch/lib/THC/THCHalf.cu(92): error: class "__half" has no member "x"

/Users/satojkovic/torch/extra/cutorch/lib/THC/THCHalf.cu(122): error: class "__half" has no member "x"

make[1]: *** [lib/THC/CMakeFiles/THC.dir/all] Error 2
make: *** [all] Error 2

Error: Build error: Failed building.

Tensorflow Object Detection APIのCPU処理時間 on MacBook Pro

計測環境

  • MacBook Pro Late 2013モデル
    • CPU: 2.8GHz Corei7
    • Mem: 8GB 1600MHz DDR3
  • デフォルトで指定されているssd_mobilenet_v1_coco_2017_11_17

計測はTensorflowのtimelineを使用。

def run_inference_for_single_image(image, graph):
  with graph.as_default():
    with tf.Session() as sess:
      # timeline
      options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
      run_metadata = tf.RunMetadata()

      # 他の処理...

      # Run inference
      output_dict = sess.run(tensor_dict,
                             feed_dict={image_tensor: np.expand_dims(image, 0)}, options=options, run_metadata=run_metadata)

      # 他の処理...

      # Save timeline
      fetched_timeline = timeline.Timeline(run_metadata.step_stats)
      chrome_trace = fetched_timeline.generate_chrome_trace_format()
      with open('timeline.json', 'w') as f:
        f.write(chrome_trace)

  return output_dict     

計測結果

chrome://tracingで確認。読み取れる情報は

  • 全体で130ms程度
  • 最も時間がかかっているのは、TensorArrayScatterV3

Tensorflow Object Detection API、CPUでも十分速い。

f:id:satojkovic:20180930221255p:plain

Deep Learning for Videos

sites.google.com

Deep Learningを動画に適用というのはこれから増えてくると思うし、問題を分類した上記ブログを借りて頭を整理しておくとよいなと思った。少し古いが参照論文リストもあるので、目を通すと良さそう。

  1. Video Classification

    • Image Classificationと同じ問題で、入力が動画となっただけ
    • 最もシンプルなアプローチは、動画の各フレームに対してCNNなどで分類スコアを計算し、最後にフレーム全体のスコアに統合
      • ただし、このアプローチでは時系列の情報は失われてしまう
    • LSTMなどを用いて明示的に時系列な情報を用いる方式も提案されてきている
  2. Activity Recognition

    • Video Classificationの問題であるが、動画の中の、特に人の行動を認識する問題
    • Deep Learningを用いた手法がホットな領域
    • 手動設計の特徴を用いていた時代のDense Trajectoriesを改良した方式もある
  3. Action Localization

    • 動画の中でActionを検出する問題(Actionをしている開始フレームから終了フレームまで)

MSCOCO keypoint challengeのWinner solution

blog.mapillary.com

MSCOCO joint recognition challengeで、6つのタスクのうち4つでbest scoreだったのは、Megviiという顔認識技術の企業。人物の関節位置を推定するKeypoint challengeでは、Megviiは2017年でもTopだったようです。

CVPRにも採択されていた論文について、主要な部分だけメモします。

http://openaccess.thecvf.com/content_cvpr_2018/papers/Chen_Cascaded_Pyramid_Network_CVPR_2018_paper.pdf

Cascade Pyramid Network

Megviiの手法はTop-down型のアプローチ(人物検出をして、人物矩形毎に関節推定)で、関節が見えているけれども推定が難しいhard visible partsと、occlusionで見えていないinvisible partsを推定するCascade Pyramid Network(CPN)というアーキテクチャを提案しています。

GlobalNetとRefineNet

f:id:satojkovic:20180916110732p:plain

f:id:satojkovic:20180916121159p:plain

論文の図1がCPNの全体概要図。Hard keypointについては、周辺の情報(コンテキスト)を考慮することで、推定できるようにしようというのがアイデアのよう。

そのための一つ目のステージがGlobalNetで、ResNetをベースにしたネットワークで、conv2からconv5までのfeature mapに3x3のフィルタを適用して、keypoint毎のheatmapを生成するのが基本動作。論文の図2の左にあるのが、生成されたheatmapの例。さらに、Feature Pyramid Networkと同じように、位置精度を高く、かつ周辺情報を利用できるように、深い層のmapをupsamplingしてelement wiseに足し合わせたmapを生成している。図2を見ると、left eyeの方は正解位置の緑点の近くに高いスコアが出ている様子が見えますが、left hipは深い層では正解位置の周辺にスコアが出てますが、位置精度の高い推定は出来てないことがわかります。

そこで、二つ目のステージのRefineNetを用いる。ここでは、GlobalNetで生成された異なる層のfeature mapについて、層毎に異なる回数のbottle neckを適用して冗長なfeature mapを削減していって、全部のmapを結合するようにします(upsamplingしたあとで)。

学習では、GlobalNetはN個のkeypointそれぞれについてL2ロスに基づくパラメータ更新をしますが、RefineNetではその中でロスが大きいM個に絞ってパラメータ更新を実施するようにしています(online hard kyepoint mining)。MS COCOの場合だとN=17で、Mは8のときが最も精度が良い結果となったようです。

Results

http://presentations.cocodataset.org/COCO17-Keypoints-Overview.pdf

2017年の結果です。Top5の差は3%以内ということで近いスコアですが、Megvii社の手法が一位です。