# -*- coding: utf-8 -*-

import numpy as np
import pandas as pd
import re
from keras.models import Sequential
from keras.layers.core import Dense
from keras.optimizers import SGD

# seed値
np.random.seed(2016)

def make_label():

    # バリデーションデータの推測値を取得
    valid_data = pd.read_csv("subm/valid_average.csv")
    # 実データとtargetに分割
    valid_target = valid_data.ix[:,"target"]
    del valid_data['target']
    v_target = []

    # ラベルデータを文字列から変換
    for v in valid_target:
        v_target.append(list(re.sub(r'[\[\]\.\s]','',v)))

    valid_data = np.array(valid_data, dtype=np.float32)
    valid_target = np.array(v_target, dtype=np.float32)

    # 2層のネットワークを作成
    model = Sequential()
    model.add(Dense(8, activation='relu', input_dim=6))
    model.add(Dense(6, activation='softmax'))
    sgd = SGD(lr=1e-3, decay=1e-6, momentum=0.9, nesterov=True)
    model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=["accuracy"])

    # 学習
    model.fit(valid_data, valid_target, batch_size=32,
              nb_epoch=3500,
              verbose=2,
              shuffle=True
              )

    # クラス名取得
    columns = []
    for line in open("../../data/Caltech-101/label.csv", 'r'):
        sp = line.split(',')
        for column in sp:
            columns.append(column.split(":")[1])

    true_num = 0.0
    false_num = 0.0

    # テストデータが各クラスに分かれているので、
    # 1クラスずつ読み込んで推測を行う。
    for test_class in range(0, 6):
        # テストデータの推測値を取得
        test_data = pd.read_csv("subm/result_average_%i.csv"%test_class)
        test_id = test_data.ix[:,"img"]
        del test_data['img']
        test_data = np.array(test_data, dtype=np.float32)

        # 推測
        test_res = model.predict(test_data)

        # imgを追加し、疑似ラベルを書き出す
        result1 = pd.DataFrame(test_res, columns=columns)
        result1.loc[:, 'img'] = pd.Series(test_id, index=result1.index)
        pseudo_file = './subm/pseudo_label_%i.csv'%test_class

        # 確率が0.8以上のデータのみを疑似ラベルとして使用する。
        i_index = []
        for i, row in result1.iterrows():
            val = row.values
            if np.max(val[0:6]) > 0.8:
                i_index.append(i)
        result1_out = result1.ix[i_index, :]
        result1_out.to_csv(pseudo_file, index=False)

        # 推測の精度を測定する。
        # 一番大きい値が入っているカラムがtest_classであるレコードを探す
        one_column = np.where(np.argmax(test_res, axis=1)==test_class)
        print ("正解数　　" + str(len(one_column[0])))
        print ("不正解数　" + str(test_res.shape[0] - len(one_column[0])))
        true_num += len(one_column[0])
        false_num += test_res.shape[0] - len(one_column[0])

    print "正解率　　" + str(true_num / (true_num + false_num))


# 実行した際に呼ばれる
if __name__ == '__main__':

    make_label()

