Deep Learningツール「Caffe」が簡単すぎる件

Deep Learning

最近はChainerとか出てますが、友人のススメでCaffeを使ってみました。

率直にいうと、「なにこれ、簡単すぎる!!」。
とにかく画像を放り込んでCaffeにもぐもぐさせるだけで、チューニングしなくてもそこそこの精度が出る。

ワタクシ、機械学習はツールの使い方を知っているだけで、理論の理解は概要レベルでド素人のミーハーです。
そんなぼくでも出来たんだから、未来は明るい。

インストールが面倒なだけ

コンパイルがね、躓くと泥沼です。
リンカエラー恐怖症になるかと思いました。

~~そんなのいつもやってる事なので、大したことではない。~~

データ集めるのが面倒なだけ

正解データを集めるのがね、面倒です。
どこからどれだけの量を取ってくるか、あるいは取ってこれるのかは、運です。

~~そんなのいつもやってる事なので、大したことではない。~~

チューニングが面倒なだけ

チューニングがね、ハードル高いです。
概要レベルのド素人では分からないので、このへんの資料を穴が空くほど読みましょう。

~~そんなのいつもやってる事なので、大したことではない。~~

計算量のハードルはかなり下がっている

Deep Learningと言えばGoogleさんがゴリゴリやってるイメージですよね。
じゃあ自分もやるためにはGoogle並の計算リソースが必要かといえば、そんなことありません。
ぼくらでも手元のPCですぐに始められます。

まず、nVidiaが提供するCUDAをインストールしておけば、ツールのフラグを立てるだけでGPUを利用できる。
これだけでCPUモードより数倍のスピードが出る。
データセットの量などにもよるけど、お試しニューロンならiMacで一晩寝かせるだけで作れる。

アイデア次第で充分面白いものが作れる

ツールやインフラは手元に揃っているので、あとはアイデア次第。

問題は、「何を分類させるか」だけです。
これはアプリ屋さんの得意分野のはず。

近いうちに、どんどん賢いアプリケーションが増えるでしょう。
スマホのカメラはますます大活躍、というわけだ。

とりあえずデータ集めをがんばろうと思います。

一人でWebサービス作るならnode.jsがオススメという話

「好み」や「慣れ」「制約」の問題は忘れて読んで欲しい。それは個々人の問題だから。

時代はSPA

スマホの普及で、モバイルネットワークなのに画面遷移ごとにページのリロードなんてユーザはじれったくて待ってくれない。
だから、SPA(Single Page Application)という手法が出るのは必然だ。
これは、画面遷移に応じて必要なデータを読み込み、必要な部分だけを再描画する手法だ。

言語のスイッチングコストは予想以上に高い

昔と比べて、ウェブサービスの開発コストはほんとうに下がった。
だから、一人でサービスを作る人もこれから格段に増えるに違いない。

一人でSPAを組む時にしんどいのが、言語のスイッチングコストだ。
Railsで組んでいるなら、RubyとJavaScriptの2つを並行して書かなければならない。

言語はそれぞれ独特の作法があり、いいコードを書くにはそれなりの鍛錬が必要だ。
しかしいかに熟練していたとしても、常に複数言語のテクニックやライブラリにキャッチアップするのは大変だ。

node.jsは”お一人様向け”

node.jsは、サーバサイドで動くJavaScript環境だ。
つまり、スイッチングコストが圧倒的に低い。

もちろん、DOM操作やファイル操作など、クライアントとサーバサイドでは相互で通用しないテクニックもある。
でもそれは言語の問題ではなく、アーキテクチャの問題だ。

一人で効率よく開発したいなら、node.jsをお薦めする。
フレームワークはどれがいい?
そんなのは今どきどれもよく出来ているから、「住めば都」だ。

Dockerでビルド中にdevicemapperがエラーを発生する問題の対処法

docker

問題の概要

Dockerfileのビルド中に以下のようなエラーがランダムに発生するケースがあります:

Error getting container <container ID> from driver devicemapper: Error mounting

僕のケースでは、カーネルがLinux 3.13.0-40-generic、ディストリは Ubuntu 14.04.1 LTSでした。

Dockerのバグでカーネルのバージョンが原因

この問題はGitHubの下記issueで議論されています。

最近、vbatts氏が以下のようなコメントを投稿していました:

after a good bit of investigation, this appears to be an issue in the 3.13 kernel. There are abundant fixes for device-mapper/dm thin in 3.14 (and fixes/backports to 3.14.y and greater). Too many for me to bisect presently.

The state is that this issue is now only reproducible on ubuntu-14.04.1 LTS, which is locked on linux 3.13.0.

In my testing, even using the builds from http://kernel.ubuntu.com/~kernel-ppa/mainline/v3.14.27-utopic/ allowed me to not hit this issue, but that would likely not be a “supported” resolution for many infrastructures…

I am reluctant to close the issue as fixed, as it is for newer kernels, because so many folks will be on ubuntu 14.04.1 LTS for a while… and will likely still hit this bug.

devicemapperがエラーを起こすのは、linuxのバージョンが3.13.0の場合に限るそうです。

Linuxのバージョンを3.13より上にする

Ubuntu 14.04の場合は、以下のパッケージをインストールします。

sudo apt-get install linux-image-3.16.0-29-generic

次に、システムを再起動してください。
カーネルのバージョンが正しくアップグレードされたことを確認します。

$ uname -a
Linux dev4 3.16.0-29-generic #39-Ubuntu SMP Tue Dec 16 20:54:13 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

これで、件のDockerのエラーは発生しなくなりました。

PhantomJSでHTML5の一部APIを使えるようにする方法

phantomjs

PhantomJS 1.9.xは古いWebKitを使っている

GUIを持たないヘッドレスブラウザのPhantomJSは、ウェブでのフロントエンド開発においてそのテストに適したツールです。
このPhantomJSは、QtWebKitをベースに開発されています。
HTML5やCSS3をふんだんに使ったイマドキのウェブサービスを開発している場合、PhantomJSを使ってテストしようとすると上手くいかない場合があります。
これは、使用しているWebKitが古いために起こる問題です。古いWebKitではJavaScriptCoreも古いので、JavaScriptの新しい機能も一部使えません。

どのような機能が使えないのかは、Supported Web Standards に明記されています。
このページには書かれていませんが、Web fontsも使えません。これは前回の記事で使えるようにする方法を書きました。

PhantomJS向けのshimsまとめ

前述の通り、PhantomJSは古いWebKitをベースにしているため、HTML5のAPIやJavaScriptの新機能が使えません。
自分が確認した限りで使えなかったAPIを使えるようにするshimをまとめました。
以下の機能が使えるようになります。

  • Function.prototype.bind
  • History API

今後も適宜更新していこうと思います。

https://gist.github.com/noradaiko/12cbaf8a1674e3b8c8e6.js

参考になれば幸いです!

関連資料

PhantomJS 1.9.xでウェブフォントを使う方法

phantomjs

ヘッドレスブラウザのPhantomJSはWeb fonts未対応

Web fontsは昨今とても一般的に使われるようになった技術です。
例えば、Twitter Bootstrapfont awesomeなどで、いわゆる “Glyphicons” として使われることが多いように思います。

PhantomJSというGUIを持たないブラウザがあります。
このブラウザは、ウェブサービスのフロントエンドのテスト自動化にとても便利なツールです。
JavaScriptで自動化のための処理を記述できて、スクリーンキャプチャも出来てとても便利です。

Web fontsに対応させることは出来るが再ビルドが必要

しかしながら、現行の1.9.xではWeb fontsに対応していません。
理由は、WOFFファイルにPhantomJSがまだ対応していないためです。
Web fontsを有効にするための手順 がありますが、PhantomJSをビルドしなおす必要があります。
ビルドは結構時間がかかり、大変です。

ビルド済みWeb Fonts対応版PhantomJS

PhantomJS with Webfonts Support – Binary Build – Arunoda Susiripala – Web Geek というサイトでは、ビルド済みのWeb Fonts対応版PhantomJSを公開しています。バージョンは1.9.0のようです。

ビルド済みのWeb Fonts対応版PhantomJS 1.9.0をダウンロード

作者に感謝しつつ、使いましょう!

PhantomJS + CasperJSで テスト終了時に警告が出まくる問題への対処方法

phantomjs

警告の内容

CasperJSでテストを書いていると、スクリプト終了時にPhantomJSが次のような大量の警告を吐いて止まらなくなります。

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL ...
Domains, protocols and ports must match.

これではまともにテスト結果が見られない上、CIも回せません。

PhantomJS v1.9.8はバギーなのでv1.9.7を使う

以下のスレッドにヒントが書かれていました。

To anyone who has a problem with this. Downgrade PhantomJS to 1.9.7 and run casperjs with the –ssl-protocol=tlsv1 to be functionally completely the same as PhantomJS 1.9.8.
There won’t be an updated PhantomJS 1.x version which fixes this issue.

Mac OSXでの v1.9.7 のインストール法

brewだと1.9.8が入ってしまいます。
バイナリを本家から直接ダウンロードして使います。

ただし、最新版へのリンクしかありませんので、バージョン番号を変えて直接リンクを開いてください。
一応、こちらにリンクも貼っておきます。

brewでインストールした既存のphantomjsはアンインストールしておくことを忘れないでください。

[node.js] mongooseでクエリをタイムアウトさせるには

MongoDB

tl;dr

  • MongoDBではv2.6から cursor.maxTimeMS()によって処理をタイムアウトさせられる
  • 各ドライバから使用可能
  • mongooseでは mongoose.Query#maxTime メソッドで指定可能

サーバ側で処理をタイムアウトさせるには

MongoDBでは、v2.6からサーバ側で処理の実行タイムリミットを設定できます。
処理のタイムリミットは、cursor.maxTimeMS() メソッドを呼ぶことで設定できます。
この maxTimeMS を設定すると、指定したタイムリミットを超えて検索やアップデートが実行された場合、その処理を中止します。

以下のようにコンソールで試せます:

db.collection.find({description: /August [0-9]+, 1969/}).maxTimeMS(50)

各ドライバでのmaxTimeMSの使用方法

各ドライバといっても調べたものだけを列挙しておきます。

PHP

例:

$cursor = $collection->find();
$cursor->maxTimeMS(2000);

try {
    $results = iterator_to_array($cursor);
} catch (MongoExecutionTimeoutException $e) {
    echo "query took too long!";
}

ちなみに、PHPにはMongoCursor::timeout もあります。
このメソッドはクライアント側でタイムアウト処理を行うものです。
サーバ側では処理をキャンセルしないので、注意です。

node.js

こちらに詳しく書いてあります。
例:

var MongoClient = require('mongodb').MongoClient;

MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
    // Get an aggregation cursor
    var cursor = db.collection('data')
        .find({"$where": "sleep(1000) || true"})
        .maxTimeMS(50);

    // Get alll the items
    cursor.toArray(function(err, items) {
        console.dir(err);
        console.dir(items);
        db.close();
    });
});

mongooseでタイムアウトさせるには

MongoDBのnode.jsにおけるODM(Object Data Mapping)のmongooseでもmaxTimeMSに対応しています。
v3.8.13 から利用できるようになりました。
該当の変更は こちら
実際には子分モジュールの mquery で実装されています。

使い方はシンプル:

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');

var Cat = mongoose.model('Cat', { name: String });
Cat.find({name: 'Zildjian' }).maxTime(1000).exec(function(err, docs) {
    console.log(err); // --> { [MongoError: operation exceeded time limit] name: 'MongoError' }
});

operation exceeded time limit というメッセージのエラーが得られます。

このように、mongoose.Query オブジェクトを返すメソッドでmaxTimeメソッドが使えます。
Model#saveメソッド、Model#remove では残念ながら使えないようです。

エラーを判別しにくい問題

Errorオブジェクトにはエラー種別を明示的に判別するコードがありません。
そのため、とても不安な方法ですがエラーメッセージで判別する方法しか見当たりません(他に良い方法をご存知の方がおられましたらぜひご教授ください)。
メッセージによるタイムアウト判別は以下のようになります:

if(err.message === 'operation exceeded time limit') {
   // retry
}

なぜPHPにはMongoExecutionTimeoutExceptionがあるのにnode.jsでは無いんだ?

参考