<jupyter_start><jupyter_text>Metaparameters<jupyter_code>NB_EPOCH = 50
BATCH_SIZE = 16
VERBOSE = 1
VALIDATION_SPLIT = 0.2<jupyter_output><empty_output><jupyter_text>Data generator<jupyter_code>classes = {'Anomaly': 0, 'Bearded Seal': 1, 'Ringed Seal': 2, 'Polar Bear': 3, 'UNK Seal': 4}
def GetPartitionsAndLabels():
    df = pd.read_csv("{}/training.csv".format(dataPath))
    rowcount = int(df.shape[0])
    train_count = int(rowcount * (1 - VALIDATION_SPLIT))
    test_count = rowcount - train_count
    print ("Train: {} Validation: {}".format(train_count, test_count))
    
    ids = df["hotspot_id"].astype(str).values
   
    train = ids[:train_count]
    validation = ids[train_count:]
    
    print(train.shape)
    print(validation.shape)
    
    partitions = {}
    partitions['train'] = train
    partitions['validation'] = validation

    labels = {}
    for index, row in df.iterrows():
        label = 'Anomaly'
        if (row.hotspot_type == 'Animal'):
            label = row.species_id
            
        labels[str(row.hotspot_id)] = classes[label]
    
    return partitions, labels

partition, labels = GetPartitionsAndLabels()
def LoadImage(id):

    # Images are named <originalName>_HOTSPOT_ID.JPG
    # ID can be "1234" which Pandas converts to "1234.0" or "1234.99"
    if (id.endswith('.0')):
        id = id[:-2]

    imageMask = "{}/*HOTSPOT_{}.JPG".format(imgCropPath, id)
    imageFiles = glob(imageMask)
    assert len(imageFiles) == 1
    
    imageFile = imageFiles[0]
    image = Image.open(imageFile)
    image.thumbnail((224, 224), Image.ANTIALIAS)
    return np.array(image)   

LoadImage(partition['train'][0]).shape
# From https://stanford.edu/~shervine/blog/keras-how-to-generate-data-on-the-fly.html
class DataGenerator(Sequence):
    'Generates data for Keras'
    def __init__(self, list_IDs, labels, batch_size=32, dim=(224,224), n_channels=3,
                 n_classes=10, shuffle=True):
        'Initialization'
        self.dim = dim
        self.batch_size = batch_size
        self.labels = labels
        self.list_IDs = list_IDs
        self.n_channels = n_channels
        self.n_classes = n_classes
        self.shuffle = shuffle
        self.on_epoch_end()

    def __len__(self):
        'Denotes the number of batches per epoch'
        return int(np.floor(len(self.list_IDs) / self.batch_size))

    def __getitem__(self, index):
        'Generate one batch of data'
        # Generate indexes of the batch
        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]

        # Find list of IDs
        list_IDs_temp = [self.list_IDs[k] for k in indexes]

        # Generate data
        X, y = self.__data_generation(list_IDs_temp)

        return X, y

    def on_epoch_end(self):
        'Updates indexes after each epoch'
        self.indexes = np.arange(len(self.list_IDs))
        if self.shuffle == True:
            np.random.shuffle(self.indexes)

    def __data_generation(self, list_IDs_temp):
        'Generates data containing batch_size samples' # X : (n_samples, *dim, n_channels)
        # Initialization
        X = np.empty((self.batch_size, *self.dim, self.n_channels))
        y = np.empty((self.batch_size), dtype=int)

        # Generate data
        for i, ID in enumerate(list_IDs_temp):
            # Store sample
            X[i,] = LoadImage(ID)

            # Store class
            y[i] = self.labels[ID]

        return X, keras.utils.to_categorical(y, num_classes=self.n_classes)<jupyter_output><empty_output><jupyter_text>VGG16 model layout:<jupyter_code>def ShowLayers(base_model):
    for i, layer in enumerate(base_model.layers):
        print (i, layer.name, layer.output_shape)
original_model = VGG16(weights=None, include_top=True)
ShowLayers(original_model)<jupyter_output>0 input_1 (None, 224, 224, 3)
1 block1_conv1 (None, 224, 224, 64)
2 block1_conv2 (None, 224, 224, 64)
3 block1_pool (None, 112, 112, 64)
4 block2_conv1 (None, 112, 112, 128)
5 block2_conv2 (None, 112, 112, 128)
6 block2_pool (None, 56, 56, 128)
7 block3_conv1 (None, 56, 56, 256)
8 block3_conv2 (None, 56, 56, 256)
9 block3_conv3 (None, 56, 56, 256)
10 block3_pool (None, 28, 28, 256)
11 block4_conv1 (None, 28, 28, 512)
12 block4_conv2 (None, 28, 28, 512)
13 block4_conv3 (None, 28, 28, 512)
14 block4_pool (None, 14, 14, 512)
15 block5_conv1 (None, 14, 14, 512)
16 block5_conv2 (None, 14, 14, 512)
17 block5_conv3 (None, 14, 14, 512)
18 block5_pool (None, 7, 7, 512)
19 flatten (None, 25088)
20 fc1 (None, 4096)
21 fc2 (None, 4096)
22 predictions (None, 1000)<jupyter_text>Removing top and last 3 layers:<jupyter_code># Input = 512x512x3

# VGG16 size : 224x224x3
base_model = VGG16(weights='imagenet', include_top=False, input_shape=(224, 224, 3)) # Will download the 560MB trained model.

# Output = ['Anomaly' 'Bearded Seal' 'Ringed Seal' 'Polar Bear' 'UNK Seal']
x = base_model.output
x = Flatten(name='flatten')(x)
x = Dense(2048, name='fc1')(x)
x = Dense(2048, name='fc2')(x)
predictions = Dense(5, activation='softmax', name='predictions')(x)

model = Model(inputs=base_model.input, outputs=predictions)
ShowLayers(model)<jupyter_output>0 input_2 (None, 224, 224, 3)
1 block1_conv1 (None, 224, 224, 64)
2 block1_conv2 (None, 224, 224, 64)
3 block1_pool (None, 112, 112, 64)
4 block2_conv1 (None, 112, 112, 128)
5 block2_conv2 (None, 112, 112, 128)
6 block2_pool (None, 56, 56, 128)
7 block3_conv1 (None, 56, 56, 256)
8 block3_conv2 (None, 56, 56, 256)
9 block3_conv3 (None, 56, 56, 256)
10 block3_pool (None, 28, 28, 256)
11 block4_conv1 (None, 28, 28, 512)
12 block4_conv2 (None, 28, 28, 512)
13 block4_conv3 (None, 28, 28, 512)
14 block4_pool (None, 14, 14, 512)
15 block5_conv1 (None, 14, 14, 512)
16 block5_conv2 (None, 14, 14, 512)
17 block5_conv3 (None, 14, 14, 512)
18 block5_pool (None, 7, 7, 512)
19 flatten (None, 25088)
20 fc1 (None, 2048)
21 fc2 (None, 2048)
22 predictions (None, 5)<jupyter_text>Freeze VGG layers<jupyter_code>for layer in base_model.layers: layer.trainable = False<jupyter_output><empty_output><jupyter_text>Compile the model<jupyter_code>sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy', 'categorical_accuracy'])
model.summary()
params = {'dim': (224,224),
          'n_channels': 3,
          'batch_size': BATCH_SIZE,
          'n_classes': len(classes),
          'shuffle': True}

training_generator = DataGenerator(partition['train'], labels, **params)
validation_generator = DataGenerator(partition['validation'], labels, **params)

# Checpointing
checkpoint = ModelCheckpoint(filepath=os.path.join(modelPath, "model-{epoch:02d}.h5"))

# Train model on dataset
history = model.fit_generator(generator=training_generator,
                    validation_data=validation_generator,
                    use_multiprocessing=True,
                    workers=4,
                    epochs=NB_EPOCH,
                    callbacks=[checkpoint])
print ("Saving model to {}/{}.h5".format(modelPath, datetime.datetime.today().strftime('%Y-%m-%d')))
model.save("{}/{}.h5".format(modelPath, datetime.datetime.today().strftime('%Y-%m-%d')))
def ShowGraphs(history):
    # list all data in history
    print(history.history.keys())

    # summarize history for accuracy
    plt.plot(history.history['acc'])
    plt.plot(history.history['val_acc'])
    plt.title('model accuracy')
    plt.ylabel('accuracy')
    plt.xlabel('epoch')
    plt.legend(['train', 'test'], loc='upper left')
    plt.show()

    # summarize history for loss
    plt.plot(history.history['loss'])
    plt.plot(history.history['val_loss'])
    plt.title('model loss')
    plt.ylabel('loss')
    plt.xlabel('epoch')
    plt.legend(['train', 'test'], loc='upper left')
    plt.show()
    
ShowGraphs(history)<jupyter_output><empty_output><jupyter_text>Fine tune-optimization<jupyter_code>FREEZELAYERS = int(len(model.layers) / 2)
print ("We have {} layers. Freeze first {} layers".format(len(model.layers), FREEZELAYERS))


for layer in model.layers[:FREEZELAYERS]: layer.trainable = False
for layer in model.layers[FREEZELAYERS:]: layer.trainable = True
sgd = SGD(lr=0.0001, momentum=0.9)
model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy', 'categorical_accuracy'])
# Train model on dataset
history = model.fit_generator(generator=training_generator,
                    validation_data=validation_generator,
                    use_multiprocessing=True,
                    workers=4,
                    epochs=NB_EPOCH,
                    callbacks=[checkpoint])
ShowGraphs(history)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1340432920476907, 'fraction_numerical': 0.06609561291816182, 'mean_word_length': 3.711014176663032, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 28, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '653270', 'license': 'MIT', 'n_tokens_mistral': 3488, 'n_tokens_neox': 3022, 'n_words': 709, 'path': 'src/archive/hotspotdetection/VGG16transferlearning-Original.ipynb', 'repo_name': 'Bhaskers-Blu-Org2/arcticseals', 'size': '8639'}