u++の備忘録

【論文メモ】Development and Validation of a Deep Learning Algorithm for Detection of Diabetic Retinopathy in Retinal Fundus Photographs

Development and Validation of a Deep Learning Algorithm for Detection of Diabetic Retinopathy in Retinal Fundus Photographs

どんなもの?

眼底写真を用いた糖尿病性網膜症の診断を、deep learningアルゴリズムで自動化。2種類のデータセットでの実験を通じて、高精度で検知できると分かった。

先行研究と比べてどこがすごい?

(データセットが違うので単純な比較はできないが)sensitibityとspecificityが高い。

技術や手法のキモはどこ?

deep convolutional neural network - 糖尿病性網膜症の診断に用いられた眼底写真128175枚を訓練データに - 写真は3~7人の医師や研修医が診断し、多数決でラベル付け - 出力は0~1の値(糖尿病性網膜症でありそうな度合い)

どうやって有効だと検証した?

Sensitivity and specificity are statistical measures of the performance of a binary classification test, also known in statistics as classification function: - Sensitivity (also called the true positive rate, the recall, or probability of detection[1] in some fields) measures the proportion of positives that are correctly identified as such (e.g. the percentage of sick people who are correctly identified as having the condition). - Specificity (also called the true negative rate) measures the proportion of negatives that are correctly identified as such (e.g. the percentage of healthy people who are correctly identified as not having the condition).

議論はある?

  • 同システムの利点
    1. consistency of interpretation
    2. high sensitivity and specificity
    3. instantaneous reporting of results
    4. sensitivity and specificityを目的に応じて調整できる
  • 今後の展望
    1. より豊富な訓練データ
    2. より多角的なシステム評価
  • システムの限界
    1. 医師の判断に基づきラベル付けしているため医師が見つけられないものは見つけられない
    2. neural newworkのブラックボックス
    3. "Hence, this algorithm is not a replacement for a comprehensive eye examination"

次に読むべき論文は?

NULL

Google Homeに「寝坊30分」って言ったら、職場に丁寧な遅刻連絡メールを打つ

皆さん、寝坊することありますか?

寝坊はしないのが一番ですが、してしまった時には迅速かつ冷静に適切なところに連絡するのが大切です。しかし寝坊して急いでいると文章を推敲している時間もなく、焦りから誤字脱字や連絡先のミスをして更に自身の評価を下げてしまうことも想定されます。

今回、Google Homeを使って手軽に職場のメーリスに遅刻連絡メールを打つ仕組みを実装してみました。

作ったもの

このようなメールを送ることができます。

f:id:upura:20180127223925p:plain

実装方法

Google HomeのIFTTTによる機能拡張で、簡単に設定できました。

設定項目

f:id:upura:20180127224224p:plain

上記の”this”と"that"で、それぞれアプリケーションを指定し、さらに対応する文言などを設定します。

例えば、Google Homeに「ツイート ◯◯◯◯◯◯」と話し掛けた際に、Twitterに「◯◯◯◯◯◯」と投稿してほしい場合は、前者を”this”、後者を”that”に設定します。穴埋め方式になっており、英語が読めれば簡単です。
qiita.com

"this"の設定

次のように、Google Homeに「寝坊 (遅れる時間:例「30分」など)」と言った場合に動作するよう設定しました。$マークは、任意の言葉を指します。ここでの$マークの位置で取得した語を、"that"で使い回すことができます。

f:id:upura:20180127224817p:plain

"that"の設定

メール側の設定をします。例としてToに部長、Ccに部署のメーリスのアドレスを登録します。

f:id:upura:20180127225045p:plain

そして件名と内容も書いておきます。”TextField”には、$マークで取得した内容が埋め込まれます。つまり「遅刻 30分」と言えば、件名は「出社が30分遅れます」になります。

f:id:upura:20180127225040p:plain

最後に「Create」ボタンを押せば設定完了です。

おわりに

この設定によって、布団に入っている状態からでも遅刻連絡を適切に打てるようになります。これで社会人としての心構えはバッチリですね(違う)。

Google HomeのIFTTT連携で、かなり多様な仕組みが実装できそうなので、いろいろやってみたいと思います。

セキュリティ関係で過去に読んだ3冊

コインチェックの件で、にわかにセキュリティ周りを復習する機運が高まってきたので、これまで読んだ本をまとめておく。

www.nikkei.com

『暗号技術入門 第3版 秘密の国のアリス』

www.hyuki.com

現代の暗号技術の基礎を、豊富な図と平易な文章で解説してくれる。暗号技術同士がそれぞれ独立して存在しているのではなく、どのように結び付いているかをザックリと理解できる。

話は逸れるが、著者の結城浩さんが書いた『数学文章作法』(基礎編推敲編)は、(書名に「数学」とあるが)理系文系問わずオススメ。抽象的な「良い文章」という概念を、具体的な作法にまで落とし込んで説明している。

(こういう本は解説の粒度とか網羅性とか難しいだろうなあ)

TCP/IPの絵本』

www.shoeisha.co.jp

我々が日常的に使うインターネットは「TCP/IP」というプロトコル(手続きのルールのようなもの)を基盤にして構築されている。「絵本」の名の通り、豊富な図でインターネットの裏側の仕組みを具体的に理解できる。

『おうちで学べるセキュリティのきほん』

www.shoeisha.co.jp

その名の通り、自分で(Windows OSの)パソコンを動かす実習が記載されている。具体的なコマンド・プロンプト操作を通じて、セキュリティ技術が実世界にどこに相当するのかを実感できる。実習以外の解説部分にも、過去の実世界のセキュリティ実例を含めて書かれており、上記2冊で(一般的な視点で)蓄えた知識の理解が深まると思う。

RBFカーネルのハイパーパラメータは何物か?

はじめに

今回の記事は、下記の質問に答えるものです。

f:id:upura:20180121220647p:plain

RBFカーネルとは?

RBFカーネル(Radial basis function kernel)は下記のように定義される関数のことです。

 K(x, x')=\exp(-\gamma||x-x'||^2)
ただし ||x-x'||^2ユークリッド空間上の距離の2乗、 \gamma=\frac{1}{2\sigma^2}です。

RBFカーネルカーネル関数の一つで、機械学習の文脈では、サポートベクターマシン(SVM)など内積のみを扱う線形のアルゴリズム非線形化する際に登場します*1

RBFカーネルを用いたSVM

RBFカーネルのハイパーパラメータが何物かを知るには、実際にRBFカーネルを用いたSVMが(RBFカーネルの)ハイパーパラメータの違いでどのような挙動を示すかを見るのが分かりやすいかと思います。

そしてscikit-learnの公式ページに、ズバリそのものの項目があるので、該当部分を引用します。

RBF SVM parameters — scikit-learn 0.22 documentation

Intuitively, the gamma parameter defines how far the influence of a single training example reaches, with low values meaning ‘far’ and high values meaning ‘close’. The gamma parameters can be seen as the inverse of the radius of influence of samples selected by the model as support vectors.

日本語訳:
直感的には、ハイパーパラメータ \gammaは「一つの訓練データが与える影響の範囲」を意味します。小さいほど「遠く」、大きいほど「近く」まで影響します。ハイパーパラメータ \gammaはサポートベクトルモデルとして選ばれた訓練データの影響範囲の半径の逆数(インバース)としても見なすことができます。

つまり、ハイパーパラメータ \gammaが小さいほど個々の訓練データが「存在を主張」し、大きいほど「おとなしく」なります。そのためハイパーパラメータ \gammaが小さい場合には青・赤の訓練データがお互いに存在を大きく主張するので、互いの境界で識別曲線が引かれます。一方で大きい場合には青・赤の訓練データがお互いに自分の周りしか存在を主張しないため、歪な形の識別曲線が引かれるといった具合です。

f:id:upura:20180121230034p:plain

上の画像を生成したPythonコード

SVM(RBFカーネル)のハイパーパラメータを変えると何が起こるの? - Qiitaを参考に作成しました。

# -*- coding: utf-8 -*-
import numpy as np
from sklearn import svm, datasets
import matplotlib.pyplot as plt
from itertools import product

if __name__ == '__main__':
    iris = datasets.load_iris()
    #特徴量は最初の2つ, クラスラベルも最初の2つを使う
    X = iris.data[:100, :2]
    #特徴量にノイズを加える
    E = np.random.uniform(0, 1.0, size=np.shape(X))
    X += E
    y = iris.target[:100]
    #meshのステップサイズ
    h = 0.02
    #コストパラメータ
    Cs = [2 ** -5, 2 ** 15]
    #RBFカーネルのパラメータ
    gammas = [2 ** -9, 2 ** -6, 2** -3, 
              2 ** 3, 2 ** 6, 2 ** 9]

    svms = [svm.SVC(C=C, gamma=gamma).fit(X, y) for C, gamma in product(Cs, gammas)]
    titles = ["C: small, gamma: 2**-3", "C: small, gamma: 2**-2",
              "C: small, gamma: 2**-1", "C: small, gamma: 2**1",
              "C: small, gamma: 2**2", "C: small, gamma: 2**3",
              "C: large, gamma: 2**-3", "C: large, gamma: 2**-2",
              "C: large, gamma: 2**-1", "C: large, gamma: 2**1",
              "C: large, gamma: 2**2", "C: large, gamma: 2**3"]
    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))

    for i, clf in enumerate(svms):
        plt.subplot(4, 3, i + 1)
        plt.subplots_adjust(wspace=0.4, hspace=1)
        Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
        Z = Z.reshape(xx.shape)
        plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8)
        plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired)
        plt.xlabel("Sepal length", fontsize=8)
        plt.ylabel("Sepal width", fontsize=8)
        plt.xlim(xx.min(), xx.max())
        plt.ylim(yy.min(), yy.max())
        plt.xticks(())
        plt.yticks(())
        plt.title(titles[i], fontsize=8)
    plt.show()

おわりに

質問に立ち返ると、RBFカーネルのハイパーパラメータ \gammaは「個々の訓練データをどれだけ重要視するか」の設定と捉えられそうです。訓練データからRBFカーネルを用いて分布を推定するという文脈では「(RBFカーネル)関数の広がり(やすさ)を制御する」というような解釈になるかと思います。

【Python&遊戯王】文章類似度の計算手法”Doc2vec”は「コンマイ語」にも通用するのか

はじめに

要するにやること

本記事では

  • 遊戯王カードの効果テキストを基に
  • Doc2vecという文章単位の類似度を計算するアルゴリズムを使って
  • 類似したカードを探すコードを実装してみます

遊戯王カードの効果テキストは、あまりの複雑さや特殊な解釈のために「コンマイ語」と揶揄されることもあるのですが、今回の記事はそんなコンマイ語に対してもDoc2vecが通用するのかの検証の意味合いも持っています。

動機

下記の記事を発見し、次のような記載があったので、やってみることにしました。
qiita.com

余談ですが遊戯王のカードでもやってみたのですが、自分が遊戯王に詳しくないので似ているかどうかピンと来なかったのでやめました。
Githubにソースとモデル一式をUPしておくので、興味がある方がいましたらやってみてください。
https://github.com/GuiltyMorishita/card2vec

ソースコードの修正

↑のGithubからデータを取得し、Windowsならではの"UnicodeEncodeError"を回避するためにコードを修正しました。修正の過程などはGithubでご確認ください。

github.com

gensimのDoc2vecは以前に下記の記事で触れていたこともあり、自分のやりやすい書き方にザックリと変更している箇所もあります。

upura.hatenablog.com

実行

card2vec.py(先駆者のこの命名センス、素晴らしいと思います)を実行すると、下記のような形式のデータを保持します。"names"はカード名、"texts"は効果テキストをそれぞれテキスト型で持っています。

f:id:upura:20180121181249p:plain

類似カードの出力

学習が終了したら、いよいよ類似カードを出力してみます。

    # 類似カードを求めたいカード名
    TARGET_CARD_NAME = names[random.randint(0, len(names))]
    # 直接指定も可能
    # TARGET_CARD_NAME = "xxxxxxxxxxxxxx"
    card_index = names.index(TARGET_CARD_NAME)

    # 類似カードと類似度のタプル(類似度上位10件)のリストを受け取る
    similar_docs = model.docvecs.most_similar(card_index)
    print(names[card_index])
    print(texts[card_index])
    print("--------------------is similar to--------------------\n")
    for similar_doc in similar_docs:
        print(names[similar_doc[0]] + " " + str(similar_doc[1]))
        print(texts[similar_doc[0]], "\n")

例えば「ソーラー・エクスチェンジ」に関する類似カードは、以下のような結果になりました。きちんと、ライトロード関連のカードが出力されています。

ソーラー・エクスチェンジ
手札から「ライトロード」と名のついたモンスターカード1枚を捨てて発動する。自分のデッキからカードを2枚ドローし、その後デッキの上からカードを2枚墓地に送る。
--------------------is similar to--------------------

閃光のイリュージョン 0.7759238481521606
自分の墓地から「ライトロード」と名のついたモンスター1体を選択し、攻撃表示で特殊召喚する。自分のエンドフェイズ毎に、デッキの上からカードを2枚墓地に送る。このカードがフィールド上から離れた時、そのモンスターを破壊する。そのモンスターがフィールド上から離れた時このカードを破壊する。 

ライトロード・ドルイド オルクス 0.7378130555152893
このカードがフィールド上に表側表示で存在する限り、「ライトロード」と名のついたモンスターを魔法・罠・効果モンスターの効果の対象にする事はできない。このカードが自分フィールド上に表側表示で存在する限り、自分のエンドフェイズ毎に、自分のデッキの上からカードを2枚墓地に送る。 

ライトロード・スピリット シャイア 0.7361984252929688
このカードの攻撃力は、自分の墓地に存在する「ライトロード」と名のついたモンスターの種類×300ポイントアップする。このカードが自分フィールド上に表側表示で存在する限り、自分のエンドフェイズ毎に、自分のデッキの上からカードを2枚墓地へ送る。 

ライトロード・ドラゴン グラゴニス 0.7135570049285889
このカードの攻撃力と守備力は、自分の墓地に存在する「ライトロード」と名のついたモンスターカードの種類×300ポイントアップする。このカードが守備表示モンスターを攻撃した時、その守備力を攻撃力が超えていれば、その数値だけ相手ライフに戦闘ダメージを与える。このカードが自分フィールド上に表側表示で存在する場合、自分のエンドフェイズ毎に、デッキの上からカードを3枚墓地に送る。 

ライト・バニッシュ 0.7092658877372742
自分フィールド上に存在する「ライトロード」と名のついたモンスター1体をリリースして発動する。モンスターの召喚・反転召喚・特殊召喚を無効にし破壊する。 

ライトロード・エンジェル ケルビム 0.703083872795105
このカードが「ライトロード」と名のついたモンスターを生け贄にして生け贄召喚に成功した時、デッキの上からカードを4枚墓地に送る事で相手フィールド上のカードを2枚まで破壊する。 

光の援軍 0.6913601756095886
自分のデッキの上からカードを3枚墓地へ送って発動する。自分のデッキからレベル4以下の「ライトロード」と名のついたモンスター1体を手札に加える。 

マイン・ゴーレム 0.6905478835105896
このカードが戦闘によって墓地に送られた時、相手ライフに500ポイントダメージを与える。 

ライトロード・レイピア 0.6747479438781738
「ライトロード」と名のついたモンスターにのみ装備可能。装備モンスターの攻撃力は700ポイントアップする。このカードがデッキから墓地に送られた時、このカードを自分フィールド上に存在する「ライトロード」と名のついたモンスター1体に装備する事ができる。 

魔法再生 0.6690211296081543
手札の魔法カードを2枚墓地に送る。自分の墓地から魔法カードを1枚選択し、手札に加える。 

おわりに

無事にコンマイ語でもDoc2vecが機能していそうだと分かりました。定量的に精査するならば、遊戯王Wikiなどのラベルを用いてP@kなどを算出するのが良い気がします。うまい検証方法を思いついたら、発表資料の形式にまとめられるレベルまで深めてみたいと思っています。自然言語処理では「英語でうまくいった手法を日本語で使ってみたら~だった」みたいな論文を見かける気もするので、僕もJSAI辺りへの投稿を目指したいと思います(←舐めんな)。

【論文メモ】Aggregated knowledge from a small number of debates outperforms the wisdom of large crowds

論文名

Aggregated knowledge from a small number of debates outperforms the wisdom of large crowds
Joaquin Navajas et. al.
Nature Human Behaviour, 2018
https://www.nature.com/articles/s41562-017-0273-4

概要

Abstractの要約は上記ツイート。正しくは5,180人っぽい。話し合いによって、明らかな間違いが是正されていくということか。

お台場の水陸両用バス「TOKYO NO KABA(KABA3)」に乗ってきた

土日は基本予定がなく意識的に外出しないと引きこもりになるので、お台場の水陸両用バス「TOKYO NO KABA(KABA3)」に乗ってきました。

www.kaba-bus.com

予約

上記のホームページから予約します。大人3,500円です。完了するとメールが送られてきて、記載されたURLからチケット確認用のQRコードが取得できます。当日でも空いていれば予約可能らしいです(その場合の予約方法は電話?)。

搭乗

当日は発車時刻の15分前までに、アクアシティお台場の1階にある集合場所に行き、上記QRコードを提示して搭乗口に並びます。早めに手続を済ませ待っていたところ、発車時刻の15分前ごろに、ひと目でそれと分かる大型バスがやってきました。

f:id:upura:20180120193403j:plain

「どこから乗るのかな?」と思っていたら、男心くすぐる変形!

f:id:upura:20180120193538j:plain
f:id:upura:20180120193529j:plain

このような柄の座席で、可愛らしいです。定員38人ですが、昨年11月27日に運行開始したばかりで認知度がまだまだ低いのか、乗客は5組20人弱でした。

f:id:upura:20180120193636j:plain

若干気になる注意書きも……。

f:id:upura:20180120193919j:plain

運転席には当然のことながらハンドルと舵の両方がありました。

f:id:upura:20180120193943j:plain

運行

f:id:upura:20180120194221p:plain
公式サイト(http://www.kaba-bus.com/tokyo/)より引用。

運行時間は約45分。最初の15分は地上でお台場の観光地を巡ります。バスツアーのごとく、ガイドのお姉さんが名所を紹介してくれました。

地上のコースを終えた後は、いよいよ東京湾へ突入です。

f:id:upura:20180120194448j:plain

乗客全員で「3、2、1、カバ~」と掛け声を掛けながら、バスが東京湾へ進んでいきます。

※この瞬間の動画を撮ったのですが、ぜひご自身で体験していただきたいので掲載しないことにしました

f:id:upura:20180120194642j:plainf:id:upura:20180120194650j:plain

水中パートでは、窓を開けて解放感あるクルージングを体験できます。レインボーブリッジを下から望むこともでき、少々寒かったですが非常に良い時間を過ごしました。

おわりに

貴重な体験ができ、とても満足です。最初は大人1人3,500円は若干高い気もしましたが、お台場をガイドさん付きで観光できるオプションもありますし、悪くない額だと思います。また運転手さん(キャプテン)は、大型バスの運転免許と船舶の免許を両方持っている稀有な人材なので、人件費がかかるのではないかと。ひさしぶりに充実した休日を過ごした気がしました。