kivantium活動日記

プログラムを使っていろいろやります

2017年5月 第4週

印象的だったニュース

SoftBankNVIDIA株式取得

SoftBank Takes $4 Billion Stake in U.S. Chipmaker Nvidia, Sources Say - Bloomberg
SoftBankNVIDIAの株式を取得して4位の株主になったらしい。

NVIDIAの株については、AI関連企業の中でもNVIDIAの株価上昇率が特に高いことを指摘した以下のツイートが印象に残った。

また、NIPS締め切り前にGPUインスタンスが枯渇する事態になっていたらしく、ブームの高まりをさらに感じた。
Cloud giants 'ran out' of fast GPUs for AI boffins • The Register

新しく知ったもの

clDNN

GitHub - 01org/clDNN: Compute Library for Deep Neural Networks (clDNN)


Marxico

Marxico - Markdown Editor for Evernote
オンラインでMarkdownを編集できるサービス。数式のプレビューなどもできる。

自分はHackMD - Collaborative markdown notesを愛用しているが、MarxicoのHackMDに対するメリットはよく分からない。

XPPAUT

XPP/XPPAUT Homepage
微分方程式などを解くソフト。iOS版もあるらしい

Valgrind

Valgrind - Wikipedia
有名なデバッガらしい。printfデバッグより高度なデバッグをしたことがないのでデバッガの使い方もおいおい身に着けていきたい。

気になった論文

The Marginal Value of Adaptive Gradient Methods in Machine Learning

[1705.08292] The Marginal Value of Adaptive Gradient Methods in Machine Learning


ファインチューニングのときはSGDの方がいいなどのオカルト情報は以前から聞いていたが、実際にSGDの方が優れていると主張しているのはちょっと気になる。

ICLR 2017でBEST PAPER AWARDを取ったUnderstanding deep learning requires rethinking generalizationでもSGD自体に正則化効果があることが指摘されていたし、SGDの理論研究がこれから盛り上がるかもしれない?

Engineering RGB color vision into Escherichia coli

Engineering RGB color vision into Escherichia coli: Nature Chemical Biology: Nature Research


読んだ本

楽しく学べる「知財」入門 (講談社現代新書)

楽しく学べる「知財」入門 (講談社現代新書)

特許や商標などの知的財産権についての入門書。
「Asahi」ロゴマーク事件 特許事務所 東京都その他全国対応 【60分無料相談をご利用ください!】のような事例を集めて紹介していて、とても面白かった。

kindleで90%以上ポイント還元してくれるキャンペーンをやっていたのでいろいろ買った。

2017年5月 第3週

新しく知ったこと

「ずんだホライずん」のクラウドファンディング

東北ずん子アニメ「ずんだホライずん」制作プロジェクト | クラウド出版
クラウドファンディングでアニメ制作の予算を集めているらしい。3万円出すと14000枚の原画と中割り絵がもらえるというコースがあって投資してしまった。


こういう訴え方に弱い。

Visual Studio Code

Visual Studio Code - Code Editing. Redefined
IDEを使ってみようと思って試してみた。Linuxでも動くし見た目もいい感じなので使っていきたい。

TPUの無料開放

Googleが研究者向けにTPUを無料で使わせてくれるらしい。


プログラミング用フォント Myrica

myrica.estable.jp
Rictyを使うのに飽きたので別のプログラミング用フォントを探して見つけたもの。しかし、Vimプロポーショナルフォントをうまく扱えないらしく(プロポーショナルフォントを使いたい · Issue #741 · vim-jp/issues · GitHub)、Source Code Proなども含めAdobe系のフォントの幅がおかしくなったのでまだRictyを使っている。

様方と気付

簡単ビジネス文書!気付と様方の使い方を覚えよう。知っておくと便利な宛名です。
郵便物を世帯先と違う苗字の人に送るときには宛名に「様方」という言葉を使い、ホテルなど本来その人がいない場所に送るときは「気付」を使うらしい。欲しいものリストで宛名にハンドルネームを使うときにどうするかという議論で知った。

読んだ本

Gaussian Processes for Machine Learning (Adaptive Computation and Machine Learning series)

Gaussian Processes for Machine Learning (Adaptive Computation and Machine Learning series)

ガウス過程の本。Gaussian Processes for Machine Learning: Book webpageで本文のPDFやコードが公開されている。
幅広いトピックを扱っていたが、各テーマの数学的バックグラウンドの紹介は最小限で、再生核ヒルベルト空間の話題とかは全然分からないままだったので別の本でも勉強したい。

表紙がかわいい。きんいろモザイクが面白い。応援していたゲストの「りかけいの女子」が無くなっていて悲しかった。

お願い! ロイヤルニート (1) (まんがタイムKRコミックス)

お願い! ロイヤルニート (1) (まんがタイムKRコミックス)

庶民の主人公と世間知らずのお嬢様というベタな組み合わせで順当に面白かった。

「女の子のかわいさをお楽しみ頂くため、邪魔にならない程度の差し障りのない受験勉強をお楽しみ頂く漫画です」という感じ。かわいい。

読んだWebページ

今週見つけたけどまだ読んでいないもの

2017年5月 第2週

読んでいるブログの今週のまとめという企画が面白そうなので自分もやってみることにしました。

学ぶって言うのはまねぶって言うじゃん? みんな最初は誰かの真似、おんなしおんなし。(井口 祐未)

例によって飽きたらやめます。
zkro.hateblo.jp

新しく知ったこと

perf

Linuxでソフトのパフォーマンスを解析するツールにperfというものがあることを知った。プログラムを高速化するためにはどの処理に時間が掛かっているのか調べるのが重要なのでこういうツールは役に立ちそう。perfの使いかたが参考になりそう。

EDINET

有価証券報告書等の開示書類を閲覧するサイトにEDINETというのがあるらしい。

Qbsolv

D-Waveの最適化ソルバーがあるらしい。使い方は知らない。https://github.com/dwavesystems/qbsolv

Cuckoo search

カッコウの托卵に着想を得た最適化アルゴリズムがあるらしい。詳細は理解していないのでそのうち理解したい。Cuckoo search - Wikipedia

gtags

コードリーディングに役に立ちそうなツール。ctagsよりいろいろすごいらしい。人間とウェブの未来 - GNU GLOBALとvimで巨大なコードでも快適にコードリーディングが参考になった。rtagsというclangの構文解析インターフェースをつかってタグ付けするツールもあるらしいがうまく動かせなかった。

DSD

MicrosoftがDNAでプログラミングするための言語を開発しているらしい。実用性は不明。Programming DNA Circuits - Microsoft Research

順位相関係数

順位データに対する相関係数を出す方法として順位相関係数というものが使われる。スピアマンの順位相関係数ケンドールの順位相関係数の2つがある。

DJI

ドローンのシェア70%を占める会社。DJI (会社) - Wikipedia

中央アフリカ帝国

1976年-1979年に存在した帝国。日本・フランスから国号変更を承認されるなどなかなかいいところまでいったらしい。中央アフリカ帝国 - Wikipedia
アメリカ大統領が最敬礼で迎えるのはイギリス国王・ローマ法王・日本国天皇のみらしいという知識も得た。

読んだもの

Ubuntu 16.04でADS-1500Wを使う

増え続ける紙資料を電子化して保管するためにスキャナーを買いました。

購入時には大きさと価格を考慮して以下の3つを検討しましたが、無線LAN機能がついていることとLinux用ドライバーが公式で配布されていることを理由にADS-1500Wを買いました。

ドライバーは配布されているものの、どこまでの機能がLinuxで動くか事前調査で分からなくて不安だったので動作報告をしておきます。確認した環境はUbuntu 16.04です。

動かし方

1. ADS-1500Wを無線LANに接続します。WindowsMacがあるとPC側のネットワーク設定を転送できて便利ですが、本体にSSIDを検索してネットワークキーを直接入力する機能や、WPS/AOSSが用意されているので無くてもつなぐことができます。

2. ソフトウェアダウンロードからドライバーをダウンロードします。ダウンロードするとインストール方法を書いたページ(リンクを開くと自動でダウンロードが始まるので注意!)に飛ばされますが、ここの指示は古いようです。dpkgでダウンロードしてdebをインストールします。

3. Scanner Setting for normal userからbrother-udev-rule-type1-1.0.0-1.all.debをダウンロードしてインストールします。ここまでの手順を実行すればUSB接続でのスキャンはできるはずです。

4. 最後に、無線LAN経由でスキャンできるように設定します。シェルを開いて

$ brsaneconfig4 -a name=ADS-1500W-Wireless model=ADS-1500W ip=192.168.1.20

のように実行するとスキャナーが登録されます。
nameには好きな名前を設定してください。IPアドレスは本体側で「メニュー > ネットワーク > 無線LAN > TCP/IP」とすれば確認できます

5. Ubuntuで「シンプルスキャン」を実行し、設定の「スキャンする対象」がいま登録したスキャナーの名前になっていることを確認してから「スキャン」とすればスキャンできます。両面スキャンを行うにはスキャンボタン右側の▼をクリックして「フィーダより全てのページ」を選択します。

以上のような手順でUbuntu上で無線LAN経由でのスキャンが行えることが確認できました。

ADS-1500Wには他にもスマートフォンアプリからスキャンして結果を確認する機能や、PCを経由せずにDropBoxに直接アップロードする機能などがあり便利に使えそうです。

画像処理で大腸菌のコロニー数を数えたかった話 その2

kivantium.hateblo.jp
の続編です。

前回は先行研究を一切調べずに適当にやったので今回は少し先行研究調査をして前回よりはまともな方法を実装したいと思います。

先行研究

Google検索したところ

ということが分かりました。

追記: ImageJを使うにはこの解説が分かりやすそう
satoshithermophilus.hatenablog.com


見た論文の中で一番簡単そうだったCell counting based on local intensity maxima grouping for in-situ microscopy - IEEE Conference Publicationを実装することにしました。

論文の内容と妥協ポイント

この論文では

  • Cell cluster Region Segmentation
  • Local Intensity Maxima Detection
  • Local Intensity Maxima Grouping
  • Cell Counting

の4段階で細胞数をカウントしていました。

Cell cluster Region SegmentationではMartinezの方法で細胞領域のセグメンテーションを行うと書いてあったのですが、Martinezの論文が入手できませんでした。そこでそれっぽいセグメンテーションができる閾値を手動で設定することにしました(妥協ポイント1)

Local Intensity Maxima Detectionではbilateral filterを掛けた後、各ピクセルについてそのピクセルを中心とする3x3の領域で最も明るい場合にlocal intensity maximumと判定するという処理をしていました。実験の結果3x3では小さすぎるようだったのでwindow sizeも手動で設定することにしました(妥協ポイント2)

Local Intensity Maxima Groupingではlocal intensity maximumを5つの基準に従ってグルーピングしていました。しかし、論文の基準は「2つのmaximumを結ぶ直線が細胞の境界と交差しない」のような実装が面倒なものが多かったので、2つのmaximumが同じwindowに入るならグループにするという単純な基準を採用しました(妥協ポイント3)

Cell Countingはグループの数を数える処理です。

実装

以上の妥協を行った実装が以下のようになります。(何も見直ししてないからコードが汚い)

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>

#include <iostream>
#include <vector>
#include <map>
#include <cmath>
#include <algorithm>

cv::Mat org, src, bin, blured, dst;
int wsize = 5;
int threshold = 200;

using P = std::pair<int, int>;

struct UnionFind {
    std::vector<int> par;
    UnionFind(int n) : par(n, -1) {}
    int find(int x) { return par[x] < 0 ? x : par[x] = find(par[x]); }
    bool same(int x, int y) { return find(x) == find(y); }
    void unite(int x, int y) {
        x = find(x); y = find(y);
        if (x == y) return;
        if (par[y] < par[x]) std::swap(x, y);
        if (par[x] == par[y]) --par[x];
        par[y] = x;
    }
};

void drawWindow(void) {
    cv::Mat img = org.clone();
    cv::bilateralFilter(src, blured, 7, 5, 35);
    cv::threshold(blured, bin, threshold, 255, cv::THRESH_BINARY);
    std::vector<P> cell;
    for(int y=wsize; y<blured.cols-wsize; ++y) {
        for(int x=wsize; x<blured.rows-wsize; ++x) {
            int c = blured.data[y*blured.step+x]; 
            bool is_max = true;
            for(int dy=-wsize; dy<=wsize; ++dy) {
                for(int dx=-wsize; dx<=wsize; ++dx) {
                   if(blured.data[(y+dy)*blured.step+(x+dx)] > c) is_max = false;
                }
            }
            if(is_max && bin.data[y*bin.step+x] == 255) {
                int p = y*img.step+x*img.elemSize();
                img.data[p+0] = 0;
                img.data[p+1] = 0;
                img.data[p+2] = 255;
                cell.push_back(P(y, x));
            }
        }
    }

    UnionFind uf(cell.size());
    for(size_t i=0; i<cell.size(); ++i) {
        for(size_t j=0; j<cell.size(); ++j) {
            if(abs(cell[i].first - cell[j].first) < wsize && abs(cell[i].second - cell[j].second) < wsize) {
                uf.unite(i, j);
            }
        }
    }

    int pop = 0;
    for(size_t i=0; i<cell.size(); ++i) {
        if(uf.find(i) == i) pop++;
    }
    std::cout << "population is: " << pop << std::endl;

    cv::imshow("Source", img);
    cv::imshow("Binary", bin);

}

// トラックバーに変化があった時に呼ばれる関数
void on_trackbar( int, void* ) {
    drawWindow();
}

int main(int argc, const char** argv) {
    org = cv::imread(argv[1]);
    src = cv::imread(argv[1], cv::IMREAD_GRAYSCALE);
    dst = cv::Mat(src.size(), CV_8UC3);

    // 画像の読み込みに失敗したらエラー終了する
    if(src.empty()) {
        std::cerr << "Failed to open image file." << std::endl;
        return -1; 
    }

    // トラックバー付きウィンドウの作成
    cv::namedWindow("Binary");
    cv::createTrackbar("threshold", "Binary", &threshold, 255, on_trackbar);
    cv::createTrackbar("window size", "Binary", &wsize, 15, on_trackbar);
    drawWindow();

    while(true) {
        int key = cv::waitKey(0);
        if (key == 'q') {
            return 0;
        }
        if(key == 's') {
            cv::imwrite("result.png", dst);
        }
    }
}

実行結果

入力画像
f:id:kivantium:20170508230735p:plain

手動で閾値を設定してセグメンテーションした結果
f:id:kivantium:20170508230637p:plain

local intensity maximumとなるピクセルを赤く表示した結果
f:id:kivantium:20170508230819p:plain

出力は

population is: 21

でした。

もう少し難しい入力画像と処理結果
f:id:kivantium:20170508230907p:plain
f:id:kivantium:20170508231003p:plain
f:id:kivantium:20170508231012p:plain

population is: 55

これより大きい画像について実行しようとすると、画像の場所ごとに明るさが違うようで単純な閾値設定による二値化ではうまくセグメンテーションができませんでした。AdaptiveThresholdも試しましたが、OpenCVの関数ではうまくできませんでした。次回は妥協ポイントその1をなんとかする必要がありそうです。

RNNによるツイートの自動生成

授業で「Deep Learningを使って何か作る」という課題を与えられました。チーム開発なのですが、知らないうちにテーマがツイートの自動生成に決まっていたので実装をやりました。発表内容は以下のスライドを見てください。

以下、実装の詳細を説明します。
使ったコードはkivantium/rnn-twitter · GitHubに置いてあります。
github.com

char-rnn (Keras)

char-rnnはKarpathyがThe Unreasonable Effectiveness of Recurrent Neural Networksで紹介したことで有名になり、各種フレームワークに移植されているLSTMの有名なモデルです。モデルの説明はKarpathyの記事を読んでください。
Kerasを使いたかったのでkeras/lstm_text_generation.py at master · fchollet/keras · GitHubを元に実装しました。

かな漢字混じりの文章をそのまま学習させたところ意味のある文章が生成されなかったので、入力文字列を全てカタカナにする前処理を行いました。

漢字の読みを取り出す (Mecab, Python)

MeCabの辞書としてmecab-ipadic-neologdを使いました。(過去記事

Pythonバインディングsudo apt-get install python-mecabで入ります。

MeCab形態素解析を行うと読み情報が得られるので以下のようなコードで取り出します。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import MeCab
 
mt = MeCab.Tagger("-Ochasen -d /usr/lib/mecab/dic/mecab-ipadic-neologd")
mt.parse('')
text = 'あらゆる現実をすべて自分のほうへねじ曲げたのだ。'
node = mt.parseToNode(text)
node = node.next
data = ''
while node:
    if node.next:
        data += node.feature.split(',')[-2]
    node = node.next
print data

結果は

アラユルゲンジツヲスベテジブンノホウヘネジマゲタノダ。

となります。

辞書に読みが入っていないと*になるので気になる人は手動で取り除いてください。
Pythonエンコーディングは厳しいのでうまくいかなかったら頑張ります。

Yahooのかな漢字変換APIを使う (Python)

かな漢字変換を自分で実装するのはつらいのでYahooのAPIを使いました。
テキスト解析:かな漢字変換 - Yahoo!デベロッパーネットワーク

利用するにはアプリケーションIDが必要なのでご利用ガイド - Yahoo!デベロッパーネットワークに従って取得します。

カタカナからひらがなの変換はjaconvを使いました。GitHub - ikegami-yukino/jaconv: Pure-Python Japanese character interconverter for Hiragana, Katakana, Hankaku and Zenkaku
また、XMLの解析にはBeautifulSoupを使いました。Beautiful Soup Documentation — Beautiful Soup 4.4.0 documentation
どちらもpipで入ります。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import jaconv
import requests
from bs4 import BeautifulSoup

text = u'アラユルゲンジツヲスベテジブンノホウヘネジマゲタノダ。'

hira = jaconv.kata2hira(text)
yahoo_url = "http://jlp.yahooapis.jp/JIMService/V1/conversion"

appid = 'PUT YOUR ID HERE'

parameter = {'appid': appid,
            'sentence': hira,
            'results': 1}
r = requests.get(yahoo_url, params=parameter)
soup = BeautifulSoup(r.text)
sentence = ''
for word in soup.find_all('candidatelist'):
    sentence += word.find('candidate').text
print(sentence)

出力は

あらゆる現実をすべて自分の方へねじ曲げたのだ。

となります。
ここまでの機能で適当な文章が作れます。
データセットとしてはYJ Captions 26k Datasetの説明文を抜き出して使いました。

文章を作るだけではbotとしての面白みに欠けるので画像を生成しようと思いました。
運の良いことにMS COCOの説明文からGANで画像を生成する研究があり、コードと学習済みデータが公開されているのでそれを使おうと思いました。
GitHub - reedscot/icml2016: Generative Adversarial Text-to-Image Synthesis

しかし、この研究は英語から画像を生成しているので生成した日本語から英語にする必要があります。

Microsoftの翻訳APIを使う (Python?)

Google翻訳APIは有料だったのでMicrosoftAPIを使います。
使い方についてはたくさんの解説記事がありますが、最近仕様が変わったらしくほとんどの記事は今では使えない方法でした。
見つかった中で唯一動いた自動要約&ニューラルネット翻訳で海外の記事を読みやすくするSlackBot - Qiitaに従いました。

Cognitive Services - Text Translationに従ってkeyを取得します。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import subprocess
from bs4 import BeautifulSoup

def popen(cmd):
    outputs = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = outputs.communicate()
    return stdout

text = 'あらゆる現実をすべて自分の方へねじ曲げたのだ。'

token_url = "https://api.cognitive.microsoft.com/sts/v1.0/issueToken"
translate_url = "https://api.microsofttranslator.com/v2/http.svc/Translate"

KEY = 'YOUR KEY HERE'

CATEGORY = "generalnn"
request_token = popen('curl -X POST \"{url}\" -H \"Content-type: application/json\" -H \"Content-length: 0\" -H \"Accept: application/jwt\" -H \"Ocp-Apim-Subscription-Key:{key}\"'.format(url=token_url, key=KEY))
result = popen(
    "curl -X GET --header \'Accept: application/xml\' \'{url}?appid=Bearer%20{token}&text={text}&from=ja&to=en&category={category}\'".format(
        url=translate_url, token=request_token, text=text, category=CATEGORY))
soup = BeautifulSoup(result)
print(soup.string)

出力は

All the realities were screwed towards myself.

となります。

さすがにこの方法は汚い気がしますがDone is better than perfectと唱えて次に進みます。

GANによる画像の生成 (Torch, AWS)

GitHub - reedscot/icml2016: Generative Adversarial Text-to-Image SynthesisAWSで動かしました。

  • READMEのリンクからCOCO caption data in Torch formatCOCO GAN-CLSをダウンロード
  • CONFIGのファイルの位置を書き換える
  • scripts/coco_queries.txtに画像を生成したい英文を入れる
  • ./scripts/demo_coco.shを実行して画像を生成する

うまくいくと
f:id:kivantium:20170121141048p:plain
みたいな画像が出来ます。

こうして得た日本語文と、対応する画像をれんと (@licarent) | Twitterに流しています。

うまくいった例を貼り付けておきます。



RNNが生成する日本語文はいまいちで、GANが生成する画像はさらにいまいちなのですが、今の僕の技術レベルだとこれくらいが限界でした。
もっと面白いbotを作りたいものです。

AWSのGPUで機械学習した話(Torch編)

TL; DR

AWSは初期状態でGPUインスタンスを立てられない設定になっていることがあるから気をつけましょう


学校で「ディープラーニングを使って何かを作れ」という課題が出たのでGenerative Adversarial Text-to-Image Synthesisを動かそうと思ったのですが、どうやらこれはGPUがないと動かないコードのようで手元で動きませんでした。
締め切りも近く自分で学習させている暇はないのでAWSを借りることにしました。

AWSAmazonが運営しているサーバーサービスで、Amazonの全営業利益の半分以上を稼いでいるそうです。

Deep Learning AMIを使う

時間課金されるAWSで環境構築してる暇はないので、既に環境構築されている環境がないかなと思って調べたらBitfusion Boost Ubuntu 14 Torch 7という環境構築済みのイメージがあったので使うことにしました。値段は$0.066/hrなので環境構築にハマる時間を考えたら十分元が取れそうです。

GPUが使えるインスタンスはP2とG2があり、一番安いg2.2xlargeを使うことにしました。値段は変動するそうなのですが、使ったときは$0.65/hrだったので1日くらいならあまり負担になりません。

まずは、クラウドでの Linux 仮想マシンの起動方法 – AWSチュートリアルに沿って無料枠のサーバーでSSHの仕方などを学びました。

次に、Documentation: Machine Images - Bitfusion.ioに従ってDeep Learning用のインスタンスをセットアップしましたが、ここで問題が起きました。
ドキュメントの画像によると
http://www.bitfusion.io/wp-content/uploads/2016/11/2-8-768x497.png
でLaunch with 1-clickを押せばインスタンスが起動するはずなのに何分待っても起動が確認できませんでした。
起動していなければいいのですが、起動の確認方法を知らないだけで料金が発生しているかもしれないと思うと怖くなり一旦アカウントを削除しました。

翌日、AWS GPUインスタンスを利用して高速な機械学習環境を手に入れよう | Tech-Sketchに従って動かしてみたところ

You have requested more instances (1) than your current instance limit of 0 allows for the specified instance type. Please visit http://aws.amazon.com/contact-us/ec2-request to request an adjustment to this limit.

というエラーが発生しました。どうやら新しいアカウントではGPUインスタンスの数に制限があるようです(DashboardのLimitsから確認できます)

LimitsページのRequest limit increaseから「g2.2xlargeの制限を増やしてくれ〜」と申請したところ1日半くらいでメールが届いて使えるようになりました。

この状態でBitfusionのAMIでg2.2xlargeを立てたところTorchの環境は完璧に整備されている上にgitなども揃っていて、必要なデータを転送するだけで目的のコードを動かすことが出来ました。Bitfusionは他にもTensorFlowやChainerなどの環境構築済みのAMIを売っているようなので必要があったら使ってみようと思います。
AWS Marketplace: Bitfusion.io

以上をまとめると、

  • Launch with 1-clickボタンはエラーが出なくて怖い
  • 環境構築済みAMIは便利、金で時間を買おう

ということになります。

何を作ったかは明日の発表会が終わったら記事にします。
twitter.com