def main(mode='train', gpu='0'):
    os.environ["CUDA_VISIBLE_DEVICES"]=gpu

    data = data_utils.ISIC2018_data(4)
    num_classes = 7

    # extract feature
    base_model = resnet50.ResNet50(weights='imagenet', include_top=False, pooling='avg', input_shape=(224,224,3))

    images_feature = []
    y_list = []
    with tf.Session() as sess:
        try:
            if mode == 'train_evaluation':
                x, y = data.read_record('train_evaluation')
                outputname = 'images_feature_with_labels_from_vgg16_train'
            elif mode == 'evaluate':
                x, y = data.read_record('evaluate')
                outputname = 'images_feature_with_labels_from_vgg16_evaluate'

            sess.run(tf.global_variables_initializer())
            cnt = 0
            while True:
                x_, y_ = sess.run([x, y])
                features = base_model.predict(x_)
                y_list.append((np.argmax(y_, axis=1)))
                #print(features.shape)
                images_feature.append(features)
                cnt += 1
                print('batch %d' % cnt)
        except tf.errors.OutOfRangeError:
            print('load finish labels')

    x_y = [images_feature, y_list]
    np.save(outputname, x_y)
def test_record():
    timer_ = timer.timer()
    ISIC2018_data_ = data_utils.ISIC2018_data()
    ISIC2018_data_.set_valid_index(4)
    iter_x, iter_y = ISIC2018_data_.get_inputs()
    load(iter_x, iter_y, ISIC2018_data_.extra_init)
    #load(*(ISIC2018_data_.get_train))
    #load(*(ISIC2018_data_.get_valid))
    timer_.get_duration()
def main(mode='train', gpu='0'):
    os.environ["CUDA_VISIBLE_DEVICES"] = gpu

    data = data_utils.ISIC2018_data(4)
    num_classes = 7

    # using resnet50
    base_model = resnet50.ResNet50(weights='imagenet',
                                   include_top=False,
                                   pooling='avg',
                                   input_shape=(224, 224, 3))

    # using resnet152
    #base_model = resnet152.ResNet152(weights='imagenet', include_top=False, pooling='avg', input_shape=(224,224,3))

    # using resnet152
    #base_model = resnet.ResNet152(weights='imagenet', include_top=False, pooling='avg', input_shape=(224,224,3))

    # using densenet
    #base_model = densenet.DenseNet201(weights='imagenet', include_top=False, pooling='avg', input_shape=(224,224,3))

    # inception v3
    #base_model = inception_v3.InceptionV3(weights='imagenet', include_top=False, pooling='avg', input_shape=(224,224,3))

    model = models.Sequential()

    model.add(base_model)
    # remove fully connected according to paper
    model.add(layers.Dense(1024, activation='relu'))
    model.add(layers.Dense(7, activation='relu'))
    #model.add(layers.Dense(1000, activation='relu'))
    model.add(layers.Dense(num_classes, activation='softmax', name='fc7'))
    base_model.trainable = False
    #model.compile(loss=median_weight_class_loss,
    #model.compile(loss='categorical_crossentropy',
    model.compile(loss=focal_loss,
                  optimizer=SGD(lr=0.001, momentum=0.9, decay=0.0),
                  metrics=[metrics.categorical_accuracy])

    #model_dir = '/home/jiaxin/myGithub/Reverse_CISI_Classification/src/densenet201_keras_pre/model_fc'
    #model_dir = '/home/jiaxin/myGithub/Reverse_CISI_Classification/src/resnet152_keras_pre/model_fc'
    #model_dir = '/home/jiaxin/myGithub/Reverse_CISI_Classification/src/resnet152_keras_pre/model_fc'
    #model_dir = '/home/jiaxin/myGithub/Reverse_CISI_Classification/src/resnet50_keras_pre/model_cw'
    model_dir = '/home/jiaxin/myGithub/Reverse_CISI_Classification/src/resnet50_keras_pre/model_fc_repeat'
    #model_dir = '/home/jiaxin/myGithub/Reverse_CISI_Classification/src/resnet50_keras_pre/model_fc_3_m'
    #model_dir = '/home/jiaxin/myGithub/Reverse_CISI_Classification/src/resnet50_keras_pre/model_fc_cw_nor'
    os.makedirs(model_dir, exist_ok=True)
    print('model_dir', model_dir)
    est = tf.keras.estimator.model_to_estimator(keras_model=model,
                                                model_dir=model_dir)

    train_spec = tf.estimator.TrainSpec(
        input_fn=lambda: data.read_record('train'))
    eval_spec = tf.estimator.EvalSpec(
        input_fn=lambda: data.read_record('train_evaluation'))

    if mode == 'train':
        tf.estimator.train_and_evaluate(est, train_spec, eval_spec)
    elif mode == 'evaluate':
        with tf.Session() as sess:
            try:
                x, y = data.read_record('evaluate')
                sess.run(tf.global_variables_initializer())
                y_list = []
                while True:
                    _, y_ = sess.run([x, y])
                    y_list.extend((np.argmax(y_, axis=1)))
            except tf.errors.OutOfRangeError:
                print('load finish labels')

            # test
            #cnt = 0
            #while True:
            #    try:
            #        x, y = data.read_record('evaluate')
            #        sess.run(tf.global_variables_initializer())
            #        y_list_ = []
            #        while True:
            #            _, y_ = sess.run([x, y])
            #            y_list_.extend((np.argmax(y_, axis=1)))
            #    except tf.errors.OutOfRangeError:
            #        cnt += 1
            #        print(cnt)
            #        assert all([a==b for a, b in zip(y_list, y_list_)])

            pp = []
            while True:
                predictions = est.predict(
                    input_fn=lambda: data.read_record('evaluate'))
                predictions_list = []
                for pre in predictions:
                    p = np.argmax(pre['fc7'])
                    predictions_list.append(p)

                statistics_ = statistics.statistics(hps, mode='evaluate')
                statistics_.add_labels_predictions(predictions_list, y_list)
                statistics_.get_acc_normal()
                result = statistics_.get_acc_imbalanced()
                np.save('predictions_label_fc_repeat',
                        [predictions_list, y_list])
                #np.save('predictions_label_fc_3_m', [predictions_list, y_list])
                #np.save('predictions_label_fc_without_fulcon', [predictions_list, y_list])
                pp.append(result)

                print('---')
                np.save('result_fc_repeat', pp)
                #np.save('result_fc_3_m', pp)
                #np.save('result_fc_without_fulcon', pp)
                time.sleep(120)
def train(hps, val_index):
    """Train model for a number of steps"""

    # select dataset
    with tf.device(FLAGS.device_cpu):
        if FLAGS.data == 'ISIC2018':
            data = data_utils.ISIC2018_data()
        else:
            tf.logging.info('Give dataset name')
            sys.exit(-1)

        # get data information: width, height from data_utils [224, 224, 3]
        width, height, channel = data.get_shape()
        # get data information: owidth, oheight from data_utils [400, 300, 3]
        owidth, oheight, ochannel = data.get_origin_shape()

        save_prefix = FLAGS.save_prefix.format(FLAGS.batch_size, oheight,
                                               owidth)
        parameters = os.path.join(save_prefix, FLAGS.parameters)
        logdir = os.path.join(save_prefix, FLAGS.logdir)

        psuffix = 'model_' + FLAGS.mode + '_' + FLAGS.model + '_' + str(
            FLAGS.with_memory) + '_' + str(val_index)
        lsuffix = 'log_' + FLAGS.mode + '_' + FLAGS.model + '_' + str(
            FLAGS.with_memory) + '_' + str(val_index)
        train_model = os.path.join(parameters, psuffix)
        train_graph = os.path.join(logdir, lsuffix)

        tf.logging.info('train model %s' % train_model)
        tf.logging.info('train graph %s' % train_graph)

        if FLAGS.remove:
            if tf.gfile.Exists(train_model):
                tf.gfile.DeleteRecursively(train_model)
                tf.gfile.MakeDirs(train_model)
            if tf.gfile.Exists(train_graph):
                tf.gfile.DeleteRecursively(train_graph)
                tf.gfile.MakeDirs(train_graph)
            sepoch = 0
        else:
            ckpt = tf.train.get_checkpoint_state(train_model)
            if ckpt and ckpt.model_checkpoint_path:
                sepoch = int(
                    ckpt.model_checkpoint_path.split('/')[-1].split('-')
                    [1]) + 1
                model_path = ckpt.model_checkpoint_path
                tf.logging.info(model_path)
                tf.logging.info('sepoch is %d' % sepoch)
            else:
                sepoch = 0
                tf.logging.info('Fail to restore, start from %d' % sepoch)

        if FLAGS.with_memory:
            ckpt = tf.train.get_checkpoint_state(
                FLAGS.checkpoint_dir.format(FLAGS.batch_size, data.nHei,
                                            data.nWid, val_index))
            if ckpt and ckpt.model_checkpoint_path:
                all_model_checkpoint_paths = ckpt.all_model_checkpoint_paths
                model_path_template = all_model_checkpoint_paths[0].split(
                    '-')[0]
                model_path = model_path_template + '-99'
                sepoch = 0
                tf.logging.info(model_path)
                tf.logging.info('sepoch is %d' % sepoch)
            else:
                tf.logging.info('Fail to restore for memory')
                sys.exit(-1)

    gpu = FLAGS.device_gpu + str(0)
    with tf.device(gpu):
        with tf.Graph().as_default() as g:
            # validation groups
            data.set_valid_index(val_index)
            # define variables
            xs = tf.placeholder(tf.float32, [None, height, width, channel],
                                name='xs')
            ys = tf.placeholder(tf.float32, [None, hps.num_classes], name='ys')
            trainable = tf.placeholder(tf.bool, name='trainable')
            learning_rate = tf.placeholder(tf.float32, [],
                                           name='learning_rate')
            #train_mode = tf.placeholder(tf.bool)

            # using model
            selected_model = model.get_model(hps, xs, ys, learning_rate,
                                             trainable)
            selected_model.build_graph()

            # TODO Use memory
            if FLAGS.with_memory:
                memory_layer = memory.Memory(hps, key_dim=FLAGS.feature_size)
                train_op = memory_layer.query_and_make_update(
                    model.feature_map, ys)
                summaries = tf.summary.merge_all()
                predictions = memory_layer.query(model.feature_map)
                get_restored_variables = tf.get_collection(
                    tf.GraphKeys.GLOBAL_VARIABLES, scope='extract_feature_map')
                saver = tf.train.Saver(get_restored_variables,
                                       max_to_keep=FLAGS.epoch)
                #init_op = tf.variables_initializer([memory_layer.mem_keys, memory_layer.mem_vals, memory_layer.mem_age, memory_layer.query_proj, memory_layer.threshold], name='init_op')
            else:
                # default to use this branch now,
                # model provided at least train_op, summaries and predictions
                train_op = selected_model.train_op
                summaries = selected_model.summaries
                predictions = selected_model.predictions
                saver = tf.train.Saver(max_to_keep=26)
                init_op = tf.global_variables_initializer()

            config = tf.ConfigProto(
                log_device_placement=FLAGS.log_device_placement)
            config.gpu_options.allow_growth = True

            summary_writer = tf.summary.FileWriter(train_graph, g)

            step = 0
            with tf.Session(config=config) as sess:
                if FLAGS.with_memory == False and (FLAGS.remove == True
                                                   or sepoch == 0):
                    sess.run(init)
                else:
                    sess.run(init)
                    saver.restore(sess, model_path)

                # training for (FALGS.epoch-sepoch)
                for i in range(sepoch, FLAGS.epoch):
                    # init iterator for dataset
                    sess.run(data.extra_init)
                    tf.logging.info("%s: Epoch %d, val_index is %d" %
                                    (datetime.now(), i, val_index))
                    # set learning rate
                    if i < 40:
                        learning_rate_ = 0.1
                    elif i < 90:
                        learning_rate_ = 0.01
                    elif i < 150:
                        learning_rate_ = 0.001
                    else:
                        learning_rate_ = 0.0001

                    batch_x_iter, batch_y_iter, path_iter = data.get_inputs()
                    try:
                        j = 0
                        while True:
                            batch_x, batch_y, path = sess.run(
                                [batch_x_iter, batch_y_iter, path_iter])
                            _, summary_op_ = sess.run(
                                [train_op, summaries],
                                feed_dict={
                                    xs: batch_x,
                                    ys: batch_y,
                                    learning_rate: learning_rate_,
                                    trainable: True
                                })
                            summary_writer.add_summary(summary_op_, step)
                            step += 1
                            j += 1
                    except tf.errors.OutOfRangeError:
                        tf.logging.info("%s: Epoch %d complete after iter %d" %
                                        (datetime.now(), i, j))

                    # Val
                    if i % 5 == FLAGS.valid_frequency:
                        batch_x_iter, batch_y_iter, path_iter = data.get_train(
                        )
                        try:
                            while True:
                                batch_x, batch_y, path = sess.run(
                                    [batch_x_iter, batch_y_iter, path_iter])
                                predictions_ = sess.run(predictions,
                                                        feed_dict={
                                                            xs: batch_x,
                                                            ys: batch_y,
                                                            trainable: False
                                                        })
                                statistics_.add_labels_predictions(
                                    batch_y, predictions_, path)
                        except tf.errors.OutOfRangeError:
                            tf.logging.info("%s: Epoch %d training complete " %
                                            (datetime.now(), i))
                            statistics_.get_print_precision()
                            acc_normal = statistics_.gey_acc_normal()
                            tf.logging.info(
                                "%s: Epoch %d complete acc_normal is %f" %
                                (datetime.now(), i, acc_normal))
                            acc_imbalanced = statistics_.get_acc_imbalanced()
                            tf.logging.info(
                                "%s: Epoch %d complete acc_imbalanced is %f" %
                                (datetime.now(), i, acc_imbalanced))

                        saver.save(sess,
                                   os.path.join(train_model, 'model'),
                                   global_step=i + 1)
def evaluate(hps):
    """evaluate"""
    sec = 150 * 6
    tf.logging.info('Evaluate every %ds' % sec)

    # select dataset
    with tf.device(FLAGS.device_cpu):
        if FLAGS.data == 'ISIC2018':
            data = data_utils.ISIC2018_data()
        else:
            tf.logging.info('Give dataset name')
            sys.exit(-1)

        # get data information: width, height from data_utils [224, 224, 3]
        width, height, channel = data.get_shape()
        # get data information: owidth, oheight from data_utils [400, 300, 3]
        owidth, oheight, ochannel = data.get_origin_shape()

        save_prefix = FLAGS.save_prefix.format(FLAGS.batch_size, oheight,
                                               owidth)
        checkpoint_dir = FLAGS.checkpoint_dir.format(FLAGS.batch_size, oheight,
                                                     owidth)
        checkpoint_dir = os.path.join(save_prefix, checkpoint_dir)

    gpu = FLAGS.device_gpu + str(0)
    config = tf.ConfigProto(log_device_placement=FLAGS.log_device_placement)
    config.gpu_options.allow_growth = True
    while True:
        with tf.device(gpu):
            with tf.Session(config=config) as sess:
                # get graph
                ckpt = tf.train.get_checkpoint_state(checkpoint_dir)
                if ckpt and ckpt.model_checkpoint_path:
                    epoch = int(ckpt.model_checkpoint_path.split('-')[1])
                    model_path = ckpt.model_checkpoint_path
                    graph_path = os.path.join(FLAGS.checkpoint_dir,
                                              model_path + '.meta')
                    tf.logging.info('Restore graph from %s, Epoch is %d' %
                                    (graph_path, epoch))
                else:
                    tf.logging.info('Fail to restore, Sleep for %d' % sec)
                    time.sleep(sec)
                    continue

                statistics_ = statistics.statistics(hp, epoch, mode='evaluate')

                # load graph from checkpoint and load variable
                saver = tf.train.import_meta_graph(graph_path)
                saver.restore(sess, model_path)

                # get desirable variables
                summaries = tf.get_collection(tf.GraphKeys.SUMMARIES)[0]
                predictions = tf.get_collection('predictions')[0]
                train_op = tf.get_collction('train_op')[0]
                trainable = tf.get_collection('trainable')[0]
                xs = tf.get_collection('xs')[0]
                ys = tf.get_collection('ys')[0]
                #summaries = tf.get_tensor_by_name(summaries+':0')
                #predictions = tf.get_tensor_by_name('predictions:0')
                #train_op = tf.get_tensor_by_name('train_op:0')

                batch_x_iter, batch_y_iter, path_iter = data.get_valid()
                try:
                    while True:
                        batch_x, batch_y, path = sess.run(
                            [batch_x_iter, batch_y_iter, path_iter])
                        predictions_ = sess.run(predictions,
                                                feed_dict={
                                                    xs: batches,
                                                    ys: batch_y,
                                                    trainable: False
                                                })
                        statistics_.add_labels_predictions(
                            batch_y, predictions_, path)
                except tf.errors.OutOfRangeError:
                    tf.logging.info("%s: Epoch %d evaluation complete " %
                                    (datetime.now(), i))
                    statistics_.get_print_precision()
                    acc_normal = statistics_.gey_acc_normal()
                    tf.logging.info("%s: Epoch %d complete acc_normal is %f" %
                                    (datetime.now(), i, acc_normal))
                    acc_imbalanced = statistics_.get_acc_imbalanced()
                    tf.logging.info(
                        "%s: Epoch %d complete acc_imbalanced is %f" %
                        (datetime.now(), i, acc_imbalanced))

                evaluation_detail = os.path.join(save_prefix,
                                                 FLAGS.evaluation_detail)
                statistics_.save_triples(evaluation_detail)

                time.sleep(sec)