Hatena::ブログ(Diary)

Over&Out その後 このページをアンテナに追加 RSSフィード Twitter

2014-12-19

iOSエンジニアが初めてAndroid開発をやってみた第1日目のメモ

当方フリーランスエンジニアですが、iOS専業でやっております。これまで幾度と無く「ちなみにAndroidの方は・・・?」「すいません、できないんです・・・」と肩身の狭い思いをしてきましたが、ついに今日第一歩目を踏み出しました。


ちなみに現在のスペックですが、

  • iOSアプリ開発歴4年、Android開発歴ゼロ
  • Androidはユーザーとしても経験値ほぼゼロ(先週 Nexus5 購入して WiFi セットアップしただけ)

という感じです。


実況中継的に随時追記する形で書いていきたいと思います。iOS からプログラミングの世界に入り、これから Android もやってみたい、という人も今となっては結構多いんじゃないかと思うので、どなたかの第一歩目の参考になれば幸いです。


※(終了後に追記)あとから読んだ人には何のことかわからないかもしれませんが、本記事は昼ぐらいに出だし(午前中に進めた内容。書籍購入まで)をアップし、その日何かやる度に実況中継的に追記していったものです。思いつくままに手を付けていった順に書いてるので、勉強しやすい順序とかにもなっていないと思います。


Android Studio インストール

何はともあれ開発環境のインストールから。(Android Studioは、iOSでいうXcode みたいなもの)

  • http://developer.android.com/sdk/index.html
  • Setup Wizard 通り
  • 途中で JDK 7.0 のダウンロード&インストールが必要(リンクはウィザード内で提示されるので事前準備は不要)
  • Standard と Custom 選択するところがあるがとりあえず Standard
  • License Agreement の後、そこそこ長いダウンロードとインストールがある

プロジェクト作成&エミュレータで動かしてみる

開発環境を入れたところで「で、どうしようかな。。」と一瞬途方に暮れたかけたのですが、iOSだとどうするかな、と想像してみて、何はともあれプロジェクト作成してエミュレータで空のプロジェクトを動作させてみるのがいいのかなと。

  • バージョンはとりあえず 4.4 (自分の Android がそうだったので)以上
  • テンプレートは違いがわからないので Blank
  • ActivityNameとかLayoutNameなどなど、それぞれがどこに影響するかわからないのでデフォルトのままで

で、上部のバーに Xcode の Build & Run ボタンと同じようなのがあったので、


f:id:shu223:20141219131748p:image


押してみると、デバイス選択っぽいのが出てきて、無事エミュレータで動作しました!


f:id:shu223:20141219131817p:image:w250


ただ、ロック画面みたいなところから起動したので、Androidの操作自体がわからなくてちょっと困惑しましたが。。


書籍を入手

最初はWebでググるにも用語自体がわからなかったりするので、近所の書店に行って、参考書籍を購入しました。


つくるべきものは決まっているので、サンプルをチュートリアル的に進めるタイプのものではなく、「テーブルビュー的なのはどう実装するんだろう」という感じで逆引き的に調べられそうかどうか、を判断基準に、書店で目次を確認して選びました。


書籍1:Android StudioではじめるAndroidプログラミング入門

Android StudioではじめるAndroidプログラミング入門
掌田 津耶乃
秀和システム
売り上げランキング: 37,320


入門とありますが目次見るとわりと網羅的な感じがしたので購入しました。今こうやって見るとAmazonではなかなか厳しいレビューついてますね。。


書籍2:Androidアプリ開発逆引きレシピ (PROGRAMMER’S RECiPE)

Androidアプリ開発逆引きレシピ (PROGRAMMER’S RECiPE)
株式会社Re:Kayo-System
翔泳社
売り上げランキング: 94,035


逆引きレシピが欲しかったので最初に手に取りました。出版年月も新しめだし。


書籍3:Androidアプリ開発パーフェクトマスター―Android4/3/2.2完全対応 (Perfect Master)

Androidアプリ開発パーフェクトマスター―Android4/3/2.2完全対応 (Perfect Master)
金城 俊哉
秀和システム
売り上げランキング: 41,222


分厚すぎて絶対外に持ち出せないし、実用的じゃないんじゃないか。。と思いましたが、情報量は多いし、悩んでる時間がもったいないので購入。


UIImageView的なものを置いてみる

画像リソースの実態は、(フォルダ名の一般名称がわからないので自分の現在のプロジェクトで言うと)

MyFirstApplication/app/src/main/res

にあります。


が、画像の追加はプロジェクトウィンドウ内にある「drawable-mdpi」フォルダにドラッグ&ドロップするとのこと。(書籍1からの情報)


UIImageView的なUIコンポーネントは、Widgetsのところに「ImageView」というそのものズバリなものがあったので、それを配置。


画像の入れ方がよくわからなかったのですが(書籍1ではプログラムから入れていた)、ImageView を IB 的なところでダブルクリックしたら src 画像を選ぶダイアログが出てきて、無事 drawable-mdpi に入れたものを選択することができました。


f:id:shu223:20141219142442p:image:w220


UIViewContentMode的なプロパティと、このレイアウト周りがわからないけど、そのあたりは後回しで。。


ボタンを置いてみる

ボタンを押したらコンソールにログをはく、的なことをやってみます。

  • Widgetsに「Button」というのがあるので、それを配置
  • 右にあるプロパティウィンドウから、「onClick」を探して、「button_onClick」と入力
  • MainActivity.javaを開き、ボタンクリックのイベントハンドラを実装
public void button_onClick(View view) {
    Log.d("MyApp", "view:" + view);
}

(記念すべき初めてのコード!)


ボタンまわりは書籍1を、Log の書き方はググって下記記事を参考にしました。


で、これだとエラーが出たので、import を追記

import android.view.View;
import android.util.Log;

(使用クラスごとに必要なのか・・・!?そんなわけないと思うけど、おいおい学んでいきます。。)


f:id:shu223:20141219142623p:image:w220


ボタンを押すと、コンソールに次のように出力されました。

12-19 14:21:48.467 1911-1911/com.shu223.myfirstapplication D/MyApp﹕ view:android.widget.Button{9cf6a48 VFED..C. ...P.... 372,921-707,1065 #7f080041 app:id/button}


画面遷移

次は UINavigationController の push / pop 的な画面遷移を・・・と思ったのですが、買った書籍(総ページ数約2000!)を調べてみても見当たらず・・・*1


ググるとすぐに出てきました。


インテントは他のアプリと連携するときに用いるもので、他のアプリ(例えばブラウザアプリ、メールアプリ等)を起動することができます。


同じアプリでも他の画面 (Activity) クラスを起動する場合には、インテントを使用します。

そうなんですね、カルチャーショック。。


それはさておき、

画面の遷移は, 元画面(メイン画面)のアクティビティから次画面(サブ画面)のアクティビティを起動することで実現できる.

とのことなので、

  • メニューから新規アクティビティを作成
    • [File] > [New] > [Activity]
    • SubActivityと命名
  • SubActivity に Button を置き、onClick プロパティに button_onClick と入力
  • SubActivity.java に以下のコード(と必要なimport)を追記
public void button_onClick(View view) {

    Log.d("MyApp", "onClick:" + view);

    Intent intent = new Intent(SubActivity.this, MainActivity.class);
    startActivity(intent);
}
  • MainActivity.java のボタンのイベントハンドラを以下のように修正
public void button_onClick(View view) {

    Log.d("MyApp", "onClick:" + view);

    Intent intent = new Intent(MainActivity.this, SubActivity.class);
    startActivity(intent);
}

上記記事では AndroidManifest.xml へ SubActivity の定義を追加する必要がある、とありますが、自動的に追加されてました。


f:id:shu223:20141219152052g:image


テーブルビュー的なものを実装する

iOS でいう UITableView は、Android では「リストビュー」と呼ぶそうです。で、「アダプター」なるものが UITableViewDataSource 的役割をするっぽい(いや、それ以前の、単なる配列かも。。)

  • Containers にある「ListView」を配置
  • SubActivity.java の onCreate メソッド内に、以下のコードを追記
ListView listView = (ListView)findViewById(R.id.listView);
ListAdapter adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, DAYS);
listView.setAdapter(adapter);
  • 同じく SubActivity.java に、以下のコードを追記(static な配列を生成)
private static final String[] DAYS = new String[] {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

以上、「書籍2」の写経です。正直なところ、`R.id.listView` の `R` とか、`android.R.layout.simple_dropdown_item_1line` が何なのかとか全然わかっておりません。。


f:id:shu223:20141219162621p:image:w220


ちなみに コードから IBOutlet 的に UI オブジェクトにアクセスするにはどうしたらいいのか と思ってましたが、上記のように `findViewById` メソッドで取得するのが定石のようです。iOSでいえば `getViewWithTag` ですね。id は自動補完で出てきますが、IB的な画面の Properties の「id」からも確認できます。


実機で動かしてみる

ここまで忘れてたのですが、せっかく Android 端末を買ったので、実機で動かしてみます。


実機の「デベロッパーモード」を有効にする必要があるとのこと。「書籍3」に全編スクショ付きで載ってたので、Androidの使い方がわからない自分でも簡単でした。

  • [設定] > [端末情報]
  • 「ビルド番号」のところを7回タップ(おもろいw) -> デベロッパーモードになる
  • [設定] > [開発者向けオプション] > [USBデバッグ] を有効にする

あとはエミュレータの代わりに、実機を選択するだけ。


f:id:shu223:20141219165446j:image:w300


CSVファイルの読み込み

書籍に見当たらなかったのでググりました。


新規クラスファイルの生成方法がわからなくてけっこう困ったのですが、

app/src/main/java の位置で [File] > [New] しないと、メニューに「Java Class」というのが出ないようです。さらに、「com.shu223.myfirstapplication」と書かれているディレクトリ(パッケージ?)の下に置くと、他のクラスから扱えるようになるようです。


あと「プロジェクトの一番上」という表現もよくわからなかったのですが、 app/src/main 直下に assets という名前でディレクトリを作成すればOKでした。


  • assets ディレクトリを作成
    • 直下に csv ファイルを置く
  • CSVParser クラスを作成
package com.shu223.myfirstapplication;

import android.content.Context;
import android.content.res.AssetManager;
import android.util.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

/**
 * Created by shuichi on 14/12/19.
 */
public class CSVParser {

    public static void parse(Context context) {
        // AssetManagerの呼び出し
        AssetManager assetManager = context.getResources().getAssets();
        try {
            // CSVファイルの読み込み
            InputStream is = assetManager.open("params.csv");
            InputStreamReader inputStreamReader = new InputStreamReader(is);
            BufferedReader bufferReader = new BufferedReader(inputStreamReader);
            String line = "";
            while ((line = bufferReader.readLine()) != null) {
                // 各行が","で区切られていて4つの項目があるとする
                StringTokenizer st = new StringTokenizer(line, ",");
                String first = st.nextToken();
                String second = st.nextToken();
                String third = st.nextToken();
                String fourth = st.nextToken();

                Log.d("MyApp", "Parsed:" + first + second + third + fourth);
            }
            bufferReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  • SubActivity から呼んでみる
CSVParser parser = new CSVParser();
Context context = getApplicationContext();
parser.parse(context);

Context についてはググって下記記事を参考にしました。


実行結果については省略。


ボタンに応じてクリックイベントの処理を分岐させる

MainActivity にボタンを2つ置いて、iOS でいう tag で判別して次に遷移する画面を切り替える、みたいなことをやるには、id プロパティを使用するようです。

  • MainActivity.xml にボタンをもう1つ追加
  • 2つのボタンの id をそれぞれ、「button1」「button2」とする
  • MainActivity.java のイベントハンドラの実装を次のように変更する
public void button_onClick(View view) {

    switch (view.getId()) {
        case R.id.button1:
        {
            Intent intent = new Intent(MainActivity.this, SubActivity.class);
            startActivity(intent);
            break;
        }
        case R.id.button2: {
            Intent intent = new Intent(MainActivity.this, BLEActivity.class);
            startActivity(intent);
            break;
        }
    }
}

参考:クリックイベントに応答する - Android 開発入門


プロジェクトの API LEVEL を変更する

「APIレベル」って初耳でそもそも何なのかわかってないのですが、BLE 関連のコードを書き始めると、巷に情報がよく出ているサンプルコードの多くは `startLeScan`、 `stopLeScan` という BluetoothAdapter クラスのメソッドを使っていて、どうやらこれらは API LEVEL 21 で deprecated になっているらしい。


で、仕方なく推奨されている新しい方を使おうと思ってみたものの、付け焼き刃すぎて、サンプルがないとよくわからない。。


APIレベルってそもそも何なの?と調べてみると、

21とか全然新しすぎる模様。iOS でいえば 8 の API を使ってたようなものか。


で、どこで API レベルが設定されていて、どう変更するのが適切なのかなと調べてみると、build.gradle というファイルを更新する、と書いてあったのですが、

Android Studio の [File] > [Project Structure] > [Flavors] からも変更できました。


ここで「Target Sdk Version」を 19 に変えて、「Sync Project with Gradle Files」ボタン押下、リビルドしました。


結果・・・deprecated なメソッドの警告はなくなりませんでした。。


で、もう一度 [Project Structure] から、[Properties] の 「Comple Sdk Version」 にマニュアルで 19 といれてみたところ、SDKのインストールが始まって、なんやかんやあって、無事「API LEVEL 21 では deprecated だけど、それより下のバージョンでは OKなメソッド」の警告が消えました。。


BLEを利用する

BLE(Bluetooth Low Energy)については参考書籍3冊とも一切記載なし。


が、ググるといろいろと参考記事が見つかりました。


実際にやってみると、deprecated 問題(前項参照)とかいろいろ大変だったのですが、下記手順でいけました。

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
  • メンバ変数などの追加
private static final long SCAN_PERIOD = 10000;
private BluetoothAdapter mBluetoothAdapter;
private Handler mHandler;
static final int REQUEST_ENABLE_BT = 0;
  • 諸々初期化処理(onCreateにて)
BluetoothManager manager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = manager.getAdapter();

if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}

mHandler = new Handler();
  • スキャン開始ボタンのイベントハンドラ
public void onClickScan(View v) {

    Log.d("MyApp", "onClickScan");

    // 10秒後にスキャン停止
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }, SCAN_PERIOD);

    // スキャン開始
    mBluetoothAdapter.startLeScan(mLeScanCallback);
}
  • ペリフェラルが見つかると呼ばれるコールバック
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
    @Override
    public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
        // 見つかったペリフェラル情報をログ出力
    }
};

実行してみると、無事部屋にあるペリフェラルデバイスが見つかってました。

12-19 19:38:38.578    2287-2299/com.shu223.myfirstapplication D/BLEActivity&#65109; name=Kontakt, bondStatus=10, address=EE:FB:3B:6C:B8:BE, type2, uuids=
12-19 19:38:38.768    2287-2300/com.shu223.myfirstapplication D/BLEActivity&#65109; name=null, bondStatus=10, address=59:F9:0E:E7:AD:41, type0, uuids=
12-19 19:38:38.958    2287-2299/com.shu223.myfirstapplication D/BLEActivity&#65109; name=null, bondStatus=10, address=59:F9:0E:E7:AD:41, type0, uuids=
12-19 19:38:39.078    2287-2300/com.shu223.myfirstapplication D/BLEActivity&#65109; name=Kontakt, bondStatus=10, address=EE:FB:3B:6C:B8:BE, type2, uuids=
12-19 19:38:39.128    2287-2299/com.shu223.myfirstapplication D/BLEActivity&#65109; name=null, bondStatus=10, address=59:F9:0E:E7:AD:41, type0, uuids=
12-19 19:38:39.318    2287-2300/com.shu223.myfirstapplication D/BLEActivity&#65109; name=null, bondStatus=10, address=59:F9:0E:E7:AD:41, type0, uuids=
12-19 19:38:39.498    2287-2299/com.shu223.myfirstapplication D/BLEActivity&#65109; name=null, bondStatus=10, address=59:F9:0E:E7:AD:41, type0, uuids=

(iOS のセントラルマネージャのように、重複するペリフェラルについてはコールバックをまとめる、ということはやってくれない


アニメーション

PulsingHalo的なのを実装したくて着手していたのですが、所用につき今日はここまで。*2


所感

Android Studio という専用 IDE があるし、エミュレータもまぁ確かに遅いけど全然アリだし、関連書籍は充実してるし、ググれば大量に開発情報が出てくるしで、開発環境としては超快適だと思いました。iOSと比べてどうの、という不満は全くなし


ただ、やはり Android は、API群(SDK)がまるっきり違う上に開発言語や IDE も違うので、思った以上に「覚え直し」感がありました。。ひとつのアプリをプロダクト品質で出すまでにはまだまだ先が遠い印象。。


最近始めて Mac OS X アプリをつくったときは新しい世界が切り開かれる感じがしてワクワクしたのですが、やはり「モバイル端末でのアプリ開発」という似ている分野では自分はあまり新鮮味を感じられないのかなと。(ObjC->Swiftへのコンバートにもあまり興味が無いように)


そんなわけで、1日やってみた後の所感としては「おとなしく iOS の世界に戻ろう」という気持ちになっております。。


*1:あとでわかってみれば、載っていました。が、そもそもインテント、アクティビティという概念を知ってないと目次からは辿りつけない。。

*2:この後の予定としては、「レイアウト」「ボタン等の見た目のカスタマイズ」「デバッグ」などなど予定していました。

2014-12-12

iOSと機械学習

ビッグデータとかの機械学習隆盛の背景にある文脈や、その拠り所となるコンピュータの処理性能から考えても「モバイルデバイス向けOSと機械学習を紐付けて考えようとする」ことはそもそもあまり筋がよろしくない・・・とは思うのですが、やはり長くiOSだけにコミットしてきた身としては、新たに興味を持っている機械学習という分野と、勝手知ったるiOSという分野の交差点はないのかなと考えずにはいられないわけでして。。


そんなわけで、「iOS と機械学習」について雑多な切り口から調べてみました。


iOSで使える機械学習ライブラリ

DeepBeliefSDK

コンボリューショナルニューラルネットワークを用いた画像認識ライブラリ。iOSとかのモバイルデバイスで処理できるよう、高度に最適化してある、OpenCVと一緒に使うのも簡単、とのこと。


何はともあれ SimpleExample というサンプル実行したら、


f:id:shu223:20141211210821j:image


頼んでもないのにいきなりノートパソコンを認識しました!すごい!


SimpleExample のソースを見てみると、フレーム毎に得られるピクセルバッファの処理はこんな感じでした。

- (void)runCNNOnFrame: (CVPixelBufferRef) pixelBuffer
{
  assert(pixelBuffer != NULL);

	OSType sourcePixelFormat = CVPixelBufferGetPixelFormatType( pixelBuffer );
  int doReverseChannels;
	if ( kCVPixelFormatType_32ARGB == sourcePixelFormat ) {
    doReverseChannels = 1;
	} else if ( kCVPixelFormatType_32BGRA == sourcePixelFormat ) {
    doReverseChannels = 0;
	} else {
    assert(false); // Unknown source format
  }

	const int sourceRowBytes = (int)CVPixelBufferGetBytesPerRow( pixelBuffer );
	const int width = (int)CVPixelBufferGetWidth( pixelBuffer );
	const int fullHeight = (int)CVPixelBufferGetHeight( pixelBuffer );
	CVPixelBufferLockBaseAddress( pixelBuffer, 0 );
	unsigned char* sourceBaseAddr = CVPixelBufferGetBaseAddress( pixelBuffer );
  int height;
  unsigned char* sourceStartAddr;
  if (fullHeight <= width) {
    height = fullHeight;
    sourceStartAddr = sourceBaseAddr;
  } else {
    height = width;
    const int marginY = ((fullHeight - width) / 2);
    sourceStartAddr = (sourceBaseAddr + (marginY * sourceRowBytes));
  }
  void* cnnInput = jpcnn_create_image_buffer_from_uint8_data(sourceStartAddr, width, height, 4, sourceRowBytes, doReverseChannels, 1);
  float* predictions;
  int predictionsLength;
  char** predictionsLabels;
  int predictionsLabelsLength;

  struct timeval start;
  gettimeofday(&start, NULL);
  jpcnn_classify_image(network, cnnInput, JPCNN_RANDOM_SAMPLE, 0, &predictions, &predictionsLength, &predictionsLabels, &predictionsLabelsLength);
  struct timeval end;
  gettimeofday(&end, NULL);
  const long seconds  = end.tv_sec-- start.tv_sec;
  const long useconds = end.tv_usec - start.tv_usec;
  const float duration = ((seconds) * 1000 + useconds/1000.0) + 0.5;
  NSLog(@"Took %f ms", duration);

  jpcnn_destroy_image_buffer(cnnInput);

  NSMutableDictionary* newValues = [NSMutableDictionary dictionary];
  for (int index = 0; index < predictionsLength; index += 1) {
    const float predictionValue = predictions[index];
    if (predictionValue > 0.05f) {
      char* label = predictionsLabels[index % predictionsLabelsLength];
      NSString* labelObject = [NSString stringWithCString: label];
      NSNumber* valueObject = [NSNumber numberWithFloat: predictionValue];
      [newValues setObject: valueObject forKey: labelObject];
    }
  }
  dispatch_async(dispatch_get_main_queue(), ^(void) {
    [self setPredictionValues: newValues];
  });
}

・・・と決してシンプルとは言い難いですが、ここで行っている分類処理のコアは、

jpcnn_classify_image(network, cnnInput, JPCNN_RANDOM_SAMPLE, 0, &predictions, &predictionsLength, &predictionsLabels, &predictionsLabelsLength);

この1行にあるのかなと。で、あとはバッファまわりの諸々とか、得られた結果の処理とか。


おもしろそうなので、また別の機会にちゃんと見てみようと思います。


ML4iOS

iOSでの機械学習を行うためのオープンソースライブラリ。ライセンスは Apache License, Version 2.0 。


コミット履歴を見ると、3年前(2012年1月)からあり、つい最近も更新されています。


LearnKit

iOS, OS X 向け機械学習フレームワーク、とのこと。


サポートしているアルゴリズム

  • Anomaly Detection
  • Collaborative Filtering
  • Decision Trees
  • k-Means
  • k-Nearest Neighbors
  • Linear Regression
  • Logistic Regression
  • Naive Bayes
  • Neural Networks
  • Principal Component Analysis

READMEに下記のようなサンプルコード載ってるので、今度試す。

LNKNeuralNetClassifier *classifier = [[LNKNeuralNetClassifier alloc] initWithMatrix:matrix 
                                                                 implementationType:LNKImplementationTypeAccelerate
                                                              optimizationAlgorithm:algorithm
                                                                            classes:[LNKClasses withRange:NSMakeRange(1, 10)]];
[classifier train];

LNKClass *someDigit = [classifier predictValueForFeatureVector:someImage length:someImageLength];

使いやすそう。


mlpack-ios

mlpack を Objective-C プロジェクトにリンクできるようにしたもの、とのこと。


mlpack というのは「スケーラブルなC++機械学習ライブラリ」らしい。


Swift-Brain

Swiftで書かれた人工知能/機械学習ライブラリ。ベイズ理論、ニューラルネットワーク、その他AIが実装されているとのこと。


  • Matrices
    • Matrix operations
  • Machine Learning algorithms
    • Basic Regressions
    • Neural Networks
    • Support Vector Machines
    • Bayesian Classifiers
    • Self Organized Maps (maybe?)
    • Clustering
  • Statistics
    • Bayes Theorem/Naive Classifier
    • Kalman Filter
    • Markov Model

学習結果をiOSで利用

機械学習によって得られたモデル等をiOSで利用する」ケースです。


冒頭で、「iOSと機械学習を結びつけて考えるのはあまり筋がよろしくない」と書きましたが、このケースでは学習自体はiOSデバイスではなくバックエンド(という表現が正しいかは不明)で行うので、至極真っ当、というか王道かと。


画像認識

OpenCV for iOS に機械学習で作成したモデル(分類器)のxmlファイルをアプリに持たせれば、人の顔以外にもいろんなものを認識できますよ、という記事。



分類器自体はプラットフォーム依存ではないので、iOSという限定を外せばかなり色々とチュートリアル記事とかモデル配布記事がでてきます。


文字認識

iOS で使える OCR ライブラリ。


機械学習で精度を向上させたり、日本語を覚えさせたり。


参考:画像からのテキスト抽出:tesseract-ocr - Qiita


音声認識

こういう話でいえば、同様に、iOS用の音声認識エンジンも学習データを用意してモデルを自作することができます。

OpenEars は PocketSphinx (CMU Sphinx) というカーネギーメロン大学によるオープンソース認識エンジンのラッパーライブラリで、それ用の音響モデルを自作することはできます(とある案件で試したことあり)。


国産の「大語彙連続音声認識エンジン Julius」(iOSで利用可能)も、もちろん学習によりモデルを自作できます。


実例集

ストアに出ているアプリなど。


Deep Belief by Jetpac - teach your phone to recognize any object

上でも紹介した、DeepBeliefSDKを使ったアプリ。


f:id:shu223:20141211211050j:image:w200


このアプリでネコを認識するデモ動画。


Deep Learning

ディープラーニングで画像を分類するアプリ。


f:id:shu223:20141211211118j:image:w200


Summly

2011年12月と、ちょっと古い記事ですが、Summlyという「ウェブのコンテンツを箇条書きとキーワードの一覧に要約する」アプリのニュース記事。

まずは、特別なアルゴリズムでHTML処理を使って、ウェブページからテキストを抜き出すことから始まる。そのテキストを分析して、記事から選び出された「凝縮された部分」を箇条書きで吐き出す。Summlyのアルゴリズムは、いくつもの機械学習の手法と「遺伝的」アルゴリズム――進化をまねた発見的探索法――を利用してこれを行っている。

ダロイジオ氏のアルゴリズムは、さまざまな出版社によるいろいろなタイプの記事の、人間による要約を調査した。そしてこれらの要約を、Summlyが吐き出すべきものや、情報キュレーションを行う人間の仕事をうまく真似るための、メトリクス[尺度]を調整する際のモデルとして活用した。


その後 Yahoo! に買収され、Yahoo!のニュース要約とパーソナライズ表示、動画、画像検索機能等にその技術が用いられているとのこと。


Plant Recognition: Bringing Deep Learning to iOS

ディープラーニングで植物を認識する、という論文。


f:id:shu223:20141211211217j:image


おわりに

iOS と機械学習を絡めたお仕事、お待ちしております!


2014-12-11

「FILTERS」で学ぶ GLSL

GLSL を書いてオレオレフィルターをつくれる」というコンセプトのカメラアプリがリリースされました。


f:id:shu223:20141211164529j:image:w600

Filters〜世界一面白いカメラフィルターが、ここから生まれる。〜



シェーダを書いて動的に適用する、というアイデア自体は昔からあるものですが、


wonderfl や jsdo.it をつくったカヤック製アプリなので、

  • フォークできる
  • リアルタイムプレビューしてくれるエディタでコード(GLSL)を書ける
  • シェアできる

という非常に魅力的な点があります。あと前述の従来品はサンプルだったりするので、もちろんカメラアプリとしてのクオリティも全然違います。



既に魅力的なフィルタがいろいろとアップされています。


f:id:shu223:20141211164641g:image


GLSL には興味があったものの、なかなか勉強する機会がなかったので、他の方がつくったフィルタをフォークしてコード(GLSL)を読みつつコメントを入れていくということをやってみました。


タイトルの後ろに (commented) と入れているので、よろしければ参考にしてみてください。*1


以下、いくつか紹介していきます。


グレースケールにする

入力画像をグレースケールに変換するフィルタ。


f:id:shu223:20141211164705j:image


これはフィルタを新規作成すると生成されるデフォルトテンプレートの最後の行だけいじってコメントを入れたもの。GLSLを書いてみる最初の1歩として、この3行を理解するといいかもしれません。


grayscale (commented)
void main()
{
    // 座標を取得
    vec2 uv  = iScreen;
    
    // カメラからの入力テクスチャから、該当座標の色を取得する
    vec4 color = texture2D(iCamera, uv);
  
    // RGBのGとBをRで置き換えた色を生成して適用
    gl_FragColor = vec4(color.r,color.r,color.r, 1.0);
}

歪める&青っぽくする

入力画像を歪め、全体的に青っぽくするフィルタ。


f:id:shu223:20141211164756j:image


iCamera(カメラからの入力テクスチャ) + texture2D関数で、入力画像の任意の座標の色をとってこれることを利用して、座標をx,yそれぞれ2乗した先の画素値をとってきて歪みを実現しています。


water (commented)
void main()
{
    // 座標取得
    vec2 scr = iScreen;
  
    // 座標に応じて近隣の色を取得する
    // (カメラの入力テクスチャから、注目座標のx,yを2乗した座標の色をとってくる
    vec4 color  = texture2D(
      iCamera,
      vec2(
        pow(scr.x, 2.0),
        pow(scr.y, 2.0)
      )
    );
  
    // 青っぽくして適用
    gl_FragColor = vec4(
      vec3(
        color.r *   0.0 / 255.0,
        color.g * 153.0 / 255.0,
        color.b * 204.0 / 255.0
      ),
      1.0
    );
}

画像の一部にモザイクをかける

ピンポイントにモザイクをかけるフィルタ。ピンチイン・アウトにも対応。


f:id:shu223:20141211164814j:image


モザイク処理は、座標値を floor 関数で粗くして周辺画素と同じ色を使用することで実現されています。


また、出力位置が円の中にあるかどうかでモザイクをかける・かけないを判定して、円形のモザイク処理が実現されています。


ピンチイン・アウトに対応しているので座標処理がちょっと複雑な感じがする場合は、いったん iSize をなくして考えてみるとわかりやすいかもしれません。


Pinpoint Mosaic
// 白色を定数として定義
const vec3 white = vec3(1.0, 1.0, 1.0);

// 座標positionが、半径size・中心座標offsetにある円の内側にあるかを判定する
bool inCircle(vec2 position, vec2 offset, float size) {
    float len = length(position - offset);
    if (len < size) {
        return true;
    }
    return false;
}

void main( void ) {
    // 座標取得
    vec2 uv = iScreen;
    // 座標を粗くする(15 x ピンチサイズ倍して切り捨て)
    uv = floor(uv * iSize * 15.0) / 15.0 / iSize;
    // 粗くした座標の色を取得
    vec4 color = texture2D(iCamera, uv);
    
    // 白色(whiteは定数として定義済み)を生成
    vec3 destColor = white;
    // 出力位置を計算
    vec2 position = (gl_FragCoord.xy * 2.0 - iResolution) / min(iResolution.x, iResolution.y);
    
    // 出力位置が円の内側にあるか?
    if (inCircle(position, iPosition, 1.0 + (1.0 - iSize))) {
        // モザイク化する(粗くした座標の色を使用)
        destColor = color.rgb;
    }
    else {
      
        // モザイク化しない(元々の色を使用)
        destColor = texture2D(iCamera, iScreen).rgb;
    }
    
    // 決定した色を出力出力
    gl_FragColor = vec4(destColor, 1.0);
}

所感

FILTERS、GLSLの勉強におすすめです!


(GLSL関連記事)


(余談)iOS 8 とシェーディング言語

シェーダが書けると iOS の Core Image のフィルタ(CIFilter)も自作できるようになります。(iOS 8 から)


拙作『iOS8-Sampler』にもシェーダを書いて作成したカスタムフィルタのサンプルがいくつか入っています。


(2014.12.12追記)他のアプリからFILTERSのフィルタを使う



ってツイートしたら、中の人からリプライがあり、なんと既に Photo Editing Extension 対応してるとのこと。すごい!


標準の「写真」アプリから試してみました。


f:id:shu223:20141212134814j:image


現状では、上位30個ぐらいのフィルタが選べるようです。



*1:なお、コードをシンプルにするため、処理に使われていない関数や定数は削除しました。

2014-12-10

アップルによるBluetoothアクセサリの設計ガイドラインに書かれていたこと

『Bluetooth Accessory Design Guideline for Apple Products』という、Appleによる公式ドキュメントがあります。Mac や iOS デバイス、iPod 等の Apple 製品の Bluetooth アクセサリの設計についてのガイドラインです。


本記事では、このドキュメントから iOS エンジニアも知っておいた方が良さそうな部分 を抜粋していきたいと思います。


※本記事は、Bluetooth Low Energy Advent Calendar 2014 - Qiita 9日目の記事です。


アドバタイズ間隔

アドバタイズ開始から少なくとも30秒間は、推奨アドバタイズ間隔である 20 ms を使用すべき」と明記されています。

To be discovered by the Apple product, the accessory should first use the recommended advertising interval

of 20 ms for at least 30 seconds.


で、この最初の30秒間で発見されなければ、バッテリー節約のため下記のより長いアドバタイズ間隔のいずれかを使用することを推奨する、と。

If it is not discovered within the initial 30 seconds, Apple recommends using

one of the following longer intervals to increase chances of discovery by the Apple product:

  • 152.5 ms
  • 211.25 ms
  • 318.75 ms
  • 417.5 ms
  • 546.25 ms
  • 760 ms
  • 852.5 ms
  • 1022.5 ms
  • 1285 ms

ちなみに BLE の規格で定められているアドバタイズ間隔は、最小 20[ms] 〜 最大 10.24[s]の範囲で 0.625[ms]の整数倍 なので、Appleによる「最初の30秒間の推奨アドバタイズ間隔」はBLE規格上の最小間隔でもあります。


iOSエンジニアとしては、このあたりのアドバタイズ仕様を把握しておくと、セントラルとしてふるまうアプリにおいてスキャンをどう行うかの設計や、iBeacon の利用する際に役立つかもしれません。


Connection Parameters

以下の全てのルールに従っていないと、接続パラメータ要求は(iOSから)拒絶される可能性がある、と書かれています。

  • Interval Max * (Slave Latency + 1) ≤ 2 seconds
  • Interval Min ≥ 20 ms
  • Interval Min + 20 ms ≤ Interval Max Slave Latency ≤ 4
  • connSupervisionTimeout ≤ 6 seconds
  • Interval Max * (Slave Latency + 1) * 3 < connSupervisionTimeout

If Bluetooth Low Energy HID is one of the connected services of an accessory, connection interval down to

11.25 ms may be accepted by the Apple product.


The Apple product will not read or use the parameters in the Peripheral Preferred Connection Parameters

characteristic


iOSエンジニアとしては、Connection Interval が「20 ms 以上」と明記されている部分は情報として非常に有用なのではないでしょうか。


こういう計算が考え方として正しいものなのか、ちょっと自信がない(他に考慮すべきことがあるかも)のですが、Connection Intervalが20msということは、1秒間に50回データの送受信が可能、ということなので、1パケット20byteとして、


20 * 50 = 1000 bytes / sec = 1k byte / sec = 8k bits / sec

というわけで、iOSとBLE接続するデバイスとの最大通信速度は約8kbps、ということがいえるのではないでしょうか。


他にも、connSlaveLatency(スレイブが送信するデータがなにもないときに、コネクション・イベントを無視出来る回数)や connSupervisionTimeout (接続が失われたと判断する、コネクション・イベントの失敗回数)の条件式も明示されているので、どういう条件で接続が失われるのか、を具体的に把握する指針となり、参考になります。


参考:BLEの通信仕様 - Reinforce-Lab.’s Blog


Service Changed Characteristic

そのアクセサリがサービスを変更する可能性のある場合(つまり、GATT を変更する可能性がある場合)は "Service Changed Characteristic" を実装しましょう、と書かれています。

The accessory shall implement the Service Changed characteristic only if the accessory has the ability to change

its services during its lifetime.


アップル製品は、前回読んだ(キャッシュした)情報に依るかどうかを "Service Changed Characteristic" を使って決めますよ、と。

The Apple product may use the Service Changed characteristic to determine if it can rely on previously read

(cached) information from the device.


これの話ですね。


Core Bluetooth でいうと、サービス変更時に CBPeripheralDelegate の `peripheral:didModifyServices:` が呼ばれる、という件ですが、そもそもアクセサリ側で "Service Changed Characteristic" が実装されている必要があります。(実装されてなければ iOS の Bluetooth 設定を off/on してキャッシュクリアする)


Siri

「カスタム Siri コマンドを有効にする」「Siri のアベイラビリティ情報を取得する」「Siri セッションの初期化」「Siri Eyes Free Mode」「Siriセッションを最適化する」などなど興味を惹かれるタイトルが並んでいますが、HFP プロファイルとかのクラシック Bluetooth の話で Core Bluetooth でどうこうできる範囲ではないのでスルー。


「6.5 Improving Voice Recognition」も iOS エンジニアがどうこうできる部分ではないが、S/N比の推奨は 20 dB 以上 とか書いてあって、Siri とか関係なく、良好な音声入力の基準値として今後 iOS で音声処理やる際の改善のヒントになりそうです。


関連

上原さんのブログにBLE部分を日本語訳したものがまとめられています。


2014-12-09

機械学習はじめの一歩に役立つ記事のまとめ

「機械学習」というワードになんとなく惹かれつつも、具体的にやりたいことがあるわけでもないので、手を動かすことなくただひたすら「いつかやる」ために解説記事やチュートリアル記事を集める日々を過ごしていたのですが、このままじゃイカン!と Machine Learning Advent Calendar 2014 - Qiita に参加登録してみました。


が、やはり何もしないまま当日を迎えてしまったので、お茶濁しではありますが、せめて「機械学習ってどんな手法やライブラリがあって、どんな応用先があるのか?」というあたりをざっくり把握して最初に何をやるのか方向付けをするためにも、たまりにたまった機械学習系の記事をいったん整理してみようと思います。


機械学習の概要

特定のライブラリや手法の話ではなく、機械学習全般に関する解説。


機械学習チュートリアル@Jubatus Casual Talks


冒頭に、

  • 初めて機械学習を聞いた⼈人向けです
  • 数式を使いません
  • ガチな⼈人は寝てて下さい

とある通り、機械学習ってそもそも何?どう嬉しいの?というところがスタート地点である自分にとってすごくありがたかったスライド。


ざっくり目次的なものをまとめると(かなり抜粋)、

  • 機械学習って何?
    • 例: スパム判定、商品推薦、コンピュータ将棋・囲碁・チェス
    • その他適用分野
    • 機械学習が向かないタスク
    • ルールベースとの比較
  • 機械学習って何してるの?
    • 教師あり・教師なし学習とは?両者の目的の違い
    • 線形分類器(図解がわかりやすかった)


Python / scikit-learn

Python で機械学習しよう!(環境構築 on Mac編) - もろず blog

Mac 上に Python で数値計算、機械学習を行うための環境構築の手順。全編スクショ付きですごくわかりやすいです。(が、あくまで環境構築手順だけで、実際に機械学習を行ってみるところまではカバーされていません)


インストールする数値計算、機械学習ライブラリは以下の4つ。

  • NumPy

数値計算を効率的に処理するためのライブラリです

配列の操作がとても簡単になるので、行列計算には必須っぽいです

  • SciPy

様々な科学計算が実装されたライブラリです

内部でNumPyを利用しています

  • matplotlib

グラフ描画のライブラリです

内部でNumPyを利用しています

  • scikit-learn

機械学習に関する様々なアルゴリズムが実装されたライブラリです


機械学習の Python との出会い — 機械学習の Python との出会い

NumPy や SciPy などの科学技術計算モジュールの具体的な使い方を学べるチュートリアル。PDF版やePub版も用意されていて、もはや書籍。


前書きにもある通り、機械学習のごくごく初歩的な話とか、Pythonのごくごく初歩的な話は省略されているので、はじめの二歩目ぐらいに目を通すとよさそうです。

このチュートリアルでは,いろいろな機械学習の手法を Python で実装する過程をつうじて,NumPy や SciPy など科学技術計算に関連したモジュールの具体的な使い方を説明します. 機械学習の手法についてはごく簡単な説明に留めますので,詳細は他の本を参考にして下さい. また,クラスなどのプログラミングに関する基礎知識や,Python の基本的な文法については知っているものとして説明します.


(目次)

  • はじめに
    • 本チュートリアルの方針
  • 単純ベイズ:入門編

最初に実装するのは,特徴量がカテゴリ変数である場合の単純ベイズ (Naive Bayes) です. この単純ベイズの実装を通じて,NumPy / SciPy を用いた行列・ベクトルの初歩的な扱いについて説明します.

    • NumPy 配列の基礎
    • 単純ベイズ:カテゴリ特徴の場合
    • 入力データとクラスの仕様
    • 学習メソッドの実装(1)
    • 予測メソッドの実装
  • 単純ベイズ:上級編

単純ベイズ:入門編 で実装した NaiveBayes1 クラスを,NumPy のより高度な機能を利用して改良します. その過程で,NumPy の強力な機能であるブロードキャストの機能と,この機能を活用する手順を紹介します.

    • クラスの再編成
    • 単純ベイズの実装 (2)
    • 配列の次元数や大きさの操作
    • ブロードキャスト
    • クラスの分布の学習
    • 特徴の分布の学習
    • 実行速度の比較

pythonの機械学習ライブラリscikit-learnの紹介 - 唯物是真 @Scaled_Wurm

Python の機械学習ライブラリ scikit-learn のチュートリアル。scikit-learn でできること(機能)がカタログ的に紹介されています。


それぞれの機能について簡単なサンプルコードと実行結果が示されているので、色々とつまみ食い的に試してみるのによさげ。

  • サンプルデータの自動生成

sklearnにはIrisなどのトイデータセットやサンプルデータの自動生成などの機能もあります。

(0のデータ)

  • 線形SVMによる二値分類

データをトレーニング用とテスト用に分けて、トレーニングデータで訓練したモデルでテストデータを予測してみます。

  • 分類結果の評価

分類器で得られた推定結果がテストデータとどれぐらい一致しているかでモデルの評価を行います。

  • クロスバリデーション(交差検定)

上のほうで二値分類を試すときにデータをトレーニング用とテスト用に分解しました。しかし、データを分けるとそれぞれに使えるデータが少なくなってしまいます。

クロスバリデーションではデータをいくつかに分割して、1個をテスト用、残りをトレーニング用に使ってスコアの計算をします。このとき分けられたデータのすべてがテストに選ばれるようにくりかえし評価を行い、そのスコアの平均を使って評価をします。

  • グリッドサーチ

適切なパラメータを選ぶのによく使われるのがグリッドサーチという方法で、これはいくつかのパラメータの組み合わせを実際に試して評価関数を計算し、スコアがよかったパラメータを選ぶというものです

  • 不均衡データ

ラベルごとのデータ数が大きくアンバランスなデータだと学習がうまくいかないときがあります。たとえば正例:負例=1:100とかだったりすると、十分なデータがあっても訓練したモデルはすべてを負例に分類してしまったりします。こういうときはクラスに対する重み(LinearSVCならclass_weight)を変えたりresample関数を使ってトレーニングデータ内の比率が1:1に近くなるようにアンダーサンプリングやオーバーサンプリングをしたりすると結果がよくなることがあります。

  • 特徴量の抽出

分類器のモデルの入力(データのベクトルによる表現)をどうやって作るかという話


scikit-learnを用いた機械学習チュートリアル

scikit-learn のチュートリアルスライド。


スライドというメディアの特性上、コードは少なく図が多いので、上の「pythonの機械学習ライブラリscikit-learnの紹介」に出てくる機能の補助資料として読むとよさそうです。


Deep Learning

Python - はじめるDeep learning - Qiita

ずっと「ディープラーニング」というキーワードは「何かすごそう」ぐらいに気にはなってて意味はわかってなかったのですが、冒頭の説明が超わかりやすかったです。

つまるところ、Deep learningの特徴は「特徴の抽出までやってくれる」という点に尽きると思います。

例えば相撲取りを判定するモデルを構築するとしたら、普通は「腰回りサイズ」「マゲの有無」「和装か否か」といった特徴を定義して、それを元にモデルを構築することになります。ちょうど関数の引数を決めるようなイメージです。

ところが、Deep learningではこの特徴抽出もモデルにやらせてしまいます。というか、そのために多層、つまりDeepになっています。

具体的には頭のあたりの特徴、腰のあたりの特徴、そしてそれらを複合した上半身の特徴・・・というように、特徴の抽出を並列・多層に行って学習させて、それでもって判定させようというのが根本的なアイデアです


deep learning の代表的なライブラリも挙げられていました。

  • pylearn2
  • Caffe
  • nolearn
  • deepnet
  • yusugomori/DeepLearning

通常なら最新の実装も搭載されているpylearn2、画像認識ならCaffeらしいです(経験者談)。


研究やとりあえず試してみる場合に必要になる学習データを提供してくれているサイトのリストもまとめられていて、即ストックさせていただきました。


最後に pylearn2 を用いた実践手順もあり。


Deep learning


いろいろなところからリンクされていたスライド。Deep Learning の手法について図解でわかりやすく解説 ・・・されているはずなのですがちょっとよくわからなかったのでまた読もうと思います。


一般向けのDeep Learning

専門家向けではなく、一般向けに Deep Learning について説明してくれているスライド。


DeepLearning - RBMから考えるDeep Learning ?黒魔術を添えて? - Qiita

たぶん全然はじめの一歩ではないのですが、かなり詳しく書かれていて、実装についても追記される(2014年12月9日現在未完とのこと)なので、deep learning がちょっとわかってきた頃にまたあとで読むと勉強になりそうだなと。


Pythonとdeep learningで手書き文字認識


Python の Deep Learning ライブラリ、THeano を使用して手書き文字認識。前段の Deep Learning 自体の解説も噛み砕かれていて、わかりやすそうです。


DeepLearning - Theano の 基本メモ - Qiita

Deep Learning ライブラリ、THeano のチュートリアル。


Weka

機械学習(データマイニング)ソフトのWeka。Mac版もあり。*1



とある知り合いの大学院生が使っていて、GUIをポチポチしていくだけであらかじめ実装されている各種アルゴリズムによりデータが自動分類されていくという様子を目の当たりにして、今度自分も試してみよう、と思い記事だけ集めて今に至ります。


Weka入門 〜決定木とデータセットの作り方〜 in松村研

インストール〜実際にデータを分析するまでのチュートリアル。全編スクショ付きで非常にわかりやすそうです。Windows版ですが、たぶんMacでもほぼ同じかと。


決定木をつくる、入力データを用意する、のあたりはあらかじめ用意されているサンプルデータを使用するのですぐに試せるし、分析結果の見方も解説されているので、とりあえずプログラミングなしで体験してみるのによさそうです。


社会人MBA?技術者編
  • どうマイニングする?
  • 決定木分析?
  • 決定木分析?-1
  • 決定木分析?-2
  • 決定木分析?予測する
  • 決定木分析?因果関係を知る
  • 記憶ベース推論?
  • 記憶ベース推論?
  • ニューラルネット
  • 複数の分析を行う
  • アソシエーション分析?
  • アソシエーション分析?
  • ROC曲線とlift chart 補足1
  • 補足 研究開発部門での使用
  • 関連リンク集
  • データマイニング入門

リンク先に、これらの内容を再構成してまとめられたPDFもあります。


はじめてのweka勉強会 −修正版− - sleeping vote

arff形式のデータをテキストエディタで自分でつくってみる、クラスタリングするプログラムを書いてみる、ちょっとソースをいじって手法を変えてみる、といった方法が説明されていて、Wekaを使う第2歩目ぐらいによさそうです。


応用・実例

機械学習は手法も応用も多岐にわたるので、具体的な応用・実用例も集めています。


Googleの猫認識 (Deep Learning) - 大人になってからの再学習

ディープラーニングの記事を見ていると、事例として必ず出てくる、Googleの猫認識の話(ネコという概念を、コンピュータがYoutubeの動画を見続けることで自動学習したという話)について、この記事では、Deep Learning がどのように用いられているか、を噛み砕いて解説してくれています。



画像認識によって焼きたてパンの種類を判断できるレジ装置
  • 購入客がパンをトレーに載せてレジ横にあるカメラの下に置くと、BakeryScanが撮影画像を基に、パンの種類を自動判断
  • 準備作業として、パン1種類につき10個分の写真を撮影してBekaryScanに読み込ませる
    • BakeryScanが10個分の画像から、あんパンやメロンパンなど種類ごとの「画像モデル」を自動的に生成
  • 大きさや形、色、表面の状態、テクスチャーといった画像モデルの「特徴」は、B開発元があらかじめ100種類ほど設定
  • 特徴の「重み」については、店が読み込ませたパンの画像データを機械学習して、BakeryScanが自動調整

低解像度の画像から、自動車のナンバープレートのナンバーを識別
  • あるナンバープレートの画像について、高解像度のデータと低解像度に圧縮したデータをペアとして読み込ませて機械学習を行い、ナンバープレートの圧縮パターンの「辞書」を作成
    • この辞書を逆引きすることで、低解像度の画像から高解像度の画像を類推・生成
  • 自動車のナンバープレートのほか、人間の顔の圧縮パターンも機械学習させた
    • 低解像度の監視カメラ画像の解像度を高め、写った人物の顔写真を正確に推測

(元記事より)

英文の誤りを見つけ出し、ネイティブが書いたかのような文章に校正
  • Lang-8が大量に保有する、非ネイティブである学習者が書いた「誤った文章」と、ネイティブの指導者が校正した「正しい文章」のペアのデータを利用
  • これらペアのデータを100万件以上提供してもらい、機械学習させた
    • 間違いのパターンや、その正答パターンをモデル化
    • こうしたモデルを、新たな「間違った英文」に適用することで、誤り箇所とその正答候補を探し出す
  • 現在の校正精度は36.2%
    • 言語学者が人力でデータをつくり、機械学習させる従来手法の校正精度は23%程度だった
    • データの件数を100倍以上に増やすことで、校正精度を13ポイント高めた

大規模AV画像データベースと類似顔画像検索を用いたAV検索システム

「顔画像をもとに似た顔の人が出ているAVを検索するシステム」について書かれた論文。

類似する顔の検索には、HOG 特徴 という特徴量を使用しているとのこと。

実装言語は Python、使用ライブラリは OpenCV, SciPy, Numpy。


指し手を「機械学習」することで将棋アルゴリズムを自動生成
  • 最新の将棋プログラムのアルゴリズムは、コンピュータがプロ棋士による数万局の対局データ(棋譜)を分析し、指し手を「機械学習」することで自動生成されたもの
    • 過去の将棋プログラムのアルゴリズムは、プログラマーが将棋の知識と経験を駆使して手作りしていた
  • ある局面の有利さや不利さを、その局面の「特徴」と「重み」の積の合計として数値化
    • 特徴とは、駒の種類や数、位置関係、王将の危険度といった要素
    • 特徴ごとに重みが設定してあり、「金」なら400点、「飛車」なら700点、王将の近くに敵の駒がある場合はマイナス500点といった具合
  • 機械学習によりこれらの重みを自動調整

MachineLearning - 大量のニュースから興味関心のある話題をベイジアン分類で抽出する - Qiita

Ruby の naivebayes を使用。


あと、「フィードデータをためる方法」で触れられている Fastladder が気になりました。


MachineLearning - 金貨が本物かどうか見極める - Qiita

scikit-learn で線形分離。


MachineLearning - 食べられるキノコを見分ける - Qiita

K-Means クラスタリング


ねこと画像処理 part 2 – 猫検出 (モデル配布) « Rest Term

OpenCV の分類器作成

  • Boosting でのモデル作成
  • LBP特徴量を使用

ちなみにこのテーマについては前段として昨年書いたこの記事もよろしければ併せてお読みください:


Ruby - 最新記事のいいね!数を予測してみる - Qiita

言語は Ruby、単語抽出に mecab 使用。

  • 記事に含まれる単語をmecabで抽出
  • → その記事のいいね!数に応じてその単語にポイントを付与
  • → 単語ごとに出現数とポイントをデータベース化して教師データとする

機械学習 - ナイーブベイズでツンデレ判定してみた - Qiita

Python - twitter streamingAPIで突発的な流行語を抽出 - Qiita

東京都議会議員選挙の党派マニフェストを自動分類したよ - sleeping vote

2009年7月12日投開票の東京都議会議員選挙において、主要6党(自民党、民主党、公明党、共産党、幸福実現党、生活者ネットワーク)の会派マニフェストに書いてある内容を品田方式と呼ばれる選挙研究で使う分類カテゴリに従い、分類したもの

分類作業は、stiqが研究している自然言語処理と機械学習*1の方法を用いて自動分類コーディングシステムを構築し、それを使っています。

具体的なシステムの仕組みは、論文にかかれているとのこと。


佐村河内識別システム - ぱろすけ’s website

近年、自称作曲家・佐村河内守氏と外見の酷似した人物が増加し、彼らと佐村河内氏とを自動的に見分けるシステムの開発が望まれている。一方で、佐村河内氏は作曲時と謝罪会見時で大きく外見的に変化することが知られており、佐村河内氏を見分けるシステムはそのような変化に頑健である必要があるため、実現は容易ではない。本プロジェクトでは、高度なコンピュータ技術を活用し、佐村河内氏を適切に見分けるシステムを開発する。


以下2つの手法を適用したとのこと。

Fisher Vector Faces [Simonyan et al. BMVC 2013] では、一般の物体の認識に用いられる Fisher Vector (FV) と呼ばれる手法を顔画像へと適用し、顔のパーツを明示的にモデリングせずに、高精度の識別結果を記録した。顔の領域を検出し、顔の向きを合わせるなどの前処理を行った後は、ただ通常の物体認識と同様の手続きを適用するのみである。

DeepFace [Taigman et al. CVPR 2014] は Facebook 社の発表した研究であり、「ほぼ人間並みの識別能力を実現した」として大きな注目を集めた。こちらでは、顔検出と向きの補正を行った後に、Deep Convolutional Neural Networks (DCNN) と呼ばれる手法を用いて識別を行う。こちらも一般の物体の認識に用いられる手法であり、一部に独自の改良を施してはいるが、処理の大筋は顔画像に限るものではない。


(すごい精度・・・!)


*1データマイニングと機械学習を混同するのはよくなさそうで、Wekaはどっちかというとデータマイニングの文脈っぽいですが、せっかくなので一緒に整理しておきます。

2009 | 08 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |