I'm trynna make a scratch code of Semantic segmentation through U-Net. I'll use Cityscapes Dataset. I'm trying to make a dictionary(python) composed of the key(car, train, human, etc) and the value(rgb info). How can I match the dictionary with my ground_truth data?
example of labeling dictionary is like below
color_map = {
'0': [0, 0, 0], # unlabelled
'1': [128, 64, 128], # road
'2': [244, 35, 232], # sidewalk
'3': [70, 70, 70], # building
'4': [102, 102, 156], # wall
'5': [190, 153, 153], # fence
'6': [153, 153, 153], # pole
'7': [250,170, 30], # traffic_light
'8': [220, 220, 0], # traffic_sign
'9': [107, 142, 35], # vegetation
'10': [152, 251, 152], # terrain
'11': [0, 130, 180], # sky
'12': [220, 20, 60], # person
'13': [255, 0, 0], # rider
'14': [0, 0, 142], # car
'15': [0, 0, 70], # truck
'16': [0, 60, 100], # bus
'17': [0, 80, 100], # train
'18': [0, 0, 230], # motorcycle
'19': [119, 11, 32] # bicycle
}
I am working on an unsupervised image classification problem, the dataset consists of around 4700 photos of carnivores. I thought of achieving this task by constructing an autoencoder and getting the image embeddings, then applying cosine similarity. I am not getting much improvement. This is my autoencoder architecture:
Model: "functional_75"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_19 (InputLayer) [(None, 128, 128, 3)] 0
_________________________________________________________________
conv2d_126 (Conv2D) (None, 128, 128, 64) 1792
_________________________________________________________________
max_pooling2d_54 (MaxPooling (None, 64, 64, 64) 0
_________________________________________________________________
conv2d_127 (Conv2D) (None, 64, 64, 32) 18464
_________________________________________________________________
max_pooling2d_55 (MaxPooling (None, 32, 32, 32) 0
_________________________________________________________________
conv2d_128 (Conv2D) (None, 32, 32, 16) 4624
_________________________________________________________________
max_pooling2d_56 (MaxPooling (None, 16, 16, 16) 0
_________________________________________________________________
conv2d_129 (Conv2D) (None, 16, 16, 16) 2320
_________________________________________________________________
up_sampling2d_54 (UpSampling (None, 32, 32, 16) 0
_________________________________________________________________
conv2d_130 (Conv2D) (None, 32, 32, 32) 4640
_________________________________________________________________
up_sampling2d_55 (UpSampling (None, 64, 64, 32) 0
_________________________________________________________________
conv2d_131 (Conv2D) (None, 64, 64, 64) 18496
_________________________________________________________________
conv2d_132 (Conv2D) (None, 64, 64, 3) 1731
_________________________________________________________________
up_sampling2d_56 (UpSampling (None, 128, 128, 3) 0
=================================================================
Total params: 52,067
Trainable params: 52,067
Non-trainable params: 0
_________________________________________________________________
Please suggest some tips for improvement.
(4) [{…}, {…}, {…}, {…}]
0: {entity: "lovely meeting", type: "Calendar.Subject", startIndex: 53, endIndex: 66, score: 0.9183444}
1: {entity: "california", type: "Calendar.Location", startIndex: 27, endIndex: 36, score: 0.922538459}
2: {entity: "today", type: "builtin.datetimeV2.date", startIndex: 18, endIndex: 22, resolution: {…}}
3: {entity: "4am", type: "builtin.datetimeV2.time", startIndex: 41, endIndex: 43, resolution: {…}}length: 4__proto__: Array(0)
These 4 elements are part of Entities, what i want is to check if type is equal to let's say Calender.Location and worth noting that we don't always have the 4 elements we could have one or none, and even when we do have 4 the entity type Calender.Location doesn't have to be index number 1, what i have tried included testvar.entities.length and testvar.entities[0].type not knowing the ID of each makes it impossible .
Example of what i want:
i want to parse the Json input for a type Calendar.location in entities, it might exist and might not and its exact id is not known(ranges between 0 and 4), if i do find it i should return the entity associated with it in this case california.
const test =[
{entity: "lovely meeting", type: "Calendar.Subject", startIndex: 53, endIndex: 66, score: 0.9183444},
{entity: "california", type: "Calendar.Location", startIndex: 27, endIndex: 36, score: 0.922538459},
{entity: "today", type: "builtin.datetimeV2.date", startIndex: 18, endIndex: 22, resolution: {}},
{entity: "4am", type: "builtin.datetimeV2.time", startIndex: 41, endIndex: 43, resolution: {}}
]
const getentitiesByType = (arr,type) => {
for(let i in arr ){
if(arr[i].type === type){
return arr[i].entity;
}
}
};
console.log(getentitiesByType(test,"Calendar.Location"))
I'm trying to load a set of frames from an atlas for an animation. After pack my images with TexturePacker, my atlas file is like this:
ufo_data2.png
size: 2048,2048
format: RGBA8888
filter: Nearest,Nearest
repeat: none
Ufo_gfx/red/ufo_0_red0000
rotate: false
xy: 2, 1030
size: 512, 512
orig: 512, 512
offset: 0, 0
index: -1
Ufo_gfx/red/ufo_0_red0001
rotate: false
xy: 2, 516
size: 512, 512
orig: 512, 512
offset: 0, 0
index: -1
Ufo_gfx/red/ufo_0_red0002
rotate: false
xy: 516, 1030
size: 512, 512
orig: 512, 512
offset: 0, 0
index: -1
Ufo_gfx/red/ufo_0_red0003
rotate: false
xy: 2, 2
size: 512, 512
orig: 512, 512
offset: 0, 0
index: -1
Ufo_gfx/red/ufo_0_red0004
rotate: false
xy: 516, 516
size: 512, 512
orig: 512, 512
offset: 0, 0
index: -1
Ufo_gfx/red/ufo_0_red0005
rotate: false
xy: 1030, 1030
size: 512, 512
orig: 512, 512
offset: 0, 0
index: -1
Ufo_gfx/red/ufo_0_red0006
rotate: false
xy: 516, 2
size: 512, 512
orig: 512, 512
offset: 0, 0
index: -1
I'm trying to load the animation like this:
TextureAtlas atlas;
atlas = new TextureAtlas(Gdx.files.internal("data/gfx/ufo_data.atlas"));
ufo_animation = new Animation<TextureRegion>(0.033f, atlas.findRegions("Ufo_gfx/red/"));
I found that atlas.findRegions("Ufo_gfx/red/") or even atlas.findRegions("Ufo_gfx/red/*") returns always 0 results.
I thought that using a Regex like expression will be enough to load all frames, but after look inside the findRegions() code, I found the only returns when match is exactly the string entered.
FindRegions() seems useless if one think in the way TexturePacker works.
My question is: is there a way to put an string that matches all names of images with a similar name?
Note: I found that the solution is here:
https://github.com/libgdx/libgdx/wiki/Texture-packer#image-indexes
It is needed to put images with their name and underscore and index, like a_00.png
a_01.png
Then, texture packer packs images with indexes.
The solution I found is https://github.com/libgdx/libgdx/wiki/Texture-packer#image-indexes
Need to rename files as imagename_00.png, imagename_01.png, imagename_02.png.
When images are packaging, systems understands _xx as indices and automatically puts index in atlas file.
Then you only need to call findRegions(imagename)
You can create a helper function that calls getRegion(), iterates over all regions and checks whether their name.startsWith("Ufo_gfx/red/"). Put all these in a collection and return them from your helper function.
Thats simple:
All your regions should have the same name
You should rewrite index: -1 on all regions from -1 to count number from 1
How should it look like:
ufo_data2.png
size: 2048,2048
format: RGBA8888
filter: Nearest,Nearest
repeat: none
Ufo_gfx/red/ufo_0_red
rotate: false
xy: 2, 1030
size: 512, 512
orig: 512, 512
offset: 0, 0
index: 1
Ufo_gfx/red/ufo_0_red
rotate: false
xy: 2, 516
size: 512, 512
orig: 512, 512
offset: 0, 0
index: 2
Ufo_gfx/red/ufo_0_red
rotate: false
xy: 516, 1030
size: 512, 512
orig: 512, 512
offset: 0, 0
index: 3
Ufo_gfx/red/ufo_0_red
rotate: false
xy: 2, 2
size: 512, 512
orig: 512, 512
offset: 0, 0
index: 4
Ufo_gfx/red/ufo_0_red
rotate: false
xy: 516, 516
size: 512, 512
orig: 512, 512
offset: 0, 0
index: 5
Ufo_gfx/red/ufo_0_red
rotate: false
xy: 1030, 1030
size: 512, 512
orig: 512, 512
offset: 0, 0
index: 6
Ufo_gfx/red/ufo_0_red
rotate: false
xy: 516, 2
size: 512, 512
orig: 512, 512
offset: 0, 0
index: 7
Now you can create Array just using:
atlas.findRegions("Ufo_gfx/red/ufo_0_red");
All names of regions must be:
ufo_0_red_0001
rotate: false
xy: 2, 1030
size: 512, 512
orig: 512, 512
offset: 0, 0
index: 1
ufo_0_red_0002
rotate: false
xy: 2, 516
size: 512, 512
.........
I am actually trying to get a Sequential model version of VGG16 with Keras. The functional version can be obtained with:
from __future__ import division, print_function
import os, json
from glob import glob
import numpy as np
from scipy import misc, ndimage
from scipy.ndimage.interpolation import zoom
from keras import backend as K
from keras.layers.normalization import BatchNormalization
from keras.utils.data_utils import get_file
from keras.models import Sequential
from keras.layers.core import Flatten, Dense, Dropout, Lambda
from keras.layers.convolutional import Convolution2D, MaxPooling2D, ZeroPadding2D
from keras.layers.pooling import GlobalAveragePooling2D
from keras.optimizers import SGD, RMSprop, Adam
from keras.preprocessing import image
import keras
import keras.applications.vgg16
from keras.layers import Input
input_tensor = Input(shape=(224,224,3))
VGG_model=keras.applications.vgg16.VGG16(weights='imagenet',include_top= True,input_tensor=input_tensor)
Its summary goes like this :
VGG_model.summary()
Layer (type) Output Shape Param # Connected to
====================================================================================================
input_1 (InputLayer) (None, 224, 224, 3) 0
____________________________________________________________________________________________________
block1_conv1 (Convolution2D) (None, 224, 224, 64) 1792 input_1[0][0]
____________________________________________________________________________________________________
block1_conv2 (Convolution2D) (None, 224, 224, 64) 36928 block1_conv1[0][0]
____________________________________________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0 block1_conv2[0][0]
____________________________________________________________________________________________________
block2_conv1 (Convolution2D) (None, 112, 112, 128) 73856 block1_pool[0][0]
____________________________________________________________________________________________________
block2_conv2 (Convolution2D) (None, 112, 112, 128) 147584 block2_conv1[0][0]
____________________________________________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0 block2_conv2[0][0]
____________________________________________________________________________________________________
block3_conv1 (Convolution2D) (None, 56, 56, 256) 295168 block2_pool[0][0]
____________________________________________________________________________________________________
block3_conv2 (Convolution2D) (None, 56, 56, 256) 590080 block3_conv1[0][0]
____________________________________________________________________________________________________
block3_conv3 (Convolution2D) (None, 56, 56, 256) 590080 block3_conv2[0][0]
____________________________________________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0 block3_conv3[0][0]
____________________________________________________________________________________________________
block4_conv1 (Convolution2D) (None, 28, 28, 512) 1180160 block3_pool[0][0]
____________________________________________________________________________________________________
block4_conv2 (Convolution2D) (None, 28, 28, 512) 2359808 block4_conv1[0][0]
____________________________________________________________________________________________________
block4_conv3 (Convolution2D) (None, 28, 28, 512) 2359808 block4_conv2[0][0]
____________________________________________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0 block4_conv3[0][0]
____________________________________________________________________________________________________
block5_conv1 (Convolution2D) (None, 14, 14, 512) 2359808 block4_pool[0][0]
____________________________________________________________________________________________________
block5_conv2 (Convolution2D) (None, 14, 14, 512) 2359808 block5_conv1[0][0]
____________________________________________________________________________________________________
block5_conv3 (Convolution2D) (None, 14, 14, 512) 2359808 block5_conv2[0][0]
____________________________________________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0 block5_conv3[0][0]
____________________________________________________________________________________________________
flatten (Flatten) (None, 25088) 0 block5_pool[0][0]
____________________________________________________________________________________________________
fc1 (Dense) (None, 4096) 102764544 flatten[0][0]
____________________________________________________________________________________________________
fc2 (Dense) (None, 4096) 16781312 fc1[0][0]
____________________________________________________________________________________________________
predictions (Dense) (None, 1000) 4097000 fc2[0][0]
====================================================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
____________________________________________________________________________________________________
According to this website https://github.com/fchollet/keras/issues/3190 , it says
Sequential(layers=functional_model.layers)
Could covert functional models into sequential model. However, if I do:
model = Sequential(layers=VGG_model.layers)
model.summary()
It leads to
Layer (type) Output Shape Param # Connected to
====================================================================================================
input_1 (InputLayer) (None, 224, 224, 3) 0
____________________________________________________________________________________________________
block1_conv1 (Convolution2D) (None, 224, 224, 64) 1792 input_1[0][0]
input_1[0][0]
input_1[0][0]
____________________________________________________________________________________________________
block1_conv2 (Convolution2D) (None, 224, 224, 64) 36928 block1_conv1[0][0]
block1_conv1[1][0]
block1_conv1[2][0]
____________________________________________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0 block1_conv2[0][0]
block1_conv2[1][0]
block1_conv2[2][0]
____________________________________________________________________________________________________
block2_conv1 (Convolution2D) (None, 112, 112, 128) 73856 block1_pool[0][0]
block1_pool[1][0]
block1_pool[2][0]
____________________________________________________________________________________________________
block2_conv2 (Convolution2D) (None, 112, 112, 128) 147584 block2_conv1[0][0]
block2_conv1[1][0]
block2_conv1[2][0]
____________________________________________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0 block2_conv2[0][0]
block2_conv2[1][0]
block2_conv2[2][0]
____________________________________________________________________________________________________
block3_conv1 (Convolution2D) (None, 56, 56, 256) 295168 block2_pool[0][0]
block2_pool[1][0]
block2_pool[2][0]
____________________________________________________________________________________________________
block3_conv2 (Convolution2D) (None, 56, 56, 256) 590080 block3_conv1[0][0]
block3_conv1[1][0]
block3_conv1[2][0]
____________________________________________________________________________________________________
block3_conv3 (Convolution2D) (None, 56, 56, 256) 590080 block3_conv2[0][0]
block3_conv2[1][0]
block3_conv2[2][0]
____________________________________________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0 block3_conv3[0][0]
block3_conv3[1][0]
block3_conv3[2][0]
____________________________________________________________________________________________________
block4_conv1 (Convolution2D) (None, 28, 28, 512) 1180160 block3_pool[0][0]
block3_pool[1][0]
block3_pool[2][0]
____________________________________________________________________________________________________
block4_conv2 (Convolution2D) (None, 28, 28, 512) 2359808 block4_conv1[0][0]
block4_conv1[1][0]
block4_conv1[2][0]
____________________________________________________________________________________________________
block4_conv3 (Convolution2D) (None, 28, 28, 512) 2359808 block4_conv2[0][0]
block4_conv2[1][0]
block4_conv2[2][0]
____________________________________________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0 block4_conv3[0][0]
block4_conv3[1][0]
block4_conv3[2][0]
____________________________________________________________________________________________________
block5_conv1 (Convolution2D) (None, 14, 14, 512) 2359808 block4_pool[0][0]
block4_pool[1][0]
block4_pool[2][0]
____________________________________________________________________________________________________
block5_conv2 (Convolution2D) (None, 14, 14, 512) 2359808 block5_conv1[0][0]
block5_conv1[1][0]
block5_conv1[2][0]
____________________________________________________________________________________________________
block5_conv3 (Convolution2D) (None, 14, 14, 512) 2359808 block5_conv2[0][0]
block5_conv2[1][0]
block5_conv2[2][0]
____________________________________________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0 block5_conv3[0][0]
block5_conv3[1][0]
block5_conv3[2][0]
____________________________________________________________________________________________________
flatten (Flatten) (None, 25088) 0 block5_pool[0][0]
block5_pool[1][0]
block5_pool[2][0]
____________________________________________________________________________________________________
fc1 (Dense) (None, 4096) 102764544 flatten[0][0]
flatten[1][0]
flatten[2][0]
____________________________________________________________________________________________________
fc2 (Dense) (None, 4096) 16781312 fc1[0][0]
fc1[1][0]
fc1[2][0]
____________________________________________________________________________________________________
predictions (Dense) (None, 1000) 4097000 fc2[0][0]
fc2[1][0]
fc2[2][0]
====================================================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_
This is different from the original functional model since the new layer is connected to the previous layer 3 times. People say it is more powerful to use functional models. But what I want to do is just to pop the final prediction layer. And functional model cannot do this...
I have also been struggling with this and the previous poster was almost there, but left out a particular detail that was stumping me before.
Indeed you can do the "pop" even with a Model created with the Functional API, but it is a little more work.
Here's my model (Just plain vanilla VGG16)
model.summary()
____________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
====================================================================================================
input_6 (InputLayer) (None, 224, 224, 3) 0
____________________________________________________________________________________________________
block1_conv1 (Convolution2D) (None, 224, 224, 64) 1792 input_6[0][0]
____________________________________________________________________________________________________
block1_conv2 (Convolution2D) (None, 224, 224, 64) 36928 block1_conv1[0][0]
____________________________________________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0 block1_conv2[0][0]
____________________________________________________________________________________________________
block2_conv1 (Convolution2D) (None, 112, 112, 128) 73856 block1_pool[0][0]
____________________________________________________________________________________________________
block2_conv2 (Convolution2D) (None, 112, 112, 128) 147584 block2_conv1[0][0]
____________________________________________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0 block2_conv2[0][0]
____________________________________________________________________________________________________
block3_conv1 (Convolution2D) (None, 56, 56, 256) 295168 block2_pool[0][0]
____________________________________________________________________________________________________
block3_conv2 (Convolution2D) (None, 56, 56, 256) 590080 block3_conv1[0][0]
____________________________________________________________________________________________________
block3_conv3 (Convolution2D) (None, 56, 56, 256) 590080 block3_conv2[0][0]
____________________________________________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0 block3_conv3[0][0]
____________________________________________________________________________________________________
block4_conv1 (Convolution2D) (None, 28, 28, 512) 1180160 block3_pool[0][0]
____________________________________________________________________________________________________
block4_conv2 (Convolution2D) (None, 28, 28, 512) 2359808 block4_conv1[0][0]
____________________________________________________________________________________________________
block4_conv3 (Convolution2D) (None, 28, 28, 512) 2359808 block4_conv2[0][0]
____________________________________________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0 block4_conv3[0][0]
____________________________________________________________________________________________________
block5_conv1 (Convolution2D) (None, 14, 14, 512) 2359808 block4_pool[0][0]
____________________________________________________________________________________________________
block5_conv2 (Convolution2D) (None, 14, 14, 512) 2359808 block5_conv1[0][0]
____________________________________________________________________________________________________
block5_conv3 (Convolution2D) (None, 14, 14, 512) 2359808 block5_conv2[0][0]
____________________________________________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0 block5_conv3[0][0]
____________________________________________________________________________________________________
flatten (Flatten) (None, 25088) 0 block5_pool[0][0]
____________________________________________________________________________________________________
fc1 (Dense) (None, 4096) 102764544 flatten[0][0]
____________________________________________________________________________________________________
fc2 (Dense) (None, 4096) 16781312 fc1[0][0]
____________________________________________________________________________________________________
predictions (Dense) (None, 1000) 4097000 fc2[0][0]
====================================================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
____________________________________________________________________________________________________
Then I "popped" the last layer but not using pop, just with the Functional API
#Get the last but one layer/tensor from the old model
last_layer = model.layers[-2].output
#Define the new layer/tensor for the new model
new_model = Dense(2, activation='softmax', name='Binary_predictions')(last_layer)
#Create the new model, with the old models input and the new_model tensor as the output
new_model = Model(model.input, new_model, name='Finetuned_VGG16')
#Set all layers,except the last one to not trainable
for layer in new_model.layers[:-1]: layer.trainable=False
#Compile the new model
new_model.compile(optimizer=Adam(lr=learning_rate),
loss='categorical_crossentropy', metrics=['accuracy'])
#now train with the new outputs (cats and dogs!)
This creates a new model (new_model) with the last layer replaced and the old layers fixed (made non-trainable)..
new_model.summary()
____________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
====================================================================================================
input_6 (InputLayer) (None, 224, 224, 3) 0
____________________________________________________________________________________________________
block1_conv1 (Convolution2D) (None, 224, 224, 64) 1792 input_6[0][0]
____________________________________________________________________________________________________
block1_conv2 (Convolution2D) (None, 224, 224, 64) 36928 block1_conv1[0][0]
____________________________________________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0 block1_conv2[0][0]
____________________________________________________________________________________________________
block2_conv1 (Convolution2D) (None, 112, 112, 128) 73856 block1_pool[0][0]
____________________________________________________________________________________________________
block2_conv2 (Convolution2D) (None, 112, 112, 128) 147584 block2_conv1[0][0]
____________________________________________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0 block2_conv2[0][0]
____________________________________________________________________________________________________
block3_conv1 (Convolution2D) (None, 56, 56, 256) 295168 block2_pool[0][0]
____________________________________________________________________________________________________
block3_conv2 (Convolution2D) (None, 56, 56, 256) 590080 block3_conv1[0][0]
____________________________________________________________________________________________________
block3_conv3 (Convolution2D) (None, 56, 56, 256) 590080 block3_conv2[0][0]
____________________________________________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0 block3_conv3[0][0]
____________________________________________________________________________________________________
block4_conv1 (Convolution2D) (None, 28, 28, 512) 1180160 block3_pool[0][0]
____________________________________________________________________________________________________
block4_conv2 (Convolution2D) (None, 28, 28, 512) 2359808 block4_conv1[0][0]
____________________________________________________________________________________________________
block4_conv3 (Convolution2D) (None, 28, 28, 512) 2359808 block4_conv2[0][0]
____________________________________________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0 block4_conv3[0][0]
____________________________________________________________________________________________________
block5_conv1 (Convolution2D) (None, 14, 14, 512) 2359808 block4_pool[0][0]
____________________________________________________________________________________________________
block5_conv2 (Convolution2D) (None, 14, 14, 512) 2359808 block5_conv1[0][0]
____________________________________________________________________________________________________
block5_conv3 (Convolution2D) (None, 14, 14, 512) 2359808 block5_conv2[0][0]
____________________________________________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0 block5_conv3[0][0]
____________________________________________________________________________________________________
flatten (Flatten) (None, 25088) 0 block5_pool[0][0]
____________________________________________________________________________________________________
fc1 (Dense) (None, 4096) 102764544 flatten[0][0]
____________________________________________________________________________________________________
fc2 (Dense) (None, 4096) 16781312 fc1[0][0]
____________________________________________________________________________________________________
Binary_predictions (Dense) (None, 2) 8194 fc2[0][0]
====================================================================================================
Total params: 134,268,738
Trainable params: 8,194
Non-trainable params: 134,260,544
The tricky part was getting the .output as the last layer, since that makes it a Tensor. Then using that Tensor as the input for the new Dense layer and making THAT the final output in the new Model...
Hope that helps...
Thon
You can "pop" the final layer by just definining another Model taking the previous layer as output:
poppedModel = Model(VGG_model.input,VGG_model.layers[-2].output)
This model will share exactly the same weights as the original model, and training will affect both models.
You can add your own layers (or even models) after poppedModel, no problem:
popOut = poppedModel(input_tensor)
newLayOut = SomeKerasLayer(blablabla)(popOut)
anotherModel = Model(input_tensor, newLayOut)
#anotherModel will also share weights with poppedModel and VGG_model in the layers they have in common.
It's important, though, if you intend to train the new layers in anotherModel without affecting the VGG weights, that you make poppedModel.trainable = False and each layer in it with poppedModel.layers[i].trainable = False before compiling anotherModel.