Padding in Keras with output half sized input
$begingroup$
Here is my Keras model I'm working on:
model = Sequential()
model.add(Conv2D(64, kernel_size=(7, 7), strides = 2, padding = 3,
input_shape=input_shape)) # (224,224,64)
model.add(MaxPooling2D(pool_size=(2, 2), strides = 2)) # (112,112,64)
model.add(Conv2D(192, kernel_size = (3,3), padding = 1)) #(112,112,192)
model.add(MaxPooling2D(pool_size = (2,2),strides = 2)) #(56,56,192)
model.add(Conv2D(128, kernel_size = (1,1))) #(56,56,128)
model.add(Conv2D(256, kernel_size = (3,3), padding = 1)) #(56,56,256)
model.add(Conv2D(256, kernel_size = (1,1))) #(56,56,256)
model.add(Conv2D(512, kernel_size = (3,3),padding = 1)) #(56,56,512)
model.add(MaxPooling2D(pool_size = (2,2), strides = 2)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(512, kernel_size = (1,1))) #(28,28,512)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(28,28,1024)
model.add(MaxPooling2D(pool_size = (2,2), strides = 2)) #(14,14,1024)
model.add(Conv2D(512, kernel_size = (1,1))) #(14,14,512)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(14,14,1024)
model.add(Conv2D(512, kernel_size = (1,1))) #(14,14,512)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(14,14,1024)
model.add(Conv2D(1024, kernel_size = (3,3), padding = 1)) #(14,14,1024)
model.add(Conv2D(1024, kernel_size = (3,3), strides = 2, padding = 3)) #(7,7,1024)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(7,7,1024)
model.add(Conv2D(1024, kernel_size = (3,3), padding = 1)) #(7,7,1024)
model.add(Flatten())
model.add(Dense(4096))
model.add(Dense(7*7*30))
model.add(Reshape(7,7,30))
When I compile it, I got an error for padding because Keras knows only 'same', valid' and 'casual'. I understand these, but I really need padding somewhere to be equal to 3 because my output should be a half of input (we have strides equal to 2). I really don't know how to fix it. How to do padding if we want to half size the input with strides 2?
neural-network keras
$endgroup$
bumped to the homepage by Community♦ 12 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
add a comment |
$begingroup$
Here is my Keras model I'm working on:
model = Sequential()
model.add(Conv2D(64, kernel_size=(7, 7), strides = 2, padding = 3,
input_shape=input_shape)) # (224,224,64)
model.add(MaxPooling2D(pool_size=(2, 2), strides = 2)) # (112,112,64)
model.add(Conv2D(192, kernel_size = (3,3), padding = 1)) #(112,112,192)
model.add(MaxPooling2D(pool_size = (2,2),strides = 2)) #(56,56,192)
model.add(Conv2D(128, kernel_size = (1,1))) #(56,56,128)
model.add(Conv2D(256, kernel_size = (3,3), padding = 1)) #(56,56,256)
model.add(Conv2D(256, kernel_size = (1,1))) #(56,56,256)
model.add(Conv2D(512, kernel_size = (3,3),padding = 1)) #(56,56,512)
model.add(MaxPooling2D(pool_size = (2,2), strides = 2)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(512, kernel_size = (1,1))) #(28,28,512)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(28,28,1024)
model.add(MaxPooling2D(pool_size = (2,2), strides = 2)) #(14,14,1024)
model.add(Conv2D(512, kernel_size = (1,1))) #(14,14,512)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(14,14,1024)
model.add(Conv2D(512, kernel_size = (1,1))) #(14,14,512)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(14,14,1024)
model.add(Conv2D(1024, kernel_size = (3,3), padding = 1)) #(14,14,1024)
model.add(Conv2D(1024, kernel_size = (3,3), strides = 2, padding = 3)) #(7,7,1024)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(7,7,1024)
model.add(Conv2D(1024, kernel_size = (3,3), padding = 1)) #(7,7,1024)
model.add(Flatten())
model.add(Dense(4096))
model.add(Dense(7*7*30))
model.add(Reshape(7,7,30))
When I compile it, I got an error for padding because Keras knows only 'same', valid' and 'casual'. I understand these, but I really need padding somewhere to be equal to 3 because my output should be a half of input (we have strides equal to 2). I really don't know how to fix it. How to do padding if we want to half size the input with strides 2?
neural-network keras
$endgroup$
bumped to the homepage by Community♦ 12 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
$begingroup$
What do you mean by half the size of your input? which input?
$endgroup$
– n1k31t4
Jun 27 '18 at 14:37
$begingroup$
Input image is of the form (448,448,3) so in order to have (224,224,64) we use 64 kernels of size (7,7) and padding = 3 and strides = 2. 224 is half the size of 448. Also, from (14,14,1024) to (7,7,1024) we use padding = 3 and strides = 2. Seven is half of 14.
$endgroup$
– Alem
Jun 27 '18 at 15:15
add a comment |
$begingroup$
Here is my Keras model I'm working on:
model = Sequential()
model.add(Conv2D(64, kernel_size=(7, 7), strides = 2, padding = 3,
input_shape=input_shape)) # (224,224,64)
model.add(MaxPooling2D(pool_size=(2, 2), strides = 2)) # (112,112,64)
model.add(Conv2D(192, kernel_size = (3,3), padding = 1)) #(112,112,192)
model.add(MaxPooling2D(pool_size = (2,2),strides = 2)) #(56,56,192)
model.add(Conv2D(128, kernel_size = (1,1))) #(56,56,128)
model.add(Conv2D(256, kernel_size = (3,3), padding = 1)) #(56,56,256)
model.add(Conv2D(256, kernel_size = (1,1))) #(56,56,256)
model.add(Conv2D(512, kernel_size = (3,3),padding = 1)) #(56,56,512)
model.add(MaxPooling2D(pool_size = (2,2), strides = 2)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(512, kernel_size = (1,1))) #(28,28,512)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(28,28,1024)
model.add(MaxPooling2D(pool_size = (2,2), strides = 2)) #(14,14,1024)
model.add(Conv2D(512, kernel_size = (1,1))) #(14,14,512)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(14,14,1024)
model.add(Conv2D(512, kernel_size = (1,1))) #(14,14,512)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(14,14,1024)
model.add(Conv2D(1024, kernel_size = (3,3), padding = 1)) #(14,14,1024)
model.add(Conv2D(1024, kernel_size = (3,3), strides = 2, padding = 3)) #(7,7,1024)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(7,7,1024)
model.add(Conv2D(1024, kernel_size = (3,3), padding = 1)) #(7,7,1024)
model.add(Flatten())
model.add(Dense(4096))
model.add(Dense(7*7*30))
model.add(Reshape(7,7,30))
When I compile it, I got an error for padding because Keras knows only 'same', valid' and 'casual'. I understand these, but I really need padding somewhere to be equal to 3 because my output should be a half of input (we have strides equal to 2). I really don't know how to fix it. How to do padding if we want to half size the input with strides 2?
neural-network keras
$endgroup$
Here is my Keras model I'm working on:
model = Sequential()
model.add(Conv2D(64, kernel_size=(7, 7), strides = 2, padding = 3,
input_shape=input_shape)) # (224,224,64)
model.add(MaxPooling2D(pool_size=(2, 2), strides = 2)) # (112,112,64)
model.add(Conv2D(192, kernel_size = (3,3), padding = 1)) #(112,112,192)
model.add(MaxPooling2D(pool_size = (2,2),strides = 2)) #(56,56,192)
model.add(Conv2D(128, kernel_size = (1,1))) #(56,56,128)
model.add(Conv2D(256, kernel_size = (3,3), padding = 1)) #(56,56,256)
model.add(Conv2D(256, kernel_size = (1,1))) #(56,56,256)
model.add(Conv2D(512, kernel_size = (3,3),padding = 1)) #(56,56,512)
model.add(MaxPooling2D(pool_size = (2,2), strides = 2)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(256, kernel_size = (1,1))) #(28,28,128)
model.add(Conv2D(512, kernel_size = (3,3), padding = 1)) #(28,28,512)
model.add(Conv2D(512, kernel_size = (1,1))) #(28,28,512)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(28,28,1024)
model.add(MaxPooling2D(pool_size = (2,2), strides = 2)) #(14,14,1024)
model.add(Conv2D(512, kernel_size = (1,1))) #(14,14,512)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(14,14,1024)
model.add(Conv2D(512, kernel_size = (1,1))) #(14,14,512)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(14,14,1024)
model.add(Conv2D(1024, kernel_size = (3,3), padding = 1)) #(14,14,1024)
model.add(Conv2D(1024, kernel_size = (3,3), strides = 2, padding = 3)) #(7,7,1024)
model.add(Conv2D(1024,kernel_size = (3,3), padding = 1)) #(7,7,1024)
model.add(Conv2D(1024, kernel_size = (3,3), padding = 1)) #(7,7,1024)
model.add(Flatten())
model.add(Dense(4096))
model.add(Dense(7*7*30))
model.add(Reshape(7,7,30))
When I compile it, I got an error for padding because Keras knows only 'same', valid' and 'casual'. I understand these, but I really need padding somewhere to be equal to 3 because my output should be a half of input (we have strides equal to 2). I really don't know how to fix it. How to do padding if we want to half size the input with strides 2?
neural-network keras
neural-network keras
edited Jun 27 '18 at 14:25
n1k31t4
6,7012421
6,7012421
asked Jun 27 '18 at 13:51
AlemAlem
347
347
bumped to the homepage by Community♦ 12 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
bumped to the homepage by Community♦ 12 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
$begingroup$
What do you mean by half the size of your input? which input?
$endgroup$
– n1k31t4
Jun 27 '18 at 14:37
$begingroup$
Input image is of the form (448,448,3) so in order to have (224,224,64) we use 64 kernels of size (7,7) and padding = 3 and strides = 2. 224 is half the size of 448. Also, from (14,14,1024) to (7,7,1024) we use padding = 3 and strides = 2. Seven is half of 14.
$endgroup$
– Alem
Jun 27 '18 at 15:15
add a comment |
$begingroup$
What do you mean by half the size of your input? which input?
$endgroup$
– n1k31t4
Jun 27 '18 at 14:37
$begingroup$
Input image is of the form (448,448,3) so in order to have (224,224,64) we use 64 kernels of size (7,7) and padding = 3 and strides = 2. 224 is half the size of 448. Also, from (14,14,1024) to (7,7,1024) we use padding = 3 and strides = 2. Seven is half of 14.
$endgroup$
– Alem
Jun 27 '18 at 15:15
$begingroup$
What do you mean by half the size of your input? which input?
$endgroup$
– n1k31t4
Jun 27 '18 at 14:37
$begingroup$
What do you mean by half the size of your input? which input?
$endgroup$
– n1k31t4
Jun 27 '18 at 14:37
$begingroup$
Input image is of the form (448,448,3) so in order to have (224,224,64) we use 64 kernels of size (7,7) and padding = 3 and strides = 2. 224 is half the size of 448. Also, from (14,14,1024) to (7,7,1024) we use padding = 3 and strides = 2. Seven is half of 14.
$endgroup$
– Alem
Jun 27 '18 at 15:15
$begingroup$
Input image is of the form (448,448,3) so in order to have (224,224,64) we use 64 kernels of size (7,7) and padding = 3 and strides = 2. 224 is half the size of 448. Also, from (14,14,1024) to (7,7,1024) we use padding = 3 and strides = 2. Seven is half of 14.
$endgroup$
– Alem
Jun 27 '18 at 15:15
add a comment |
1 Answer
1
active
oldest
votes
$begingroup$
If you goal is simply to halve the size of your filters, you could think about using some different methods other than padding, such as dilated convolutions. Have a look at this paper for some ideas and nice explanations with pictures. Just thinking about your dimensions quickly, I am not sure you could go from 14 to 7 very easily. getting to 8 or 5 is simple enough though.
A trick few Keras users know is that you can mix in Tensorflow operations directly from the Tensorflow library.
In TF there is a function called pad
, which allows you to specify the padding manually on each side of a tensor. There are also options to say whether the padding is done with zeros, or if the values inside your original tensor are repeated/mirrored (using the mode
argument).
You could try using this to pad the layers. I can show you how to pad the tensors to get the effect you want:
from keras.models import Sequential, Model
from keras.layers import (Input, Conv2D, MaxPooling2D,
Flatten, Dense, Reshape, Lambda)
import tensorflow as tf
input_shape = (448, 448, 3)
batch_shape = (None,) + input_shape
raw_input = tf.placeholder(dtype='float16', shape=batch_shape)
paddings = tf.constant([[0, 0], # the batch size dimension
[3, 3], # top and bottom of image
[3, 3], # left and right
[0, 0]]) # the channels dimension
padded_input = tf.pad(raw_input, paddings, mode='CONSTANT',
constant_values=0.0) # pads with 0 by default
padded_shape = padded_input.shape # (454, 454, 3) because we add 2*3 padding
input_layer = Input(padded_shape, batch_shape, tensor=padded_input)
layer0 = Conv2D(192, kernel_size = (3,3), padding='valid')(input_layer)
layer1 = MaxPooling2D(pool_size=(2, 2), strides = 2)(layer0)
layer2 = Conv2D(192, kernel_size = (3,3), padding='valid')(layer1)
layer3 = MaxPooling2D(pool_size = (2,2),strides = 2)(layer2)
layer4 = Conv2D(512, kernel_size = (3,3), padding='valid')(layer3)
layer5 = MaxPooling2D(pool_size = (2,2), strides = 2)(layer4)
layer6 = Conv2D(256, kernel_size = (1,1), padding='valid')(layer5)
# layer6.shape --> [Dimension(None), Dimension(55), Dimension(55), Dimension(256)]
layer6_padded = tf.pad(layer6, paddings, mode='CONSTANT')
layer6_output = Input(input_shape=layer6_padded.shape)(layer6_padded)
# This will end up giving this error at compilation:
# RuntimeError: Graph disconnected: ...,
layer7 = Conv2D(1024, kernel_size=(3, 3), strides=2)(layer6_output)
layer8 = Flatten()(layer7)
layer9 = Dense(4096)(layer7)
layer10 = Dense(7*7*30)(layer8)
output_layer = Reshape((7, 7, 30))(layer10)
# The following both fail to get the graph as we would like it
model = Model(inputs=[input_layer], outputs=[output_layer])
#model = Model(inputs=[input_layer, layer6_output], outputs=[output_layer])
model.compile('adam', 'mse')
model.summary()
I have been unable to then bring this tensor back into the Keras model (as a layer, which is required) because the standard way of using the Input
object forces it to be the entry point of the computational graph, but we want the padded tensors to form an intermediary layer.
If you don't force the padded tensors into a Keras layer, attributes will be missing:
# AttributeError: 'Tensor' object has no attribute '_keras_history'
Which you can hack by just adding the attribute from the layer before we padded:
#layer6_output._keras_history = layer6._keras_history
Unfortunately, I still ran into other errors.
Perhaps you can post a new question on StackOverflow asking how to to this, if you can find anything. I did have a quick try using the idea of creating two graphs and then joining them, but didn't succeed.
$endgroup$
$begingroup$
There is more info on the disconneted graph error here.
$endgroup$
– n1k31t4
Jun 28 '18 at 11:26
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "557"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdatascience.stackexchange.com%2fquestions%2f33725%2fpadding-in-keras-with-output-half-sized-input%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
If you goal is simply to halve the size of your filters, you could think about using some different methods other than padding, such as dilated convolutions. Have a look at this paper for some ideas and nice explanations with pictures. Just thinking about your dimensions quickly, I am not sure you could go from 14 to 7 very easily. getting to 8 or 5 is simple enough though.
A trick few Keras users know is that you can mix in Tensorflow operations directly from the Tensorflow library.
In TF there is a function called pad
, which allows you to specify the padding manually on each side of a tensor. There are also options to say whether the padding is done with zeros, or if the values inside your original tensor are repeated/mirrored (using the mode
argument).
You could try using this to pad the layers. I can show you how to pad the tensors to get the effect you want:
from keras.models import Sequential, Model
from keras.layers import (Input, Conv2D, MaxPooling2D,
Flatten, Dense, Reshape, Lambda)
import tensorflow as tf
input_shape = (448, 448, 3)
batch_shape = (None,) + input_shape
raw_input = tf.placeholder(dtype='float16', shape=batch_shape)
paddings = tf.constant([[0, 0], # the batch size dimension
[3, 3], # top and bottom of image
[3, 3], # left and right
[0, 0]]) # the channels dimension
padded_input = tf.pad(raw_input, paddings, mode='CONSTANT',
constant_values=0.0) # pads with 0 by default
padded_shape = padded_input.shape # (454, 454, 3) because we add 2*3 padding
input_layer = Input(padded_shape, batch_shape, tensor=padded_input)
layer0 = Conv2D(192, kernel_size = (3,3), padding='valid')(input_layer)
layer1 = MaxPooling2D(pool_size=(2, 2), strides = 2)(layer0)
layer2 = Conv2D(192, kernel_size = (3,3), padding='valid')(layer1)
layer3 = MaxPooling2D(pool_size = (2,2),strides = 2)(layer2)
layer4 = Conv2D(512, kernel_size = (3,3), padding='valid')(layer3)
layer5 = MaxPooling2D(pool_size = (2,2), strides = 2)(layer4)
layer6 = Conv2D(256, kernel_size = (1,1), padding='valid')(layer5)
# layer6.shape --> [Dimension(None), Dimension(55), Dimension(55), Dimension(256)]
layer6_padded = tf.pad(layer6, paddings, mode='CONSTANT')
layer6_output = Input(input_shape=layer6_padded.shape)(layer6_padded)
# This will end up giving this error at compilation:
# RuntimeError: Graph disconnected: ...,
layer7 = Conv2D(1024, kernel_size=(3, 3), strides=2)(layer6_output)
layer8 = Flatten()(layer7)
layer9 = Dense(4096)(layer7)
layer10 = Dense(7*7*30)(layer8)
output_layer = Reshape((7, 7, 30))(layer10)
# The following both fail to get the graph as we would like it
model = Model(inputs=[input_layer], outputs=[output_layer])
#model = Model(inputs=[input_layer, layer6_output], outputs=[output_layer])
model.compile('adam', 'mse')
model.summary()
I have been unable to then bring this tensor back into the Keras model (as a layer, which is required) because the standard way of using the Input
object forces it to be the entry point of the computational graph, but we want the padded tensors to form an intermediary layer.
If you don't force the padded tensors into a Keras layer, attributes will be missing:
# AttributeError: 'Tensor' object has no attribute '_keras_history'
Which you can hack by just adding the attribute from the layer before we padded:
#layer6_output._keras_history = layer6._keras_history
Unfortunately, I still ran into other errors.
Perhaps you can post a new question on StackOverflow asking how to to this, if you can find anything. I did have a quick try using the idea of creating two graphs and then joining them, but didn't succeed.
$endgroup$
$begingroup$
There is more info on the disconneted graph error here.
$endgroup$
– n1k31t4
Jun 28 '18 at 11:26
add a comment |
$begingroup$
If you goal is simply to halve the size of your filters, you could think about using some different methods other than padding, such as dilated convolutions. Have a look at this paper for some ideas and nice explanations with pictures. Just thinking about your dimensions quickly, I am not sure you could go from 14 to 7 very easily. getting to 8 or 5 is simple enough though.
A trick few Keras users know is that you can mix in Tensorflow operations directly from the Tensorflow library.
In TF there is a function called pad
, which allows you to specify the padding manually on each side of a tensor. There are also options to say whether the padding is done with zeros, or if the values inside your original tensor are repeated/mirrored (using the mode
argument).
You could try using this to pad the layers. I can show you how to pad the tensors to get the effect you want:
from keras.models import Sequential, Model
from keras.layers import (Input, Conv2D, MaxPooling2D,
Flatten, Dense, Reshape, Lambda)
import tensorflow as tf
input_shape = (448, 448, 3)
batch_shape = (None,) + input_shape
raw_input = tf.placeholder(dtype='float16', shape=batch_shape)
paddings = tf.constant([[0, 0], # the batch size dimension
[3, 3], # top and bottom of image
[3, 3], # left and right
[0, 0]]) # the channels dimension
padded_input = tf.pad(raw_input, paddings, mode='CONSTANT',
constant_values=0.0) # pads with 0 by default
padded_shape = padded_input.shape # (454, 454, 3) because we add 2*3 padding
input_layer = Input(padded_shape, batch_shape, tensor=padded_input)
layer0 = Conv2D(192, kernel_size = (3,3), padding='valid')(input_layer)
layer1 = MaxPooling2D(pool_size=(2, 2), strides = 2)(layer0)
layer2 = Conv2D(192, kernel_size = (3,3), padding='valid')(layer1)
layer3 = MaxPooling2D(pool_size = (2,2),strides = 2)(layer2)
layer4 = Conv2D(512, kernel_size = (3,3), padding='valid')(layer3)
layer5 = MaxPooling2D(pool_size = (2,2), strides = 2)(layer4)
layer6 = Conv2D(256, kernel_size = (1,1), padding='valid')(layer5)
# layer6.shape --> [Dimension(None), Dimension(55), Dimension(55), Dimension(256)]
layer6_padded = tf.pad(layer6, paddings, mode='CONSTANT')
layer6_output = Input(input_shape=layer6_padded.shape)(layer6_padded)
# This will end up giving this error at compilation:
# RuntimeError: Graph disconnected: ...,
layer7 = Conv2D(1024, kernel_size=(3, 3), strides=2)(layer6_output)
layer8 = Flatten()(layer7)
layer9 = Dense(4096)(layer7)
layer10 = Dense(7*7*30)(layer8)
output_layer = Reshape((7, 7, 30))(layer10)
# The following both fail to get the graph as we would like it
model = Model(inputs=[input_layer], outputs=[output_layer])
#model = Model(inputs=[input_layer, layer6_output], outputs=[output_layer])
model.compile('adam', 'mse')
model.summary()
I have been unable to then bring this tensor back into the Keras model (as a layer, which is required) because the standard way of using the Input
object forces it to be the entry point of the computational graph, but we want the padded tensors to form an intermediary layer.
If you don't force the padded tensors into a Keras layer, attributes will be missing:
# AttributeError: 'Tensor' object has no attribute '_keras_history'
Which you can hack by just adding the attribute from the layer before we padded:
#layer6_output._keras_history = layer6._keras_history
Unfortunately, I still ran into other errors.
Perhaps you can post a new question on StackOverflow asking how to to this, if you can find anything. I did have a quick try using the idea of creating two graphs and then joining them, but didn't succeed.
$endgroup$
$begingroup$
There is more info on the disconneted graph error here.
$endgroup$
– n1k31t4
Jun 28 '18 at 11:26
add a comment |
$begingroup$
If you goal is simply to halve the size of your filters, you could think about using some different methods other than padding, such as dilated convolutions. Have a look at this paper for some ideas and nice explanations with pictures. Just thinking about your dimensions quickly, I am not sure you could go from 14 to 7 very easily. getting to 8 or 5 is simple enough though.
A trick few Keras users know is that you can mix in Tensorflow operations directly from the Tensorflow library.
In TF there is a function called pad
, which allows you to specify the padding manually on each side of a tensor. There are also options to say whether the padding is done with zeros, or if the values inside your original tensor are repeated/mirrored (using the mode
argument).
You could try using this to pad the layers. I can show you how to pad the tensors to get the effect you want:
from keras.models import Sequential, Model
from keras.layers import (Input, Conv2D, MaxPooling2D,
Flatten, Dense, Reshape, Lambda)
import tensorflow as tf
input_shape = (448, 448, 3)
batch_shape = (None,) + input_shape
raw_input = tf.placeholder(dtype='float16', shape=batch_shape)
paddings = tf.constant([[0, 0], # the batch size dimension
[3, 3], # top and bottom of image
[3, 3], # left and right
[0, 0]]) # the channels dimension
padded_input = tf.pad(raw_input, paddings, mode='CONSTANT',
constant_values=0.0) # pads with 0 by default
padded_shape = padded_input.shape # (454, 454, 3) because we add 2*3 padding
input_layer = Input(padded_shape, batch_shape, tensor=padded_input)
layer0 = Conv2D(192, kernel_size = (3,3), padding='valid')(input_layer)
layer1 = MaxPooling2D(pool_size=(2, 2), strides = 2)(layer0)
layer2 = Conv2D(192, kernel_size = (3,3), padding='valid')(layer1)
layer3 = MaxPooling2D(pool_size = (2,2),strides = 2)(layer2)
layer4 = Conv2D(512, kernel_size = (3,3), padding='valid')(layer3)
layer5 = MaxPooling2D(pool_size = (2,2), strides = 2)(layer4)
layer6 = Conv2D(256, kernel_size = (1,1), padding='valid')(layer5)
# layer6.shape --> [Dimension(None), Dimension(55), Dimension(55), Dimension(256)]
layer6_padded = tf.pad(layer6, paddings, mode='CONSTANT')
layer6_output = Input(input_shape=layer6_padded.shape)(layer6_padded)
# This will end up giving this error at compilation:
# RuntimeError: Graph disconnected: ...,
layer7 = Conv2D(1024, kernel_size=(3, 3), strides=2)(layer6_output)
layer8 = Flatten()(layer7)
layer9 = Dense(4096)(layer7)
layer10 = Dense(7*7*30)(layer8)
output_layer = Reshape((7, 7, 30))(layer10)
# The following both fail to get the graph as we would like it
model = Model(inputs=[input_layer], outputs=[output_layer])
#model = Model(inputs=[input_layer, layer6_output], outputs=[output_layer])
model.compile('adam', 'mse')
model.summary()
I have been unable to then bring this tensor back into the Keras model (as a layer, which is required) because the standard way of using the Input
object forces it to be the entry point of the computational graph, but we want the padded tensors to form an intermediary layer.
If you don't force the padded tensors into a Keras layer, attributes will be missing:
# AttributeError: 'Tensor' object has no attribute '_keras_history'
Which you can hack by just adding the attribute from the layer before we padded:
#layer6_output._keras_history = layer6._keras_history
Unfortunately, I still ran into other errors.
Perhaps you can post a new question on StackOverflow asking how to to this, if you can find anything. I did have a quick try using the idea of creating two graphs and then joining them, but didn't succeed.
$endgroup$
If you goal is simply to halve the size of your filters, you could think about using some different methods other than padding, such as dilated convolutions. Have a look at this paper for some ideas and nice explanations with pictures. Just thinking about your dimensions quickly, I am not sure you could go from 14 to 7 very easily. getting to 8 or 5 is simple enough though.
A trick few Keras users know is that you can mix in Tensorflow operations directly from the Tensorflow library.
In TF there is a function called pad
, which allows you to specify the padding manually on each side of a tensor. There are also options to say whether the padding is done with zeros, or if the values inside your original tensor are repeated/mirrored (using the mode
argument).
You could try using this to pad the layers. I can show you how to pad the tensors to get the effect you want:
from keras.models import Sequential, Model
from keras.layers import (Input, Conv2D, MaxPooling2D,
Flatten, Dense, Reshape, Lambda)
import tensorflow as tf
input_shape = (448, 448, 3)
batch_shape = (None,) + input_shape
raw_input = tf.placeholder(dtype='float16', shape=batch_shape)
paddings = tf.constant([[0, 0], # the batch size dimension
[3, 3], # top and bottom of image
[3, 3], # left and right
[0, 0]]) # the channels dimension
padded_input = tf.pad(raw_input, paddings, mode='CONSTANT',
constant_values=0.0) # pads with 0 by default
padded_shape = padded_input.shape # (454, 454, 3) because we add 2*3 padding
input_layer = Input(padded_shape, batch_shape, tensor=padded_input)
layer0 = Conv2D(192, kernel_size = (3,3), padding='valid')(input_layer)
layer1 = MaxPooling2D(pool_size=(2, 2), strides = 2)(layer0)
layer2 = Conv2D(192, kernel_size = (3,3), padding='valid')(layer1)
layer3 = MaxPooling2D(pool_size = (2,2),strides = 2)(layer2)
layer4 = Conv2D(512, kernel_size = (3,3), padding='valid')(layer3)
layer5 = MaxPooling2D(pool_size = (2,2), strides = 2)(layer4)
layer6 = Conv2D(256, kernel_size = (1,1), padding='valid')(layer5)
# layer6.shape --> [Dimension(None), Dimension(55), Dimension(55), Dimension(256)]
layer6_padded = tf.pad(layer6, paddings, mode='CONSTANT')
layer6_output = Input(input_shape=layer6_padded.shape)(layer6_padded)
# This will end up giving this error at compilation:
# RuntimeError: Graph disconnected: ...,
layer7 = Conv2D(1024, kernel_size=(3, 3), strides=2)(layer6_output)
layer8 = Flatten()(layer7)
layer9 = Dense(4096)(layer7)
layer10 = Dense(7*7*30)(layer8)
output_layer = Reshape((7, 7, 30))(layer10)
# The following both fail to get the graph as we would like it
model = Model(inputs=[input_layer], outputs=[output_layer])
#model = Model(inputs=[input_layer, layer6_output], outputs=[output_layer])
model.compile('adam', 'mse')
model.summary()
I have been unable to then bring this tensor back into the Keras model (as a layer, which is required) because the standard way of using the Input
object forces it to be the entry point of the computational graph, but we want the padded tensors to form an intermediary layer.
If you don't force the padded tensors into a Keras layer, attributes will be missing:
# AttributeError: 'Tensor' object has no attribute '_keras_history'
Which you can hack by just adding the attribute from the layer before we padded:
#layer6_output._keras_history = layer6._keras_history
Unfortunately, I still ran into other errors.
Perhaps you can post a new question on StackOverflow asking how to to this, if you can find anything. I did have a quick try using the idea of creating two graphs and then joining them, but didn't succeed.
edited Jun 28 '18 at 11:47
answered Jun 28 '18 at 11:23
n1k31t4n1k31t4
6,7012421
6,7012421
$begingroup$
There is more info on the disconneted graph error here.
$endgroup$
– n1k31t4
Jun 28 '18 at 11:26
add a comment |
$begingroup$
There is more info on the disconneted graph error here.
$endgroup$
– n1k31t4
Jun 28 '18 at 11:26
$begingroup$
There is more info on the disconneted graph error here.
$endgroup$
– n1k31t4
Jun 28 '18 at 11:26
$begingroup$
There is more info on the disconneted graph error here.
$endgroup$
– n1k31t4
Jun 28 '18 at 11:26
add a comment |
Thanks for contributing an answer to Data Science Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdatascience.stackexchange.com%2fquestions%2f33725%2fpadding-in-keras-with-output-half-sized-input%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
$begingroup$
What do you mean by half the size of your input? which input?
$endgroup$
– n1k31t4
Jun 27 '18 at 14:37
$begingroup$
Input image is of the form (448,448,3) so in order to have (224,224,64) we use 64 kernels of size (7,7) and padding = 3 and strides = 2. 224 is half the size of 448. Also, from (14,14,1024) to (7,7,1024) we use padding = 3 and strides = 2. Seven is half of 14.
$endgroup$
– Alem
Jun 27 '18 at 15:15