レイバンスパムに引っ掛かったのでサングラスを11個買った

ある日、いつものようにレガシーなクソコードを無限にキレイにしたり、

無限に式テンプレートしてクソコードを無限に高速化したり、もうなんかわからないものをいろいろとジェネリックにする業務を終え、疲弊しながら帰路についた時のことでした。

電車の中でTwitterを眺めていると、有益情報と

クソリプが飛んできました。

急いでFacebookiPhoneアプリから確認しに行きましたが、自分のActivitiesからはよくわかりませんでした。

するとこんなリプライが。

オタクからもこんなSlackが飛んできました。
f:id:tochikuji:20161019000313p:plain

どうやら「レイバンのサングラスが3499円で買えるイベントに参加するのでお前らも参加しろ」といった旨の招待を友達全員に送っていたようです。

今見返すと「昔はTwitterで2499円で売ってたのに、円安の影響かな?」とか思うのですが、その時点ではこの件に関してTwitterでアホみたいに叩かれていた関係もあり、そんな余裕はありませんでした。

(以下、比較的真面目な情報になるので、タイトルだけ回収したい人は下のほうにスクロールしてください)

やったこと

先ずFacebook上でバレずに済む恥は隠滅しようと、当該シェアを取り消そうと思ったのですが、iOSFacebookアプリがクソみたいに使いにくいとかそういうのは別にして、
普段Facebookは特定の友人が自分の写真をアップロードするだけのコンテンツなので全く使い方が分からず、断念しました。
そしてこのへんで事態の収束を図るため、頑張って捕まえた特急を下車し、駅のベンチで慣れないスマートフォンとの格闘を開始しました。

次点に、さらなる被害を防ぐためにFacebook上の怪しいログインセッション、アプリを抹消する作業に移りました。
このへん、iOSFacebook Appがクソでよくわからなかったので共有します。

Facebookアカウントの清浄化

先ず自分のプロフィールから"・・・"アイコンを押して、プライバシーショートカットの設定項目に飛びます。
f:id:tochikuji:20161019002832p:plain

その他の設定からセキュリティ設定に飛び、ログインの場所を開き、怪しい進行中のセッションを抹消しました。
f:id:tochikuji:20161019002947p:plain
瞬殺したのでログはないのですが、発信元IPが大阪のセッションがあったような気がします。

さらに前画面の"設定"から、"アプリ"に飛び"プラットフォーム"から、プラットフォームをOff(他アプリとの連携を許可しない)にして、全ての連携アプリを抹殺しました。
f:id:tochikuji:20161019003529p:plain

さらにレイバンスパム系はどっかのクソザコナメクジサイトから流出したログイン情報を元にパスワードクラックをしている、という話を前々から聞いていたので(この件については後ほど補足します)
"設定"→"一般"→"パスワード"とし、パスワードを秒で変更しました。

加えて、自分の場合ごく少数だったのですが、パスワードが漏れていたらパスワードを共有・類似のパターンのパスワードを使用している他のサービスのアカウントまで引っこ抜かれる可能性があるので、当該サービスのパスワードも秒で変更しました。特にその中に一つ、よく考えるとクレジットカード情報を登録している某サービスがあったのでそちらは神のような速度でアカウントを浄化しました。

Analysis

その後Twitter, Facebook上で火消しを行ってfavとLikeを稼いだあと、鈍行に乗って自宅に戻り、事態の分析に努めました。

Facebook連携

真っ先に疑うのはFacebookの連携アプリです。上述の操作で全て抹消してしまったので、個別の分析は出来ませんが、最初テンパりながらみた時は全く管理していなかったためか、30程はあった気がします。

この辺からも投稿とかShareなどは出来てしまうので皆さんは定期的に連携アプリを確認しましょう。
しかし、ここで先に言ってしまうと、今回の件は十中八九連携アプリによるものではなかった、と考えています。

Activity Logの確認と今回の原因

そのあと、FacebookのWebUIから自分のアカウントのActivity logを確認しました。
この時点ですでに件のイベントはスパムとして削除されており、Activityには招待を送った旨はリストされていなかったのですが、興味深いことを発見しました。
f:id:tochikuji:20161019010138p:plain

下のActivitiesを見ると21:22、スパムShareをするのは21:24ですので、その2分前に複数のアカウントと友達になっていました。
これは「わからんけど多分スパム」ということで放置していたFriend requestsなのですがこれを勝手に承認していたようです。(当然、秒でブロックしました)

こういう手の込んだことをするのか、という感想と共に今回の件の原因もわかってきました。

レイバンスパムの手口について

(ちょっと調べた程度なので間違ったところがあったらウェッブのプロの方ご指摘をお願いします)

Facebookの連携アプリはGraph APIというHTTP(s)ベースのAPIで動作するらしいのですが、このリファレンスを見るとPostやShareをするインターフェースはあっても、Friend requestを承認するたぐいのものは見当たりませんでした。
developers.facebook.com

もっと言えば、ごく狭い範囲の情報の取得以外の操作はFacebookによってアプリの審査を通さないと使えないらしく、既存のサービスがまるごと乗っ取られたのでなければ、スパムアプリにそんな権限が付与されるとは考え難いです。

これらを鑑みて、今回のスパム投稿はFacebookのログイン情報が漏れ、通常のPassword authenticationを通して行われたものであると結論します。

おわび、今後の対策

おそらくパスワードクラックの被害に遭ったと思われる今回の一件について、その原因は「Facebookとか、ろくすっぽ使わんしどうでもええやろ」と7年位変更していない、現行のパスワードの中で最弱の英数字のみで10文字以下のクソザコナメクジパスワードのままずっとFacebookを放置していた私の管理不行き届きにあります。
個人的にはFacebookで殺害予告とかされない限りどうでもいいと思っていたのですが、現行のFacebookのAuth flowにおいてはPassword authenticationは(二段階認証のオプションを除いて)最高権限であり、フレンドの皆さまの情報に直接アクセスできる媒体でした。
事の重大さを捉え、以後このようなことがないよう、アカウントの管理には徹底した注意を払ってゆきます。
スパムShareを飛ばしてしまったフレンドの皆さまに(本当に)深くお詫びします。









それでは本題に入ります。
レイバンサングラススパムに引っ掛かったので、サングラスを11個買いました。
本当はもっとたくさん買ってTwitterにアップしたかったのですが、これしかなかったので、とりあえずあるだけ買い占めてきました。
f:id:tochikuji:20161019214751j:plain

先に述べたようにこの度は各方面に多大なご迷惑をお掛けしました。
その中には私のシェアをみてサングラスに対する購買意欲を刺激されてしまった方も多分にいらっしゃることでしょう。
ひいてはこの度私が陳謝の意を込めて、そういった方に無料にてサングラスを進呈いたします。

この度被害に遭われた方、あるいは関係ないけどこの記事を読んだ方は、ご連絡をいただければ今度私とお会いした時にサングラスを差し上げます。(今限り、11個限定)
Facebook, Twitter, 電凸等媒体は問いません。
上記の写真よりご所望のモデルを指定の上、ご連絡ください。

また、更なるお詫びの印として5年くらい変えてなかったFacebookのプロフィール写真を変更しました。
フレンドの方はご査収ください。

以上になります。長文失礼しました。

chainerでStacked denoising Autoencoder

イマドキのナウいようじょなのでもっぱらNeural networkで遊んでます.

Autoencoder(自己符号化器)の話をします.
Autoencoder、というよりNeural Net一般の問題でありますが、ネットワークの構造を深くしてゆくと逆伝搬の途中でその勾配が弱まっていってしまって, NNの前段と後段で逆伝搬される勾配が異なってくる勾配消失(Gradient vanishing)という現象が大きな問題となってきます. このへんは青い本に書いてあった気がするのですが高くて買ってないですし、あんまり詳しくないので詳しくは述べません.

 そのため深いAutoencoderを構成する際には段ごとにその前段からの入力を元に戻すように学習させ、そうして一層ずつ学習させたネットワークを積み上げる(stack)という技法が用いられ、そうして構成されたAutoencoderをStacked Autoencoderといいます.イメージとしては(面倒なので図は用意しません)
1. 入力 x -> [AE 1層目] -> [AE 1層目をひっくり返したもの] -> x となるように学習
2. 入力 x -> [AE 1層目(固定)] -> [AE 2層目] -> [AE 2層目.T] -> x
3. 入力 x -> [AE 1層目(固定)] -> [AE 2層目(固定)] -> [AE 3層目] -> [AE 3層目.T] -> x
4~n. 以下同様 といった感じです.

そんな感じの学習を行うプログラムを書いてみました.もちろんchainerで.

Stacked denoising(deep) Autoencoder 安直に小さいネットワーク作ってやってますが、もっと賢い書き方あるかもしれませんね.
まあきちんと書いてないのもありますが、わかりにくいですし長いです.もっと楽にかけたらいいんですけどね……

f:id:tochikuji:20150916210438p:plain

ん…?

f:id:tochikuji:20150916210916p:plain

あっ!!

ということでStacked Autoencoderを拙作libDNNに実装しました. (過去記事参照) 

tochikuji.hatenablog.jp

以下MNISTを3層のAutoencoderで学習させるサンプルです.

Stacked denoising(deep) Autoencoder (with libDNN)

通常のAutoEncoderと同様に大きなモデルも一気に定義してしまって,その積み上げ順と多少のお作法に則ったencoding, decodingの伝搬規則を書けば後はtrain一発で通るようにしてあります. めっちゃ便利ですね.
手がまわなくて未だドキュメントとExampleのコメントを書いてないので身体で感じてください.(あるいは誰か書いてください)
ドキュメントきちんと書きました。pushしてなかっただけです。

chainerで(より)簡単にディープラーニングできる魔法を作りました

2016/6/1追記

なんか公開してから半年以上経って、chainerも進化したし、なんでもDNNブームもあるていど去ったのに、
まだこの記事のアクセスが絶えないし、githubにお星様がついたりするので追記しておきます。


内容をご覧になる前に、この記事ではchainerのFunctionSetをラップして、
単純なミニバッチ学習・テストのインターフェースを提供するためのライブラリについて紹介しています。

しかしchainer1.5.0以降では新たなネットワーク定義の仕方として
Link, Chainが導入されその柔軟性が増したと同時に、
FunctionSetはdeprecatedになりました。

ちょちょっと学習・テストを行うフレームワークとしてはまだ良いでしょうが,
少しでも余力のある皆様は、後学のためにもこのライブラリは使わず, 
Link, Chainを使ってきっちりナウいchainerを使うことを強くおすすめします。

-- 本文ここから --

みなさんDeep learningしてますか?
僕はここ1ヶ月以上ずっと朝から晩までDeep learningして、二度と来ないこの5歳の夏を未だ見ぬ汎化性能に捧げています.

 今日日、PythonをはじめとしたLL上のDeep learning framework(Caffeとかtorch7とか)がよりどりみどりでDeep learningを実装して試す、ということはそこまで苦ではなくなってきています.
Torchは知らないのでCaffeに限っての話ではありますが、恐らく現状もっともポピュラーなDeep learning frameworkであるCaffeは長いこと使われてきて情報が多くある一方で, その設計思想からして柔軟性に欠ける,というのが大きな問題であります.

 Caffeではネットワーク構造を予め定義して固めて,データセットを作成して固めて,そしてガリガリ学習を行わせる(Define-by-Run)というのが通常のアプローチになります.
 しかしこれは,とりあえずこんなネットワークでできるかやってみよう,とか単にアプリケーションに適用しよう,のような場合には明快でよいのですが, ネットワークの腹を開けてその詳細なところを覗いたりいじってみたりとか,ちょっと決められた通常のアプローチとは違うことをしようとした時にネックとなります. それゆえ,そうしたことをすることが求められる層の人々はCaffeではなく数値計算ライブラリのTheanoでゴリゴリディープネットを作ってみたり(Effort-and-Run?), Caffeを魔改造していろいろやってみたりするわけです.

 そんな中,日本の(!)Prefferred networksというところからchainer(http://chainer.org/)という python向けニューラルネットワークフレームワークが公開され,ここ1,2ヶ月あちこちで大流行りとなっています. 詳しくはchainerのドキュメントを参照してもらうこととして,chainerではCaffeの問題であったDefine-by-Runから来る柔軟性の低さを解消すべく, ネットワークの構造であったりforwardingの処理であったりを固めずに,計算処理の中で柔軟(on-the-fly)に変更できる, Define-and-Runの設計思想をとっています.
 早い話がこのおかげで実験の中でいろいろ好き勝手できて,大変都合がよいわけです.
 様々な長さの孫の手が用意されていて痒いところに手が届く,という点で言えば,まだまだピチピチのchainerは歴史の長いCaffeには幾分か劣るのですが, chainerは新進気鋭,最近ではnumpy-likeなCUDAのラッパであるCuPyを自ら作り,バックエンドを整備したりとこれから伸びてゆくであろう, 少なくとも2.0.0ごろには形成が逆転しているのではないかなと女児なりに考えています.

 しかし,chainerは(Caffeに比べれば)まだまだ情報も少ないですし,柔軟であるがゆえにCaffeのようにデータと定義されたネットワークさえあれば,という手軽さも少々劣ります. いろいろいじるにしてもデータを学習させてテストする,といった決め打ちのそれは(Pythonでロジックを記述するような作業抜きに)簡単に書いてしまいたい, そうでもなければすでに身につけたCaffeなりの便利な乗り物を捨てようとは思わない,というのが「彼ら」の希望らしいです.(僕も少し思います)

 そこで,というか一日中GPUをブン回して地球温暖化に大いに貢献している中で必要に駆られて,numpyが「なんとなく」使えるレベルであればデータ丸投げである程度のことをやってくれるような魔法のようなライブラリを作りました. MIT Licenseの下で公開しています.

github.com

PyPiにも上げてあるので適当にpip install chainer-libdnnなりして簡単に入れることができます. 様々な背景もあり,ようじょの割に珍しく(拙い英語で)README, exampleもしっかり書いてあるのでまあいい気はするのですが, こんな感じで簡単にDeep learningっぽいことができます.

import numpy
import chainer
import chainer.functions as F
from libdnn import Classifier
import libdnn.visualizer as V
from sklearn.datasets import fetch_mldata

# ネットワーク作って(MLP)
model = chainer.FunctionSet(fh1=F.Linear(28 ** 2, 100), fh2=(100, 10))
# 伝搬規則書いて
def forward(self, x, train):
    h = F.tanh(self.model.fh1(x))

    return F.tanh(self.model.fh2(x))

# モデル作って
mlp = Classifier(model, gpu=0) # CUDAします
mlp.set_forward(forward)

# データ作って
mnist = fetch_mldata('MNIST original')
perm = numpy.random.permutation(len(mnist.data))
mnist.data = mnist.data.astype(numpy.float32)
train_data, test_data = mnist.data[perm][:60000], mnist.data[perm][60000:]
train_label, test_label = mnist.target[perm][:60000], mnist.data[perm][60000:]

# 60000(num. of train_data) iter. を1世代として100世代ミニバッチ学習
for epoch in range(100):
    err, acc = mlp.train(train_data, train_label)
    print("%d: err=%f\t acc=%f" % (epoch + 1, err, acc))

# テスト
err, acc = mlp.test(test_data, test_label)
print("on test: %f\t%f" % (err, acc))

# 可視化なんて器用なことも
imager = V.Visualizer(mlp)
plot_filters('fh1', shape=(28, 28))

# 学習済みネットワークも保存できます
mlp.save_param()

 自分で言うのもなんですがめっちゃ便利です.
 使うときに決める必要があるのは最低限model = ...のネットワークの構成の定義と def forward(...フィードフォワードのさせ方だけで,Caffeと変わりません.
 また,普通煩わしさを感じるほどそんな必要に駆られないのでしょうが,chainer使うときに個人的にちょっとめんどくさいなと思う,chainer.Variableへの変換と, GPUのオブジェクトとCPUのオブジェクトの相互変換. そのへんは完全にインターフェースから隠蔽してバンバンnumpy.arrayとしてデータを放り込んで,取ってこられるようにしています.  現時点では最低限の構成ですが,これから便利な機能を付けて付けて,どんどん太らせていきたいと思っていますので, 欲しい機能があったら文句つけるか,継ぎ接ぎしていってください.

 このライブラリを使えばここに実例があるように,女児でも簡単にDeep learningができるので,きっと学校の成績だったりお受験だったり,いろいろ役立つんじゃないでしょうか.

 以下,想定質問です.

  • なんでもうv2.0.0なんですか? : もともとはprivateなgitlab上で開発していて,まあいろいろあるんです
  • なんでREADME英語なんですか? : いろいろあるんです
  • なんでCNNだけ優遇されてるっぽいんですか? : いろいろあるんです

以上になります.