simpleCNN.py 5.05 KiB
import numpy as np
import sys
import os
import tensorflow as tf
from sklearn.utils import shuffle
from sklearn.metrics import accuracy_score, cohen_kappa_score, f1_score

def getBatch(X, Y, batch_size, i):
    start_id = i*batch_size
    end_id = min( (i+1) * batch_size, X.shape[0])
    batch_x = X[start_id:end_id]
    batch_y = Y[start_id:end_id]
    return batch_x, batch_y

def getLabelFormat(Y):
	vals = np.unique(np.array(Y))
	sorted(vals)
	hash_val = {}
	for el in vals:
		hash_val[el] = len(hash_val.keys())
	new_Y = []
	for el in Y:
		t = np.zeros(len(vals))
		t[hash_val[el]] = 1.0
		new_Y.append(t)
	return np.array(new_Y)

def CNN( x,height,width,n_filter,n_classes):

    pred = None

    conv1 = tf.layers.conv2d( inputs = x, filters = n_filter, kernel_size = [ 7, 7 ], strides = (2, 2), padding = "same", activation = tf.nn.relu )
    bn1 = tf.layers.batch_normalization(conv1)
    n_filter += 48
    conv2 = tf.layers.conv2d( inputs = bn1,
                            filters = n_filter,
                            kernel_size = [ 4, 4 ],
                            padding = "same",
                            activation = tf.nn.relu )
    bn2 = tf.layers.batch_normalization(conv2)
    n_filter -= 32
    conv3 = tf.layers.conv2d( inputs = bn2,
                            filters = n_filter,
                            kernel_size = [ 3, 3 ],
                            padding = "same",
                            activation = tf.nn.relu )
    bn3 = tf.layers.batch_normalization(conv3)
    #vs max pool
    if tag_pool == "mean":
        features = tf.reduce_mean(bn3, [1,2], name="features")
    if tag_pool == "max":
        features = tf.reduce_max(bn3, [1,2], name="features")

    #pred = tf.layers.dense(inputs=features, units=n_classes, name="prediction")

    pred = tf.contrib.layers.fully_connected( inputs=features, num_outputs=n_classes)
    pred = tf.nn.relu( pred, name = "prediction" )


    print "prediction",pred.get_shape()
    #exit()
    return pred, features

# MAIN
# Parameters
itr = int( sys.argv[1] )
p_split = 100*float( sys.argv[2] )
batch_size = int( sys.argv[3] )
hm_epochs= int( sys.argv[4] )
path_in_val = sys.argv[5]
path_in_gt = sys.argv[6]
tag_pool = sys.argv[7]
g_path = 'dataset/'
n_filter = 64

#paths
var_train_x = path_in_val + 'train_x%d_%d.npy'%(itr,p_split)
var_train_y = path_in_gt+'train_y%d_%d.npy'%(itr,p_split)

#load dataset
#(90857,4,65,65)
train_x = np.load(var_train_x)
train_y = np.load(var_train_y)

if path_in_val == './dataset/VHSR/':

    tag_band = '_'
    # Network Parameters
    height = train_x.shape[2]
    width = height
    band = train_x.shape[1]
    n_classes = np.bincount( train_y ).shape[0]-1
    #(90857,65,65,4)
    train_x = np.swapaxes(train_x, 1, 3)

else:
    tag_band = 'NDVI_'
    height = train_x.shape[1]
    width = height
    band = train_x.shape[3]
    n_classes = np.bincount( train_y ).shape[0]-1

print "classes %d"%n_classes

#format data
train_y = getLabelFormat(train_y)

directory = g_path+'SimpCnn%s%s%d_%d/'%(tag_band, tag_pool, p_split, batch_size )
if not os.path.exists(directory):
    os.makedirs(directory)

path_out_model = directory+'modelTT%d/'%itr
if not os.path.exists(path_out_model):
    os.makedirs(path_out_model)

#log file
flog = open(directory+"log.txt","a")

learning_rate = 0.001
#tf_is_traing_pl = tf.placeholder(tf.bool, shape=(), name="is_training")
x = tf.placeholder("float",[None,height,width,band],name="x")
y = tf.placeholder( tf.float32, [ None, n_classes ], name = "y" )

sess = tf.InteractiveSession()

prediction, feat = CNN( x, height, width, n_filter, n_classes )

tensor1d = tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=prediction)
cost = tf.reduce_mean(tensor1d)

optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)

correct = tf.equal(tf.argmax(prediction,1),tf.argmax(y,1))
accuracy = tf.reduce_mean(tf.cast(correct,tf.float64))

#to have tensorboard
tf.summary.scalar("cost function", cost)
writer = tf.summary.FileWriter(path_out_model+"histogram_example")
summaries = tf.summary.merge_all()

tf.global_variables_initializer().run()

#initialise to save model
saver = tf.train.Saver()

iterations = train_x.shape[0] / batch_size

if train_x.shape[0] % batch_size != 0:

    iterations+=1

best_loss = 50
j = 0
for e in range(hm_epochs):
    #shuffle input
    train_x, train_y = shuffle(train_x, train_y)

    lossfunc = 0
    accuracy_ = 0

    for batch_id in range( iterations ):

        batch_x, batch_y = getBatch(train_x, train_y, batch_size, batch_id )

        summ, acc, _, c = sess.run([summaries, accuracy, optimizer, cost], feed_dict={x: batch_x, y:batch_y})
        accuracy_ += acc
        lossfunc += c
        writer.add_summary( summ, j )
        j += 1

    loss_epoch = float(lossfunc/iterations)
    acc_epoch = float(accuracy_/iterations)
    print "epoch %d Train loss:%f| Accuracy: %f"%( e, loss_epoch, acc_epoch )
    flog.write( "epoch %d Train loss: %f| Accuracy: %f\n"%( e, loss_epoch, acc_epoch ) )

    if loss_epoch < best_loss:
        best_loss = loss_epoch

        saver.save( sess, path_out_model+'model', global_step = itr )

flog.close()