モーグルとカバとパウダーの日記

モーグルやカバ(EXカービング)山スキー(BC)などがメインの日記でした。今は仕事のコンピュータ系のネタが主になっています。以前はスパム対策関連が多かったのですが最近はディープラーニング関連が多めです。

長野ディープラーニング同好会 #7

ディープラーニング同好会7回め開催しました。

長野ディープラーニング同好会 #7 https://nseg.connpass.com/event/111342/

今回は結構人数が多く6人で、今回はじめて参加された方が3人いらしたので、Colabの使い方とか簡単なネットワークの書き方とかのおさらいをしました。
Colabがすごい便利で、TPUがめっちゃ速い!ということをみんなで体感できたのでよかったです。

なんやかやで結構もりあがりました。
やはりこのくらい人数いたほうがいいなあ、と思います。というかこのくらいだとちょうどいい感じ。

次回、続きみたいな感じになるなら、最初にColab使ってディープラーニング試しはじめる感じのノートを準備しておかないとな、と思いました。
今あるやつはちょっと古くて、TPU動かすようになっていなかったり、Sequentialだけで書いてあったりするので。

やっぱ、初顔合わせの方が居た時に簡単に自己紹介をするようにしたのはよかったと思います。
あと、最後クロージングで今回の感想とか次こんなのしたい、みたいなの言ってもらうようにしてみたんですが、これもよかったように思います。

botからのスパム送信の推移とSMTPセッションフィルタの終焉

これは「メール Advent Calendar 2018」のために書かれたエントリです。

元ネタは今年の6月に開かれたNSEGという長野の勉強会で発表した内容です。
勉強会の動画も上がってますので興味持たれた方はこちらもぜひ。

NSEG 勉強会 #101 / メールとコミュニケーションツール - connpass
スパム対策お焚き上げ

今北産業

  • botnetから送られるスパムが激減した
  • SMTPセッションフィルタでのスパム対策は不要になりつつある
  • 諸行無常

はじめに

自分は2006年頃から taRgrey というスパム対策手法を提案しています。

taRgrey - S25R + tarpitting + greylisting (tarpit + greylist policy server)

これはSMTPセッション中のクライアントの特徴を利用するフィルタをいくつか組み合わせた手法で、 S25Rtarpittinggreylisting を組み合わせて、誤検出や副作用をなるべく少なくすることを狙ったものです。

ただ、近年スパムの数も徐々に減ってきており、また徐々に効果が少なくなってきたと感じていました。

そこでSMTPセッションフィルタがどの程度効果が出ているのか、2010年から2018年にかけての推移を確認しました。

2010年当時のスパム状況

2010年当時はまだスパム全盛期でまだ増えていく感じがありました。
特にbotnetというウイルスに感染したPCを大量に遠隔で操作し、そこから大量にスパムを出すのが主な手法でした。
ただ、OP25Bの広まりやSNS等の他の連絡手段の普及もあり、徐々に変化が起こりつつあった状況でした。

  • スパム率70%~80%程度という感じで年々増えていた
  • 97%前後がbotnetから出されたスパムだった
  • 日本発のスパムはOP25Bにより激減していた

下記表は、2010年当時の実測スパム比率と、S25Rのマッチ率≒botからのスパム送信率、tarpitting(遅延)を掛けた場合のスパム駆除(あきらめて切断される)率、同taRgreyでの駆除率です。
9割以上がbotから出されており、そのためbotに対してのスパム判定がうまくいけば高い比率で対策となっていたことがわかります。

スパム率 69%
S25Rのスパムマッチ率 93%
tarpittingでの駆除率 91%
taRgreyでの駆除率 85%

2012~2018年の状況推移

あるメールサーバで、メールの受信数や各スパムフィルタでのスパム判定数から、botからのスパムメール送信数推移を定点観測しました。

メール総数とスパム数

まず基本となるメール総数とスパム数の推移です。1メールアドレスあたりの月平均受信数です。
スパムが減っているため、メール総数が減っていることがわかります。

アカウントあたり 2014年まで 2018年現在
メール数 2,500通/月ほど 1,000通/月弱
スパム数 2,000通/月ほど 500通/月ほど

f:id:stealthinu:20181204160446p:plain

スパム率

スパム比率の推移をグラフにしました。
ここ数年で一気にスパム比率が少なくなったことがわかります。(と言ってもまだ半分がスパムですが)

f:id:stealthinu:20181204160459p:plain

  • 2014年くらいまでずっと75%くらいだった
  • その後徐々に低下し2018年には50%を切る

メール総数とハム数

正常なメール(ハム)の数は意外に減っておらず、横ばいでほぼ変わっていないことがわかります。
メールマガジンなど、DMの需要はまだ減っていないのだろうと思われます。

f:id:stealthinu:20181204160441p:plain

減ったスパムの種類

スパムはここ3,4年で大きく減っており、意外に普通のメール流量は減っていないことがわかりました。

それではどんなスパムが減ったのでしょうか。

動的IPからと推測される接続推移

S25Rに引っかかるような、逆引き名が動的IPっぽい接続はbotからである可能性が高いと推測でき、それらbotからと思われる接続はここ数年で激減していることがわかります。
またtarpittingで切断された件数も同様に減少しています。

f:id:stealthinu:20181205180721p:plain

  • S25Rに掛かる接続元は70%減程度に激減
  • tarpittingで切断されたメール数も合わせて減少

tarpittingでの切断率推移

動的IPからと思われる接続でtarpittingで切断された率も急激に減少しています。

f:id:stealthinu:20181204155731p:plain

  • 2014年くらいまでずっと80%程度だった
  • その後2018年には30%にまで急激に低下

S25Rに引っかかるものすべてがbotなわけではなく、メールマガジンの大量発信やクラウドサーバから出されているものが誤検出している場合があります。
それらはtarpittingを抜けるため、botが減ったことで相対的にそちらの比率があがり、切断率が下がったのではないかと考えられます。

tarpittingを抜けれなかったものだけがbotと考えると、botからの接続は最盛期より10%程度にまで減ったと考えられます。

SMTPセッションフィルタの有効度推移

このサーバではメールの中身で判定するコンテンツフィルタも利用でき、その場合はSMTPセッションフィルタを抜けてきたものをフィルタしています。
どちらのフィルタでどれだけスパムが落とされたかで、各フィルタの有効性がどう推移してきたかを見てみます。

コンテンツフィルタとSMTPセッションフィルタの効果推移

f:id:stealthinu:20181204160503p:plain

  • コンテンツフィルタは30%減程
  • tarpittingは85%も激減

tarpittingの1次フィルタの効果

f:id:stealthinu:20181204160510p:plain

  • 2015年頃まではずっと70%~80%維持
  • 以降急激に低下しついに30%程度に

SMTPセッションレベルでのフィルタの効果が減少してあまり意味をなさなくなっていることがわかります。

結論

botnetからの送信が大幅に減ったため、botのクセを利用してスパムを排除するSMTPセッションフィルタも効果をなさなくなりつつあることがわかりました。
スパム(botnet)はすでにメールではなく、より効果の高いSNSなどを狙ったり、メールを使う場合でもより効率の高いフィッシングなどに使われるようになったと考えられます。

このことから、taRgreyはもう導入する意味がないといえます。これはgreylistingなど他のSMTPセッションフィルタも同様です。
考案者としては複雑な心境ですが、そもそもスパムがなければスパムフィルタは不要なわけで、だから喜ぶべき話だと思います。

はてなブログへの移行

長らくはてなダイアリーで書いてきましたが、とうとうはてなブログへの移行を行いました。

移行者が多かったみたいでインポートができないという問題がありましたが、今日やったところ無事に移行できました。

最近書くものは、例えば手順書だったりプレゼン資料だったり、なるべくmarkdownで書くようにしていて、逆にmarkdownで欠けなかったはてなダイアリーの内容は後から手直ししていたため、そこは便利になる感じです。

長野ディープラーニング同好会 #6

ディープラーニング同好会6回め開催しました。

長野ディープラーニング同好会 #6 - connpass https://nseg.connpass.com/event/109608/


今回は初参加の方EijiUnoharaさんがいらしたのですが、ご自分でVGG使った転移学習で猫認識とかされてたりして、色々と参考になるお話を聞けたりしました。

あと、塩尻MLもくもく会(塩尻MLもくもく会 #12)主催されてるalaskaさんにも来ていただけました。
alaskaさんがどなたかわかってなかったのですが、お会いしてやっと顔とアカウントが合致したというか、あ、alaskaさんだったんだ、というのがわかりました。


ということで、当初第6回でやろうと思ってたことはやらず、ずっとディープラーニング系のよもやま話をして過ごしてしまいました。
が、僕的にはそういう話ができてとても楽しかったです。


塩尻MLもくもく会の進め方の話を聞いて、最初にこんなネタで今日は進めよう、というのだけやって終わりにみんなでちょこっと発表、みたいなのもいいかなと思いました。


まあこじんまりとやってるので、まあその時の感じで柔軟に進めるしかないかなと思いますが。

長野ディープラーニング同好会 #5

ディープラーニング同好会5回め開催しました。

長野ディープラーニング同好会 #5 - connpass


今回は、自分が告知するのがだいぶ遅かったため、人が集まらずに2人だけでやりました。


前回の続きで、CNNで大きく位置ずれやサイズの違いがあった場合にどうやれば認識率をあげられるかを試しました。


今回は、位置ずれやスケーリングした教師画像をプログラム的に作って大量に学習させる方法を試しました。

実は前回あまりうまく行かなかったため、絶対にこれでうまくいくだろう、と思っていた方法を試したのですが… 確かにだいぶ良くはなるのですが、MNISTのような簡単な問題で、ある程度の大きさのCNNで大量の自動生成データで試しているにもかかわらず、せいぜい90%程度となってしまいました。


だいぶ負けた気分です。

が、まあたぶんこの方法でちゃんと詰めていけば、99%とかまで持っていけそうな感じはしました。


ただ、それで詰めていってもあまりおもしろくはないと思うので、次回は方針を変えて、AEを作って、その中間層に次元削減されてできた出力を使って、そこから判定してみる、というのを試してみようと思います。

長野ディープラーニング同好会 #4

ディープラーニング同好会4回め開催しました。

長野ディープラーニング同好会 #4 - connpass


やっと色々試してみれる状況になったので、前に質問の出ていた、CNNで大きく位置ずれやサイズの違いがあった場合でも認識できるのか、認識できないならどうやればできるようになるのか、を試すことになりました。


自分は単純に、ネットワークを深くして最終のDense層を少なく、1層だけとかにして学習させれば、どこかのConvで文字が認識できるようになるんでは、とか思って試したのですが、確かに良くはなるものの、そこまで画期的によくはなりませんでした。


試すために、縮小や位置ズレを作るプログラムをその場で書いていたのですが、そこで時間使いすぎてしまったかと思います。
事前準備しといて、使える部品くらい提供しないと難しいなと思いました。

長野ディープラーニング同好会 #3

ディープラーニング同好会3回め開催しました。

長野ディープラーニング同好会 #3 - connpass


今回参加者が最終的に6名になったのですが、初参加の方が3人いらしたので、前回、前々回でやったGoogle Colab使うところからはじめて、ざっとパーセプトロンバックプロパゲーション、CNNの説明して、Kerasのコード動かしてみる、というところをおさらいしました。

んでTPU使った場合とGPU使った場合とでの速度比較もやってみました。
ただ、だいぶ時間なかったのでコード走らせて速度比較しただけで、どこ修正すればいいかとかまでは出来ずでしたが。

TPU使う場合の変更点としては下記エントリー参照ください。
Google ColabでKerasからTPUを使う方法とGPUとの速度差


これまでの3回、最初のブートストラップのところを何度もやることになってしまってますが、そんなに参加者も多くないので、今のところは、なるべく興味ある方全員を拾っていけたらな、と思います。


次回は、いろいろとデータセットやネットワークをいじって、いろいろと実験できたらいいなと思ってます。

Google ColabでKerasからTPUを使う方法とGPUとの速度差

必要なことまとめ

  • ランタイムで「TPU」を選択する
  • kerasではなくtensorflow.kerasを使う
  • modelをTPU用のモデルに変換する
  • TPUモデルではpredictができないので確認はCPUモデルに戻して行う


Google ColabでTPU使うのは、こちらの記事が詳しいです。自分もこちらを参考に試しました。
Google ColaboratoryのTPUを試してみる

またCholletさんが紹介されてた公式?のノートがあり、必要なコードがまとまってるのでおすすめです。
Keras Fashion MNIST and TPUs - Colaboratory

ランタイムで「TPU」を選択する

まず、仮想マシンのタイプを「TPU」が利用できるものに変更します。

ランタイム→ランタイムのタイプを変更→TPU

kerasではなくtensorflow.kerasを使う

下記のように「keras」からのものを使うとTPU未対応のためエラーが出て動きません。

from keras.models import Sequential
model = Sequential()

「keras」を「tensorflow.keras」にすべて置き換えてやる必要があります。

from tensorflow.keras.models import Sequential
model = Sequential()

modelをTPU用のモデルに変換する

modelは普通にそのまま作れますが、その作ったモデルをkeras_to_tpu_modelを使ってTPU用のモデルに変換して、compileやfitします。
また、model生成にはOSからTPU情報取得して渡す必要があります。

import tensorflow as tf
import os
tpu_model = tf.contrib.tpu.keras_to_tpu_model(
    model,
    strategy=tf.contrib.tpu.TPUDistributionStrategy(
        tf.contrib.cluster_resolver.TPUClusterResolver(tpu='grpc://' + os.environ['COLAB_TPU_ADDR'])
    )
)

tpu_model.compile(...)
tpu_model.fit(...)

ランタイムでGPU選択しただけでGPUが使えるため、ついTPUを選択しただけで早くなるのかと思ってしまいがちですが、変換しないとCPUのみになるのでめちゃ遅いので注意です。

TPUモデルではpredictができないので確認はCPUモデルに戻して行う

tpu_model.predict()がないため、学習後の重みを使って出力させることができません。
どうするのかな?と思ったら、CPUモデルに戻してやってそれでpredictする必要があるようです。

cpu_model = tpu_model.sync_to_cpu()
cpu_model.predict(...)

ColabのGPUとTPUランタイムでの速度差

Keras Fashion MNIST and TPUs - Colaboratory で使われている Conv2D x3 + Dense x2 のサンプルでは

GPU: 235秒
TPU: 89秒

となり、2.6倍程度の速度でした。

が、TPUはバッチサイズをもっと大きくすることができ、またネットワークサイズをGPUよりもだいぶ大きくして動かすことができます。
ネットワークサイズが大きくなるほど差が大きくなる感じです。

長野ディープラーニング同好会 #2

ディープラーニング同好会2回め開催しました。

長野ディープラーニング同好会 #2 - connpass


Google Colab使ってMNIST(数字認識)させるのの続きということで、前回はバックプロパゲーションを3層とか4層でやったのですが、今回はCNNで行いました。

以前やったディープラーニングハンズオンに参加されてない方もいたので、簡単に畳み込み層とプーリング層についての説明とかしたのですが、そこから話が深くなり、プーリングで位置ずれを吸収すると言ってもそんなに大きくは吸収できないのでは、というような質問が出ました。
例えば、画面いっぱいに「あ」と書いてあるので認識できるようになっても、画面1/4のサイズで端っこに「あ」があったら認識できないのでは、というものです。
CNNの下の方の層でもう「あ」が認識されてしまう状況ならたぶんどこにあっても認識されるはず(つまり「あ」という「部品」として認識可能になってる)だけど、層が浅くて最後のBPのフルコネクトでやっと認識できる状況だと、そういう状況になりそうと話しました。


この辺は次回でみんなで試せたらなと思います。

Google Colabで生成した動画をインライン表示する

つくりながら学ぶ!深層強化学習」という本の中で、CartPoleなどで動画を生成して表示しているものがあります。

Google Colab上で実行している場合、本の例ではそのまま動画で表示することができないのですが、Colab(Jupyter)のセル上で動画表示可能にすることができるようにしました。

といっても、こちらの「ChainerRL を Colaboratory で動かす - Qiita」を参考にさせていただいただけなのですが。


下記のように必要なツールやライブラリを入れて、HTMLへの出力(Javascriptでのアニメーション化)を利用します。

必要なツールやライブラリのインストール

!apt -qq install xvfb ffmpeg> /dev/null
!pip -q install gym
!pip -q install JSAnimation
!pip -q install pyglet==1.2.4
!pip -q install pyopengl
!pip -q install pyvirtualdisplay
!apt -qq install python-opengl

出力用の仮想ディスプレイを生成

from pyvirtualdisplay import Display
display = Display(visible=0, size=(1024, 768))
display.start()
import os
os.environ["DISPLAY"] = ":" + str(display.display) + "." + str(display.screen)

必要なPythonのライブラリをimport

import matplotlib
import gym
import JSAnimation
import pyglet
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

CartPoleの動きをランダムで行わせる

frames = []
env = gym.make('CartPole-v0')
observation = env.reset()

for step in range(0, 200):
  frames.append(env.render(mode='rgb_array'))
  action = np.random.choice(2)
  observation, reward, done, info = env.step(action)

動画をフレームごとに生成して表示

from JSAnimation.IPython_display import display_animation
from matplotlib import animation
from IPython.display import HTML

plt.figure(figsize=(frames[0].shape[1]/72.0, frames[0].shape[0]/72.0), dpi=72)
patch = plt.imshow(frames[0])
plt.axis('off')
  
def animate(i):
  patch.set_data(frames[i])
    
anim = matplotlib.animation.FuncAnimation(plt.gcf(), animate, frames=len(frames), interval=50)
HTML(anim.to_jshtml())