DeepPredNetで地震の予想が出来るのか検証してみた

# はじめに
こちらはFOSS4G 2016 Tokyoで発表した内容です。
Deep Learningは勉強し始めたばかりなので至らない点が多々あるかと思います。
間違っているところがあったら突っ込んでいただければ幸いです。

# 弊社でのDeep Learning×GISの開発事例
　タイトルで「DeepPredNetで地震の予想が出来るのか検証してみた」と書いているのですが、まずは弊社での開発事例をご紹介したいと思います。

　弊社では受託開発で**古地図の自動分類**を行っていました。
![図1.png](https://qiita-image-store.s3.amazonaws.com/0/147199/21795067-356b-467b-768e-899e7e3a840f.png)

　古地図の地図記号から識別し、土地利用の領域ごとに色分けして分類するニューラルネットワークの開発しました。


## 実装方法
・畳み込みニューラルネットワーク（CNN）で実装
・ Googleの機械学習ライブラリTensorFlowを使用
・[ハイパースペクトルの航空写真から土地を分類するプログラム](https://github.com/KGPML/Hyperspectral)をもとに作成


## 当初の予想とその結果
**予想**
水田や市街地といった特徴がわかりやすいところは精度が良く、逆に畑又は空地といったほぼ空白の部分は難しそう、と思っていました。
![図2.png](https://qiita-image-store.s3.amazonaws.com/0/147199/43d14d6e-8168-ffaf-dad6-a69bb1dc13bc.png)


**結果**
ほぼ予想通り。
空白部分が多く、地図記号が均一ではない針葉樹林なども精度が悪かったです。
![図3.png](https://qiita-image-store.s3.amazonaws.com/0/147199/217b46b6-a3a7-7851-989c-9eddd6e3b89c.png)


## 試行錯誤
　精度を上げるのは簡単じゃないかと思っていたんですが、これがなかなか大変でした。
### ①学習方法を変えてみる
　大きな一枚の画像で学習をするよりも小さい画像を複数学習するほうがいいのでは？？と考えました。
　そこで広域の特徴を捉えるために全てのタイルを繋げて一枚の地図で学習から、タイル単位で学習を繰り返し行いモデルを成長させていく学習方法に変更してみました。

### ②畳み込みニューラルネットワークの構成を変更してみる
・畳み込みニューラルネットワークの構成や設定をクラス化して設定ファイルに記述し、簡単に変更できるように改良
・畳み込み層と全結合層の層の数を増加
・全結合層の各層のニューロンの数を増加
・パッチサイズを大きく変更（15x15→37x37）

## 試行錯誤の結果
**7～8割くらいの精度になった！**
![結果.png](https://qiita-image-store.s3.amazonaws.com/0/147199/5f454f9f-a0d4-f6d7-71d8-3a429fde3c62.png)



![図5.png](https://qiita-image-store.s3.amazonaws.com/0/147199/2cd2397a-2899-1402-4eda-7313c12c2e73.png)

畳み込みニューラルネットワークの構成はこんな感じです。
![テーブル.PNG](https://qiita-image-store.s3.amazonaws.com/0/147199/5680d8b0-9a9e-50f3-e5e3-bed379236332.png)


## pix2pixで試行錯誤した精度を上回ってしまった件
　DNN界隈で話題になっている[pix2pix](https://github.com/phillipi/pix2pix)を試してみたところ、たった数時間の学習で数ヶ月試行錯誤した精度を上回ってしまいました。。
詳細は[こちら](http://qiita.com/wayama_ryousuke/items/ca43cabffde90a66434b)をご覧ください。
　また、標高タイルからCS立体図をpix2pixを使って[検証してみた記事](http://qiita.com/wayama_ryousuke/items/8e6c2b091603a30d294f)もありますので、よろしければどうぞ！

##TensorFlowを使用しての感想
・環境設定がちょっと面倒
　　＊OSはUbuntu14.04推奨
　　＊GPUを使う場合はCUDAとCuDNNが必要

・バージョンアップが早いのでキャッチアップが大変

・マルチGPUで動くようにしたけどむしろ遅くなった

・可視化ツールTensorBoardは便利
　　＊ニューラルネットの構成を図示したり、
　　　パラメータや誤差、精度などをグラフ表示したりしてくれる




# 他に応用事例はないかな？
　Deep Learning×GISで、**学習データを使えば人手でやっていた労力のかかる分類作業を自動化できる**という事がわかりました。

　他に応用事例はないかなと思い調べてみました。するとこんな記事を見つけました。
　[太陽フレアを事前に予知する宇宙天気予報](http://qiita.com/nushio/items/a8e9aabc3bd7fdf1b33e)

　この記事ではLSTMを用いて太陽フレアの発生を予測する方法について記載されています。
　こちらの宇宙天気予報では太陽光の波形データからX線フラックスの予測を行っていました。そこで、太陽光の波形データの代わりに地震波のデータを使用すれば地震の兆候をDeep Learningが抽出してくれるかもしれない、と考えました。
　
　そもそもなぜ地震に着目したかというと、現在懸念されている南海トラフや首都直下型などの地震の予知ができれば心構えや準備が出来るため、減災につながると考えたからです。

# 時系列予測には何を使う？
　「宇宙天気予報」ではLSTMを使用していました。
　時系列データの予測にはLSTMやHTMやRNNなど色々なニューラルネットワークがありますが、今回は全脳アーキテクチャ勉強会で話題になっている[DeepPredNet](https://github.com/coxlab/prednet)を使用することにしました。
デモは[こちら](https://coxlab.github.io/prednet/)です。

# Deep PredNetで地震の予想ができるか実験！
##まずは
　PredNetのソースを応用して使用するために地震波形データを画像にする必要がありました。
　さらに、マルチモーダルに対応するため、地震波形データだけでなく**マグニチュード**と**震源の深さ**も一緒に画像にしてみました。

## データの取得先
**地震波形データ**：[IRIS](http://service.iris.edu/irisws/timeseries/1/)
**地震データ**：[IRIS]
(http://service.iris.edu/fdsnws/event/1/)

IRISは全世界のデータを無料で提供していて、APIで簡単に取得できます。ただし日本のデータは少ない印象です。

## 手法
・360 × 180pxの画像を作成し、世界地図に見立てる

・観測点(ステーション)の緯度経度の小数点を切り捨てて画像のX,Yに1pxとしてプロット

・各地点のカラーは以下のようにする
R： 地震波のデータ(0～255) 
G： マグニチュード(0～255)
B： 震源の深さ(0～255)

・地震波形のデータは1秒間に数件あったため、平均して1秒当たりの値を算出

・カラーはそれぞれのデータの最小値と最大値から等間隔に256分割して0～255の輝度値として使用


* * *
するとこんな画像が出来ました。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/147199/d5d0ca81-ddc5-2626-439b-7724b3c1e071.png)

## 結果
とりあえずランダムに10個の観測点のデータを使ってやってみました。
何も出力されない・・
![キャプチャ2.PNG](https://qiita-image-store.s3.amazonaws.com/0/147199/1b763e8e-fd8a-a5fc-3a51-0d65e666aec0.png)

## 失敗原因を考えてみる
観測点の数が少ないから失敗したのか？
↓
じゃあ全世界の観測点のデータを使ったらどうだろう？
↓
データサイズがでかすぎて3日経ってもデータの取得が終わらない! 
↓
じゃあ日本に限定してみるか

## 日本に限定した結果
日本のデータは予想以上に少なかったです。
結果はやっぱり変わらない・・
![キャプチャ3.PNG](https://qiita-image-store.s3.amazonaws.com/0/147199/78bab1f7-d7cc-315f-b485-6bc2df8e3493.png)

## もう一度失敗原因を考えてみる
・畳み込みニューラルネットの特性上、周りのpxを畳み込むため、1px単位のデータだと意味をなさないのかもしれない。

・スパースなデータは畳み込みニューラルネットワークと相性が悪いのかも。やはり1px単位ではなく、補間したほうが良いのでは。

↓
**GMTでスパースな欠損データを補間してみよう！！**

## GMTを使う手法
・地震波系のデータをXYZファイルにする

・前処理としてblockmedianでエイリアスの除去する

・surfaceで補間を行いXYZデータをグリッド化する

・grdimageでグリッドデータからカラーの図を作成し、ps2rasterで画像にする

・地震波形のデータは1秒間に数件あったため、平均して1秒当たりの値を算出

・カラーはそれぞれのデータの最小値と最大値から等間隔に256分割して0～255の輝度値として使用

## GMTを使った結果
・日本の観測地点のデータが少ないため、非常にスパースなデータになってしまった

・特定の地域が異常値になっており全体の階調値がおかしくなってしまった

![キャプチャ6.PNG](https://qiita-image-store.s3.amazonaws.com/0/147199/a031d578-1e21-f198-5dbb-190b359afe17.png)


データを見直す必要がありそうです。

## 地震波形データの取得先を変更する
**地震波形データ**：[防災科学技術研究所 (Hi-net)
](https://hinetwww11.bosai.go.jp/auth/?LANG=ja)

　データの取得にはユーザー登録が必要で、フォームに入力してデータをダウンロードをします。
　長期間のデータが取得できなかったため、学習用に東日本大震災のデータ、検証用に熊本地震のデータをそれぞれ50分ずつ取得してみました。

## 実装中にはまったところ
### 同じ観測点で複数の地震波形データがある？？
　地震波形データはNS(北-南)・EW(東-西)・UD(上-下)の3成分があるようです。3つのデータを1つにする必要がありました。

　そのため3成分からベクトルの長さ(ノルム)を算出して波形データとして使用しました。

### GMTで震源地点に円を表示したい！
　マグニチュードによってサイズが異なる円をPSXYで描いてみたんですが、GMTはオプションが多くGMT初心者の私には難しかったです。。
　重ね書きのルール(>，>>，-K，-O)に気づかず数時間はまってしまいました。共感してくれる人はいるはず・・！
![キャプチャ7.PNG](https://qiita-image-store.s3.amazonaws.com/0/147199/abb13e78-0e27-d66b-aad7-6bab4de0cfff.png)

### 地震波の階調値がおかしい
地震波のデータを画像にしてみると全部真っ黒になってしまいました。特定の値に集中しているようです。
![階調１２.PNG](https://qiita-image-store.s3.amazonaws.com/0/147199/71cc4bcd-a6e3-2827-5b30-366d384980d8.png)

　原因を調査したところ、等間隔で256分割していたため、値に偏りがあり全体の階調がおかしくなっていたようでした。
　256分位にするようにしたところ、均等に数が分布されて自然になりました。
![階調１３.PNG](https://qiita-image-store.s3.amazonaws.com/0/147199/26c15aaa-f7c5-609b-a67c-51591ce296c9.png)

## 工夫したところ
## 地震発生個所のデータを特徴として捉える
　地震のデータ(マグニチュード)は1秒のみであるため、ニューラルネットで特徴として捉えるために5分間残すようにしました。
　また、5分後には収束するようにサイズとカラーを変更するようにしました。
![流れ.PNG](https://qiita-image-store.s3.amazonaws.com/0/147199/cb46354f-fa55-0688-13a2-aa3f85720ca3.png)

## 最終結果！！！
こんな結果を期待していました。 
![期待してたやつ.PNG](https://qiita-image-store.s3.amazonaws.com/0/147199/cd4aa4dc-8c14-c393-f922-ff8a48af585f.png)

***

地震波の動きから地震の発生を予想できたらいいな、と思いわくわくしながらやってみたところ。。

![3_ac.gif](https://qiita-image-store.s3.amazonaws.com/0/147199/a54247a6-a9b7-a4b6-689f-0105ca0e0c60.gif)　　　　　![3_pre.gif](https://qiita-image-store.s3.amazonaws.com/0/147199/03cbf420-acfe-6b85-05b8-58b5a7b57e7e.gif)
　　　　　**正解**　　　　　　　　　　　　　**PredNetの予想**

うーーーん。何でしょうねこれは。
精度はイマイチという結果になってしまいました。。

## 考察
**・データの数が圧倒的に足りない。**
　＊日本ではなく世界規模が必要
　＊長期間(10年単位とか)のデータが必要

**・豊富な計算資源が必要。**
　＊GPUを使って計算したが50分間のデータを
　　60回学習するのに8時間かかった。


## まとめ
　精度が高くなれば天気予報みたいな感じで「今日の地震予想」みたいなものができるかもしれません。正確性が多少低くても1つの防災の指針になるのではないでしょうか。

　また、Deep Learningは応用範囲は広いですが、まだノウハウがなく、なぜ失敗するのか、なぜこんな計算結果になるのか等が分からず苦労しました。ブラックボックス化した計算内容を人間に理解できるように解析するDeep Learningが登場すればいいのになあと思います。

　それから、一社だけだと計算資源やマンパワーが圧倒的に足りないと実感しました。ご興味のある方は一緒に研究してみませんか？


以上で終わりです！！
読んでくださってありがとうございました★