<jupyter_start><jupyter_text>Download the datset.  The orginal dataset can be downloaded from https://github.com/Horea94/Fruit-Images-Dataset Reference: <NAME>, <NAME>, Fruit recognition from images using deep learning, Acta Univ. Sapientiae, Informatica Vol. 10, Issue 1, pp. 26-42, 2018.<jupyter_code>!wget https://www.dropbox.com/s/l1525goi53teden/fruits-360.zip?dl=0
!mv fruits-360.zip\?dl\=0 fruits-360.zip
!unzip fruits-360.zip
!rm fruits-360.zip
# dimensions of our images.
img_width, img_height = 224, 224 
train_data_dir = './train/'
validation_data_dir = './valid/'
nb_train_samples = 31688
nb_validation_samples = 10657
batch_size = 64
train_datagen = ImageDataGenerator(
    rescale=1. / 255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_height, img_width),
    batch_size=batch_size,
    class_mode='categorical')

validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_height, img_width),
    batch_size=batch_size,
    class_mode='categorical')<jupyter_output>Found 33125 images belonging to 81 classes.
Found 8197 images belonging to 81 classes.<jupyter_text>Alternative way to to split train data folder into train and validation is given below. This is useful when you just have two folders for Train and Test.<jupyter_code># total_datagen = ImageDataGenerator(
#     rescale=1. / 255,
#     shear_range=0.2,
#     zoom_range=0.2,
#     horizontal_flip=True,
#     validation_split=0.2)

# test_datagen = ImageDataGenerator(rescale=1. / 255)
# train_generator = total_datagen.flow_from_directory(
#     train_data_dir,
#     target_size=(img_height, img_width),
#     batch_size=batch_size,
#     class_mode='categorical',
#     subset="training")

# validation_generator = total_datagen.flow_from_directory(
#     validation_data_dir,
#     target_size=(img_height, img_width),
#     batch_size=batch_size,
#     class_mode='categorical',
#      subset="validation")<jupyter_output><empty_output><jupyter_text>Create the ResNet50 Model for transfer learning<jupyter_code>inception_base = applications.ResNet50(weights='imagenet', include_top=False)<jupyter_output>/anaconda/envs/py35/lib/python3.5/site-packages/keras_applications/resnet50.py:263: UserWarning: The output shape of `ResNet50(include_top=False)` has been changed since Keras 2.2.0.
  warnings.warn('The output shape of `ResNet50(include_top=False)` '<jupyter_text>We load the pre-trained ResNet50 network from disk. Do notice how we have included the parameter include_top=False – supplying this value indicates  that the final fully- connected layers should not be included in the architecture.  Therefore, when forward propagating an image through the network, we’ll obtain the feature values after the final POOL layer rather than the probabilities produced by  the softmax classifier in the FC layers.<jupyter_code>x = inception_base.output
x = GlobalAveragePooling2D()(x)
x = Dense(512, activation='relu')(x)
predictions = Dense(81, activation='softmax')(x)
inception_transfer = Model(inputs=inception_base.input, outputs=predictions)
inception_transfer.compile(loss='categorical_crossentropy',
              optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
              metrics=['accuracy'])
inception_transfer.summary()
inception_transfer.fit_generator(
    train_generator,
    steps_per_epoch=33125 // 64,
    epochs=5, shuffle = True, verbose = 1, 
    max_queue_size=10,
    validation_data=validation_generator,
	validation_steps=8197 // 64)<jupyter_output><empty_output><jupyter_text>What does the Network see?<jupyter_code>def deprocess_image(x):
    # normalize tensor: center on 0., ensure std is 0.1
    x -= x.mean()
    x /= (x.std() + K.epsilon())
    x *= 0.1

    # clip to [0, 1]
    x += 0.5
    x = np.clip(x, 0, 1)

    # convert to RGB array
    x *= 255
    if K.image_data_format() == 'channels_first':
        x = x.transpose((1, 2, 0))
    x = np.clip(x, 0, 255).astype('uint8')
    return x
def normalize(x):
    # utility function to normalize a tensor by its L2 norm
    return x / (K.sqrt(K.mean(K.square(x))) + K.epsilon())
input_img = inception_transfer.input
layer_dict = dict([(layer.name, layer) for layer in inception_transfer.layers[1:]])

layer_name = 'res5b_branch2a'
kept_filters = []
for filter_index in range(200):
    # we only scan through the first 200 filters,
    # but there are actually 512 of them
    print('Processing filter %d' % filter_index)
    start_time = time.time()

    # we build a loss function that maximizes the activation
    # of the nth filter of the layer considered
    layer_output = layer_dict[layer_name].output
    if K.image_data_format() == 'channels_first':
        loss = K.mean(layer_output[:, filter_index, :, :])
    else:
        loss = K.mean(layer_output[:, :, :, filter_index])

    # we compute the gradient of the input picture wrt this loss
    grads = K.gradients(loss, input_img)[0]

    # normalization trick: we normalize the gradient
    grads = normalize(grads)

    # this function returns the loss and grads given the input picture
    iterate = K.function([input_img], [loss, grads])

    # step size for gradient ascent
    step = 1.

    # we start from a gray image with some random noise
    if K.image_data_format() == 'channels_first':
        input_img_data = np.random.random((1, 3, img_width, img_height))
    else:
        input_img_data = np.random.random((1, img_width, img_height, 3))
    input_img_data = (input_img_data - 0.5) * 20 + 128

    # we run gradient ascent for 20 steps
    for i in range(20):
        loss_value, grads_value = iterate([input_img_data])
        input_img_data += grads_value * step

        print('Current loss value:', loss_value)
        if loss_value <= 0.:
            # some filters get stuck to 0, we can skip them
            break

    # decode the resulting input image
    if loss_value > 0:
        img = deprocess_image(input_img_data[0])
        kept_filters.append((img, loss_value))
    end_time = time.time()
    print('Filter %d processed in %ds' % (filter_index, end_time - start_time))

# we will stich the best 64 filters on a 8 x 8 grid.
n = 5

# the filters that have the highest loss are assumed to be better-looking.
# we will only keep the top 64 filters.
kept_filters.sort(key=lambda x: x[1], reverse=True)
kept_filters = kept_filters[:n * n]

# build a black picture with enough space for
# our 8 x 8 filters of size 128 x 128, with a 5px margin in between
margin = 5
width = n * img_width + (n - 1) * margin
height = n * img_height + (n - 1) * margin
stitched_filters = np.zeros((width, height, 3))

# fill the picture with our saved filters
for i in range(n):
    for j in range(n):
        print(i,j)
        img, loss = kept_filters[i * n + j]
        width_margin = (img_width + margin) * i
        height_margin = (img_height + margin) * j
        stitched_filters[
            width_margin: width_margin + img_width,
            height_margin: height_margin + img_height, :] = img

# save the result to disk
save_img('stitched_filters_%dx%d.png' % (n, n), stitched_filters)
??applications.ResNet50<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10385878489326765, 'fraction_numerical': 0.030240831964969895, 'mean_word_length': 3.921885521885522, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 22, 'https://': 2, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '432151', 'license': 'MIT', 'n_tokens_mistral': 2543, 'n_tokens_neox': 2358, 'n_words': 664, 'path': '01-October-2018/Fruits-Visualize Layers.ipynb', 'repo_name': 'aarthiKarthik/deeplearning-meetup', 'size': '7321'}