猫狗大战 Tensorflow 实现

import os

import pathlib

import shutil

import random

import tensorflow as tf

#%%

tf.logging.set_verbosity(tf.logging.INFO)

os.environ["CUDA_VISIBLE_DEVICES"] = '0' #use GPU with ID=0

config = tf.ConfigProto()

config.gpu_options.per_process_gpu_memory_fraction = 0.5 # maximun alloc gpu50% of MEM

config.gpu_options.allow_growth = True #allocate dynamically

sess = tf.Session(config = config)

def organize_datasets(src_train_path, dest_train_path, n= 25000, ratio=0.2):

    src_path = pathlib.Path(src_train_path)

    # get all jpg files in this src_path path

    files = list(src_path.glob('*.jpg'))

    random.shuffle(files)   

    files = files[:n]


    n = int(len(files) * ratio)

    val, train = files[:n], files[n:]


    # remove old training folders

    shutil.rmtree(dest_train_path, True)

    print('{} removed'.format(dest_train_path))


    # create new training folders

    for c in ['dogs', 'cats']:

        os.makedirs('{}/train/{}/'.format(dest_train_path, c))

        os.makedirs('{}/validation/{}/'.format(dest_train_path, c))

    print('folders created !')

    # determine the picture's name is cat or dog

    for t in train:

        if 'cat' in t.name:

            shutil.copy2(t, os.path.join(dest_train_path, 'train', 'cats'))

        else:

            shutil.copy2(t, os.path.join(dest_train_path, 'train', 'dogs'))


    for v in val:

        if 'cat' in v.name:

            shutil.copy2(v, os.path.join(dest_train_path, 'validation', 'cats'))

        else:

            shutil.copy2(v, os.path.join(dest_train_path, 'validation', 'dogs'))

    print('Data copied!')   


src_train = './dog_cat/train'

training_path = './dog_cat_data'

organize_datasets(src_train, training_path)

#%%

def cnn_model_fn(features, labels, mode):

    """Model function for CNN."""

    # Input Layer

    input_layer = tf.reshape(features, [-1, 150, 150, 3])


    # Convolutional Layer #1

    conv1 = tf.layers.conv2d(

            inputs=input_layer,

            filters=32,

            kernel_size=[5, 5],

            padding="same",

            activation=tf.nn.relu)


    # Pooling Layer #1

    pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)


    # Convolutional Layer #2 and Pooling Layer #2

    conv2 = tf.layers.conv2d(

            inputs=pool1,

            filters=64,

            kernel_size=[5, 5],

            padding="same",

            activation=tf.nn.relu)


    pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)


    # Dense Layer

    pool2_flat = tf.reshape(pool2, [-1, 37 * 37 * 64])

    dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu)

    dropout = tf.layers.dropout(inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN)


    # Logits Layer

    logits = tf.layers.dense(inputs=dropout, units=2)

    predictions = {

            # Generate predictions (for PREDICT and EVAL mode)

            "classes": tf.argmax(input=logits, axis=1),

            # Add `softmax_tensor` to the graph. It is used for PREDICT and by the

            # `logging_hook`.

            "probabilities": tf.nn.softmax(logits, name="softmax_tensor")

            }   

    print('predictions:', predictions)


    if mode == tf.estimator.ModeKeys.PREDICT:

        return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)

    # Calculate Loss (for both TRAIN and EVAL modes)

    onehot_labels = tf.one_hot(indices=tf.cast(labels, tf.int32), depth=2)

    loss = tf.losses.softmax_cross_entropy(

            onehot_labels=onehot_labels, logits=logits)

    # Configure the Training Op (for TRAIN mode)

    if mode == tf.estimator.ModeKeys.TRAIN:

        starter_learning_rate = 0.001

        global_step = tf.Variable(0, trainable=False)

        learning_rate = tf.train.exponential_decay(starter_learning_rate,

                                                  global_step,

                                                  decay_steps=500,

                                                  decay_rate=0.9,

                                                  staircase=True)

        optimizer = tf.train.AdagradOptimizer(learning_rate=learning_rate)

        train_op = optimizer.minimize(loss=loss, global_step=tf.train.get_global_step())


        return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)

    # Add evaluation metrics (for EVAL mode)

    eval_metric_ops = {"accuracy": tf.metrics.accuracy(labels=labels, predictions=predictions["classes"])}


    return tf.estimator.EstimatorSpec(mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)   

#%%

def get_files(dogs, cats):       

    dogs_path = pathlib.Path(dogs)

    cats_path = pathlib.Path(cats)


    dogs_list = list(dogs_path.glob('*.jpg'))

    cats_list = list(cats_path.glob('*.jpg'))

    file_list_add = dogs_list + cats_list

    random.shuffle(file_list_add)

    file_list = [str(i) for i in file_list_add] 


    label_list = []

    for t in file_list_add:

        if 'cat' in t.name:

            label_list.append(0)

        else:

            label_list.append(1)


    return file_list, label_list

dogs_train = './dog_cat_data/train/dogs'

cats_train = './dog_cat_data/train/cats'

train_file_list, train_label_list = get_files(dogs_train, cats_train)

dogs_validation = './dog_cat_data/validation/dogs'

cats_validation = './dog_cat_data/validation/cats'

validation_file_list, validation_label_list = get_files(dogs_validation, cats_validation)

def _parse_function(filename, label):

    image_H = image_W = 150

    image_string = tf.read_file(filename)

    image_decoded = tf.image.decode_jpeg(image_string) 

    image_resized = tf.image.resize_images(image_decoded, [image_H, image_W])

    img_std = tf.image.per_image_standardization(image_resized)

    return img_std, label

#%%

batch_size = 50

def train_input_fn():

    '''

    運行dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))後,dataset的一個元素是(filename, label)。

    filename是圖片的文件名,label是圖片對應的標籤。


    之後通過map,將filename對應的圖片讀入,並縮放為150x150的大小。此時dataset中的一個元素是(image_resized, label)。   

    dataset.shuffle(buffersize=1000).batch(32).repeat()的功能是:在每個epoch內將圖片打亂組成大小為32的batch,無限重複。


    最後,dataset中的一個元素是(image_std_batch, label_batch)

    image_std_batch(32, 150, 150, 3),而label_batch的形狀為(32, ),接下來我們就可以用這兩個Tensor來建立模型了。


    '''

    global train_file_list

    global train_label_list

    global num_epochs

    global batch_size   


    filenames = tf.constant(train_file_list)

    train_lables = tf.constant(train_label_list) 


    dataset = tf.data.Dataset.from_tensor_slices((filenames , train_lables))

    dataset = dataset.map(_parse_function)

    dataset = dataset.shuffle(buffer_size=1000)


    dataset = dataset.repeat()

    dataset = dataset.batch(batch_size)


    iterator = dataset.make_one_shot_iterator()

    features, labels = iterator.get_next()


    return features, labels

def validation_input_fn():

    global validation_file_list

    global validation_label_list

    global num_epochs

    global batch_size


    filenames = tf.constant(validation_file_list)

    validation_lables = tf.constant(validation_label_list)


    dataset = tf.data.Dataset.from_tensor_slices((filenames , validation_lables))

    dataset = dataset.map(_parse_function)

    dataset = dataset.shuffle(buffer_size=1000)


    #dataset = dataset.repeat()

    dataset = dataset.batch(batch_size)

    iterator = dataset.make_one_shot_iterator()

    validation, v_lables = iterator.get_next()


    return validation, v_lables

#%% Get training and eval data

# Create the Estimator

dog_cat_classifier = tf.estimator.Estimator( model_fn=cnn_model_fn, model_dir="./cnn_model_2")

# Set up logging for predictions

tensors_to_log = {"probabilities": "softmax_tensor"}

logging_hook = tf.train.LoggingTensorHook(tensors=tensors_to_log, every_n_iter=50)


# Train the model

#train_result = dog_cat_classifier.train( input_fn=train_input_fn, steps=3000, hooks=[logging_hook])

train_result = dog_cat_classifier.train( input_fn=train_input_fn, steps=3000)

print('train_result:', train_result)

# Evaluate the model and print results

#eval_results = dog_cat_classifier.evaluate(input_fn=validation_input_fn, steps=100)

eval_results = dog_cat_classifier.evaluate(input_fn=validation_input_fn)

print('eval_results:', eval_results) 

print('----------ALL Done!----------')

你可能感兴趣的:(猫狗大战 Tensorflow 实现)