simpleDenseNet.py 7.18 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 ConvBnPool(x, n_fitlers):

    conv7 = tf.layers.conv2d(x,
                            filters = n_filters*2,
                            kernel_size = [ 7, 7 ],
                            strides = ( 2, 2 ),
                            padding = "same",
                            activation = tf.nn.relu)

    bn = tf.layers.batch_normalization(conv7)
    max_pool = tf.layers.max_pooling2d( bn,
                                       pool_size = [3, 3],
                                       strides=2)

    return max_pool

def DenseBlock(x,i,n_filters,drop_rate, tf_is_traing_pl):

    conv1 = tf.layers.batch_normalization(x)
    conv1 = tf.nn.relu(conv1)
    conv1 = tf.layers.conv2d( conv1,
                              filters=n_filters,
                              kernel_size=[1, 1],
                              padding="valid")

    # Apply Dropout (if is_training is False, dropout is not applied)
    drop_out1 = tf.layers.dropout( conv1,
                                 rate=drop_rate,
                                 training=tf_is_traing_pl,
                                 name="drop_out1")

    conv3 = tf.layers.batch_normalization(conv1)
    conv3 = tf.nn.relu(conv3)
    conv3 = tf.layers.conv2d( conv3,
                              filters=n_filters*2,
                              kernel_size=[3, 3],
                              padding="same")


    # Apply Dropout (if is_training is False, dropout is not applied)
    drop_out3 = tf.layers.dropout( conv3,
                                 rate=drop_rate,
                                 training=tf_is_traing_pl,
                                 name="drop_out3")


    drop_out3 = tf.concat([drop_out3,x], 3)

    return drop_out3

def ClassificationLayer(x, n_classes, n_filters, tf_is_traing_pl):

    conv = tf.layers.conv2d( x,
                            filters = n_filters*2,
                            kernel_size=[1,1])
    conv = tf.layers.batch_normalization(conv)
    conv = tf.nn.relu(conv)

    #maxpooling
    features = tf.reduce_max(conv, [1,2], name = "features")

    output = tf.layers.dense( features,
                        units = n_classes)

    output = tf.nn.relu( output, name = "prediction" )


    return output, features

def DenseNet(x, n_classes, n_filters, n_blocks, drop_rate, tf_is_traing_pl):
	# Define scope to reuse the variable

	outCBP = ConvBnPool(x, n_filters)
	outDense = outCBP

	for i in range(n_blocks):

		outDense = DenseBlock(outDense,i,n_filters,drop_rate, tf_is_traing_pl)

	logits, features = ClassificationLayer( outDense,n_classes, n_filters, tf_is_traing_pl )
	return logits,features



def checkRF( features, prediction, gt, estimators, p_split ):

    clf = RandomForestClassifier( n_estimators = estimators )

    first_bound = float(p_split/100)*features.shape[0]
    second_bound = features.shape[0]

    Xtrain = features[0:first_bound,:]
    Ytrain = prediction[0:first_bound]
    Xtest = features[first_bound:second_bound,:]
    #Ytest = features[first_bound:second_bound,:]

    clf.fit( Xtrain, Ytrain )
    predRFC = clf.predict( Xtest )

    gt = np.argmax( gt, axis=1 )

    RFeatFscore, RFeatFArray, RFeatPArray, RFeatRArray = evalMeasures( gt, predRFC )
    RFeatAcc = accuracy_score( gt,predRFC )

    return RFeatAcc, RFeatFscore, RFeatFArray, RFeatPArray, RFeatRArray

# 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]

#dataset path
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
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

#format data
train_y = getLabelFormat(train_y)

n_filters = 32
n_blocks = 6
learning_rate = 0.001
g_path = 'dataset/'

directory = g_path+'DenseNet%s%d_%d/'%(tag_band, 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")



drop_rate = 0.2 # Dropout, percentage of dropped input units
#tf_is_traing_pl = tf.Variable( True )
tf_is_traing_pl = tf.placeholder(tf.bool, shape=(), name="is_training")


# It is better to use 2 placeholders, to avoid to load all data into memory,
# and avoid the 2Gb restriction length of a tensor.
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 = DenseNet(x, n_classes,n_filters, n_blocks, drop_rate, tf_is_traing_pl )

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, tf_is_traing_pl:True})
        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()