<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 VGG
Step1:  Precompute convolutional output
Step2:  Fully convolutional net (FCN)
Since we're using a larger input, the output of the final convolutional layer is also larger. So, we probably don't want to put a dense layer in there - that would be a lot of parameters! Instead, let's use a fully convolutional net (FCN); this also has the benefit that they tend to generalize well, and also seems like a good fit for our problem (since the fish are a small part of the image)
Step3:  Bounding boxes and Multi-Output
<ASSISTANT_TASK:>
Python Code:
(val_classes, train_classes,
 val_labels, train_labels,
 val_filenames, train_filenames,
 test_filenames) = get_classes('data/fish/')
print(val_classes)
print(train_classes)
print(val_labels)
print(train_labels)
print(val_filenames)
print(train_filenames)
print(test_filenames)
# removing path
remove_path = lambda y: [x.split('/')[-1] for x in y]
raw_train_filenames = remove_path(train_filenames)
raw_val_filenames = remove_path(val_filenames)
raw_test_filenames = remove_path(test_filenames)
train_data = get_data('data/fish/train', (360, 640))
val_data   = get_data('data/fish/valid', (360, 640))
test_data  = get_data('data/fish/test', (360, 640))
from vgg16bn import Vgg16BN
model = Vgg16BN((360, 640)).model
model.pop()
model.input_shape
model.output_shape
model.summary()
Explanation: VGG
End of explanation
model.compile(optimizer=Adam(),
              loss='categorical_crossentropy',
              metrics=['accuracy'])
conv_train_features = model.predict(train_data)
conv_test_features  = model.predict(test_data)
conv_val_features   = model.predict(val_data)
Explanation: Precompute convolutional output
End of explanation
lrg_model = Sequential([
    BatchNormalization(axis=1, input_shape=model.output_shape[1:]),
    Convolution2D(128, 3, 3, activation='relu', border_mode='same'),
    BatchNormalization(axis=1),
    MaxPooling2D(),
    Convolution2D(128, 3, 3, activation='relu', border_mode='same'),
    BatchNormalization(axis=1),
    MaxPooling2D(),
    Convolution2D(128, 3, 3, activation='relu', border_mode='same'),
    BatchNormalization(axis=1),
    MaxPooling2D((1,2)),
    Convolution2D(8, 3, 3, border_mode='same'),
    Dropout(0.),
    GlobalAveragePooling2D(),
    Activation('softmax')
])
lrg_model.summary()
lrg_model.compile(optimizer=Adam(lr=0.001),
                loss='categorical_crossentropy',
                metrics=['accuracy'])
lrg_model.fit(conv_train_features, train_labels,
            batch_size=64,
            nb_epoch=2,
            validation_data=(conv_val_features, val_labels),
            verbose=2)
lrg_model.optimizer.lr=1e-5
lrg_model.fit(conv_train_features, train_labels,
            batch_size=64,
            nb_epoch=6,
            validation_data=(conv_val_features, val_labels),
            verbose=2)
Explanation: Fully convolutional net (FCN)
Since we're using a larger input, the output of the final convolutional layer is also larger. So, we probably don't want to put a dense layer in there - that would be a lot of parameters! Instead, let's use a fully convolutional net (FCN); this also has the benefit that they tend to generalize well, and also seems like a good fit for our problem (since the fish are a small part of the image)
End of explanation
import ujson as json
anno_classes = ['alb', 'bet', 'dol', 'lag', 'other', 'shark', 'yft']
bb_json = {}
for c in anno_classes:
    j = json.load(open('{}annos/{}_labels.json'.format('data/fish/', c), 'r'))
    for l in j:
        if 'annotations' in l.keys() and len(l['annotations'])>0:
            bb_json[l['filename'].split('/')[-1]] = sorted(
                l['annotations'], key=lambda x: x['height']*x['width'])[-1]
bb_json['img_04908.jpg']
train_file2idx = {o:i for i,o in enumerate(raw_train_filenames)}
val_file2idx   = {o:i for i,o in enumerate(raw_val_filenames)}
train_file2idx
# for any images that have no annotations, we'll create an empty bounding box
empty_bbox = {'height': 0., 'width': 0., 'x':0., 'y': 0.}
for x in raw_train_filenames:
    if not x in bb_json.keys(): bb_json[x] = empty_bbox
for x in raw_val_filenames:
    if not x in bb_json.keys(): bb_json[x] = empty_bbox
# convert the coordinates to our resized 224x224 images
def convert_bb(bb, size):
    bb = [bb[p] for p in ['height', 'width', 'x', 'y']]
    conv_x = (224. / size[0])
    conv_y = (224. / size[1])
    bb[0]  = bb[0]*conv_y
    bb[1]  = bb[1]*conv_x
    bb[2] = max(bb[2]*conv_x, 0)
    bb[3] = max(bb[3]*conv_y, 0)
    return bb
raw_train_sizes = [PIL.Image.open('data/fish/train/' + x).size for x in train_filenames]
raw_val_sizes   = [PIL.Image.open('data/fish/valid/' + x).size for x in val_filenames]
train_bbox = np.stack([convert_bb(bb_json[f], s) for f,s in zip(raw_train_filenames, raw_train_sizes)])
val_bbox   = np.stack([convert_bb(bb_json[f], s) for f,s in zip(raw_val_filenames, raw_val_sizes)])
def plot_bb(i):
    bb = val_bbox[i]
    plot(val_data[i])
    plt.gca().add_patch(
        plt.Rectangle((bb[2], bb[3]), bb[1], bb[0], color='red', fill=False, lw=3)
    )
%matplotlib inline
plot_bb(0)
# functional api
inp = Input(conv_layers[-1].output_shape[1:])
x   = MaxPooling2D()(inp)
x   = BatchNormalization(axis=1)(x)
x   = Dropout(0.6/4)(x)
x   = Flatten()(x)
x   = Dense(512, activation='relu')(x)
x   = BatchNormalization()(x)
x   = Dropout(0.6)(x)
x   = Dense(512, activation='relu')(x)
x   = BatchNormalization()(x)
x   = Dropout(0.6/2)(x)
y_bb= Dense(4, name='bb')(x)
y_c = Dense(8, activation='softmax', name='class')(x)
# multi-output
model = Model([inp], [y_bb, y_c])
model.compile(optimizer=Adam(lr=0.001),
             loss=['mse', 'categorical_crossentropy'],
             metrics=['accuracy'],
             loss_weights=[0.001, 1.])
model.fit(conv_train_features,
         [train_bbox, train_labels],
         batch_size=64,
         nb_epoch=3,
         validation_data=(conv_val_features, [val_bbox, val_labels]),
         verbose=2)
model.optimizer.lr = 1e-5
model.fit(conv_train_features,
         [train_bbox, train_labels],
         batch_size=64,
         nb_epoch=10,
         validation_data=(conv_val_features, [val_bbox, val_labels]),
         verbose=2)
Explanation: Bounding boxes and Multi-Output
End of explanation
<END_TASK>