[SIGNATE]画像で遊んでみる(土砂崩れを探せ)


なんか新しいコンペのメールが来てたので[SIGNATEのコンペのデータ](https://signate.jp/competitions/110)で遊んでみた。

# コンペの目的
>Tellus Satellite Challengeは、衛星データの利活用事例の可視化、優秀な分析人材の発掘、衛星データ種やフォーマットの周知・啓蒙等、Tellusの利活用の促進を目的としたデータ分析コンテストです。
>
>第1回目のテーマは「SARデータを用いた土砂崩れ検出」です。
>
>近年、自然災害のリスクが高まる中、災害時の土砂崩れの迅速把握が人命救助の観点などから極めて重要であり、観測衛星からのモニタリングが緊急時対応で実施されております。取得されたデータから土砂崩れを判定する業務は、専門家の高度なスキルにより解析される一方で、その判定は容易ではないのが実際です。そこで今回のチャレンジでは衛星画像データから土砂崩れ領域をより高い精度で検出するアルゴリズムの開発を目指します。

とのこと。
ここに書いていいのかどうかわからないが、画像ので何かやってみたかったのがちょうどよかっただけなのでちょっとやってみることにする。


## データをDLして解凍
Lhasaで解凍してみたら、65532ファイルまでしか解凍できず。
知らなかったけど、Lhasaって上限値があったのか。

別のをつかったら問題なくできそう。ただ、残り時間がびっくりするぐらいの長さ。
とりあえずほったらかして寝てみる。

## 解凍つづき
どうにもちゃんと解凍が終わらない。
メモリの問題ないのかツールの問題なのか。。。
進捗もようわからんし、解凍している間に端末が使えない状態になるのもムカついたのでPythonで解凍処理を書いてみた。
どうせ一発で終わらないだろうという推測の元、既ファイルチェックも入れてみた。


readmeを見るとこんな感じでデータが格納されているらしい

    train(Learning-use image data)
    ├─LANDSAT(Landsat-8 image files)
    │  ├─after(after earthquake)
    │  │  ├─negative(not including landslides)
    │  │  └─positive(including landslides)
    │  └─before(before earthquake)
    │      ├─negative(not including landslides)
    │      └─positive(including landslides)
    └─PALSAR(PALSAR-2 image files)
        ├─after(after earthquake)
        │  ├─negative(not including landslides)
        │  └─positive(including landslides)
        └─before(before earthquake)
            ├─negative(not including landslides)
            └─positive(including landslides)

    test(Evaluation-use image data)
    └─PALSAR(PALSAR-2 image files)
        ├─after(after earthquake)
        └─before(before earthquake)



なので、以下のようにして何回かにわけて実施できるようにした。

	# coding: UTF-8
	import zipfile
	import os

	zip_folder_path = r"C:\PJ\91_SIGNATE\20181018_\DL"
	# zip_file_name = r"\train.zip"
	# zip_file_name = r"\readme.zip"
	zip_file_name = r"\test.zip"
	zip_file_path = zip_folder_path + zip_file_name
	unzip_path = r"C:\PJ\91_SIGNATE\20181018_\DL\unzip"

	image_type = "PALSAR"
	# image_type = "LANDSAT"
	# time = "after"
	time = "before"
	nega_posi = "negative"
	# nega_posi = "positive"

	def unzip_namelist():
	    with zipfile.ZipFile(zip_file_path) as existing_zip:
	        list_zip_file = existing_zip.namelist()
	        # target_list_zip_file = [file_name for file_name in list_zip_file if (image_type in file_name) and (time in file_name) and (nega_posi in file_name)]
	        target_list_zip_file = [file_name for file_name in list_zip_file if (image_type in file_name) and (time in file_name)]
	        all_count = len(target_list_zip_file)

	        for index, file_name in enumerate(target_list_zip_file):
	            if(os.path.exists(unzip_path + "\\" +file_name)):
	                print("[{}:{}] exists {}".format(all_count, index, file_name))
	                continue
	            print("[{}:{}] extract {}".format(all_count, index, file_name))
	            existing_zip.extract(file_name, unzip_path)

	def main():
	    unzip_namelist()

	if __name__ == '__main__':
	    print("Start")
	    main()
	    print("End")


ここまででなんだかんだでほぼ丸一日かかって解凍終了。
※個人的にはもう少し解凍しやすいように圧縮しておいてもらえるとありがたかったかなぁと。。。

## データの中身について
- やりたいこととしては、「前後の画像を比べてそこが土砂崩れなのかどうかを判別したい」ということなのだろうと解釈。

- 正直なところ、trainのLANDSATは何に使えばいいのか想像ができない。
testの方にないものをモデルに組み込んで何かしらの役に立つのか？

- どうしたらいいのかさっぱりわからないので、とりあえず簡単に思いつくところで
afterとbeforeの差分を使ってそれをtrainとしてみることにする。


こんな感じで差分を生成


    def convert_image(img):
        dim = img.shape[0] * img.shape[1]
        img_vector = img.reshape(1, dim)
        return img_vector[0]

    def convert(image_path):
        feature = data.imread(image_path)
        list_feature = convert_image(feature)
        np_feature = np.array(list_feature)
        return np_feature

    def get_data(data_type, nega_posi):
        print("Start : get_data : {} , {}".format(data_type, nega_posi))
        labels = []
        file_name_list = []
        datas = []

        import glob
        target_file_path_base = ""
        if(data_type=="train"):
            image_path_after = base_image_path_train.format("after", nega_posi, "*")
            target_file_path_base = base_image_path_train
        else:
            image_path_after = base_image_path_test.format("after", "*")
            target_file_path_base = base_image_path_test

        files = glob.glob(image_path_after)

        import pathlib
        for index, file in enumerate(files):
            try:
                # 対応するbeforeを取得
                target_file_path = ""
                p_file = pathlib.Path(file)
                if(data_type=="train"):
                    target_file_path = target_file_path_base.format("before", nega_posi, p_file.name)
                else:
                    target_file_path = target_file_path_base.format("before", p_file.name)
                # print(target_file_path)

                np_feature_after = convert(file)
                # pprint.pprint(np_feature_after)
                np_feature_before = convert(target_file_path)
                # pprint.pprint(np_feature_before)

                # 差分
                np_feature_diff = np_feature_after - np_feature_before
                # pprint.pprint(np_feature_diff)
            except:
                print("Error : SKIP : {}".format(file))
                continue

            datas.append(np_feature_diff)
            file_name_list.append(p_file.name)
            if("positive" in nega_posi):
                labels.append(1)
            else:
                labels.append(0)

            # if(index>3):
            #     break

        print("End : get_data : {} , {}".format(data_type, nega_posi))
        return labels, datas, file_name_list




まずは適当なファイル数で動きそうかを試してみて、いけそうだったので全部で流してみる。


教師データを対象にやってモデルを生成してみる。


	labels_train Count : 247968
	datas_train Count : 247968
	0 : LogisticRegression : 2018/10/20 21:19:54
	 -- evaluation : 0.9935919150858176
	1 : Perceptron : 2018/10/20 21:41:10
	 -- evaluation : 0.9868329784488322
	2 : Random Forest : 2018/10/20 21:41:53
	 -- evaluation : 0.9938298490127758
	           model_name     score  \
	2       Random Forest  0.993830
	0  LogisticRegression  0.993592
	1          Perceptron  0.986833

	                                               model
	2  (DecisionTreeClassifier(class_weight=None, cri...
	0  LogisticRegression(C=1.0, class_weight=None, d...
	1  Perceptron(alpha=0.0001, class_weight=None, et...
	RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
	            max_depth=3, max_features=3, max_leaf_nodes=None,
	            min_impurity_split=1e-07, min_samples_leaf=1,
	            min_samples_split=5, min_weight_fraction_leaf=0.0,
	            n_estimators=300, n_jobs=1, oob_score=False, random_state=0,
	            verbose=0, warm_start=False)


どうみても過学習な気配しかしないが、とりあえずこれで推測させてみる。


## 推測結果

推測して、出力してみたら全部0(not including landslides)
さすがにTESTデータの全部がnot including landslidesってことはないと思うんだよな。。。
でもまあ検証するのもめんどくさいので、これで一回投稿してしまうことにする。

で、結果

>評価結果は以下の通りとなります。
>0.0

でしょうね。

データの処理方法が合ってないんだろうな。。。
どう加工したらいいんだろう。