import numpy as np
    import glob
    import cv2
    import matplotlib.pyplot as plt

    from sklearn.preprocessing import LabelBinarizer
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import accuracy_score

    import keras
    from keras.models import Sequential, load_model
    from keras.layers import Dense, Dropout, Activation, Flatten, Conv2D, MaxPooling2D, Lambda, Cropping2D
    from keras.utils import np_utils
    from keras import optimizers
    from keras.callbacks import EarlyStopping

    SEED = 2017


    # Data can be downloaded at http://download.tensorflow.org/example_images/flower_photos.tgz


    # Specify data directory and extract all file names
    DATA_DIR = 'Data/'
    images = glob.glob(DATA_DIR + "flower_photos/*/*.jpg")
    # Extract labels from file names
    labels = [x.split('/')[3] for x in images]


    unique_labels = set(labels)
    plt.figure(figsize=(15, 15))
    i = 1
    for label in unique_labels:
        image = images[labels.index(label)]
        img = cv2.imread(image)
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        plt.subplot(5, 5, i)
        plt.title("{0} ({1})".format(label, labels.count(label)))
        i += 1
        _ = plt.imshow(img)
    plt.show()


    encoder = LabelBinarizer()
    encoder.fit(labels)
    y = encoder.transform(labels).astype(float)


    X_train, X_val, y_train , y_val = train_test_split(images, y, test_size=0.2, random_state=SEED)


    # Define architecture
    model = Sequential()
    model.add(Lambda(lambda x: (x / 255.) - 0.5, input_shape=(100, 100, 3)))
    model.add(Conv2D(16, (5, 5), activation='relu', padding='same'))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(Dropout(0.75))
    model.add(Conv2D(32, (5, 5), activation='relu', padding='same'))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(Dropout(0.75))
    model.add(Conv2D(64, (3, 3), activation='relu', padding='same'))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(Dropout(0.75))
    model.add(Flatten())
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.75))
    model.add(Dense(5, activation='softmax'))

    # Define optimizer and compile
    opt = optimizers.Adam()
    model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])


    img_rows = img_cols = 100
    img_channels = 3

    def batchgen(x, y, batch_size, transform=False):
        # Create empty numpy arrays
        images = np.zeros((batch_size, img_rows, img_cols, img_channels))
        class_id = np.zeros((batch_size, len(y[0])))

        while 1:
            for n in range(batch_size):
                i = np.random.randint(len(x))
                x_ = cv2.imread(x[i])
                x_ = cv2.cvtColor(x_, cv2.COLOR_BGR2RGB)
                # The images have different sizes, we transform all to 100x100 pixels
                x_ = cv2.resize(x_, (100, 100)) 
                images[n] = x_
                class_id[n] = y[i]
                yield images, class_id


    callbacks = [EarlyStopping(monitor='val_acc', patience=5)]


    len(X_val)


    batch_size = 256
    n_epochs = 100
    steps_per_epoch = len(X_train) // batch_size
    val_steps = len(X_val) // batch_size

    train_generator = batchgen(X_train, y_train, batch_size, True)
    val_generator = batchgen(X_val, y_val, batch_size, True)

    history = model.fit_generator(train_generator, 
                                   steps_per_epoch=steps_per_epoch, 
                                   epochs=n_epochs, 
                                   validation_data=val_generator,
                                   validation_steps=val_steps,
                                  callbacks=callbacks
                                 )


    plt.plot(history.history['acc'])
    plt.plot(history.history['val_acc'])
    plt.title('Model accuracy')
    plt.ylabel('accuracy')
    plt.xlabel('epochs')
    plt.legend(['train', 'validation'], loc='lower right')
    plt.show()


    test_generator = batchgen(X_val, y_val, 1, False)
    preds = model.predict_generator(test_generator, steps=len(X_val))

    y_val_ = [np.argmax(x) for x in y_val]
    y_preds = [np.argmax(x) for x in preds]
    accuracy_score(y_val_, y_preds)


    n_predictions = 5
    plt.figure(figsize=(15, 15))
    for i in range(n_predictions):

        plt.subplot(n_predictions, n_predictions, i+1)
        plt.title("{0} ({1})".format(list(set(labels))[np.argmax(preds[i])], 
                                     list(set(labels))[np.argmax(y_val[i])]))
        img = cv2.imread(X_val[i])
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        plt.axis('off')
        plt.imshow(img)
        plt.tight_layout() 
    plt.show()