Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[question] Why can't I build a cnn policy behaving like a mlp policy ? #456

Closed
vbelus opened this issue Aug 27, 2019 · 8 comments
Closed
Labels
question Further information is requested

Comments

@vbelus
Copy link

vbelus commented Aug 27, 2019

Hi, I hope this is the right place for this question.
I'm creating a custom policy for a project and for multiple reasons I wanted to build a convolutional neural network that's on paper the same as a mlp with three hidden layers [128, 64, 64].

My mlp policy is working fine, but I can't reproduce these results with a cnn policy, even though I've dug into the functions I use and it should work like a mlp.

Here is my custom cnn policy :
(n_arrays is 1 for now, this parameter is here because the reason I wanted to build a cnn extractor was to mimic multiple mlp extractors when my obs space was multiple arrays)

def custom_cnn(scaled_images, **kwargs):
    activ = tf.nn.relu
    n_arrays = scaled_images.shape[1]
    filter_width = scaled_images.shape[2]

    layer_1 = activ(conv(scaled_images, 'c1', n_filters=128, 
    filter_size=(1, filter_width), stride=1, init_scale=init_scale, **kwargs))
    layer_1 = tf.reshape(layer_1, [-1, n_arrays, 128, 1])

    layer_2 = activ(conv(layer_1, 'c2', n_filters=64, filter_size=(1, 128), 
    stride=1, init_scale=init_scale, **kwargs))
    layer_2 = tf.reshape(layer_2, [-1, n_arrays, 64, 1])

    layer_3 = activ(conv(layer_2, 'c3', n_filters=64, filter_size=(1, 64), 
    stride=1, init_scale=init_scale, **kwargs))
    layer_3 = tf.reshape(layer_3, [-1, n_arrays, 64, 1])
    layer_3 = conv_to_fc(layer_3)
    return layer_3

So basically each time I'm doing a convolution, it is on an image of shape (1, width), and I'm doing it with a kernel of shape (1, width), with n filters, which should be equivalent to a fully connected layer of size n.

However I get terrible results with such a policy compared to the mlp one.
What have I got wrong ? I'm positive I haven't made a stupid mistake about the shape of my arrays, so why are those two implementions so different during training ?

@araffin araffin added the question Further information is requested label Aug 27, 2019
@araffin
Copy link
Collaborator

araffin commented Aug 27, 2019

Hello,

I think this issue is related to your problem (1D Convolution): #436

it is on an image of shape (1, width),

When using a CNN policy, you have to make sure the input is an image and has values in [0, 255] (cf doc).
Normalization is done automatically and this can break your training if you provide input with the wrong value range.

@vbelus
Copy link
Author

vbelus commented Aug 28, 2019

Hi @araffin and thanks for your answer,
Where is it you can this information in the docs ? I can't find it.
Does that mean a simple scaling of my input will be enough ? And do the values need to be int ?

@araffin
Copy link
Collaborator

araffin commented Aug 28, 2019

Where is it you can this information in the docs ? I can't find it.

The information is here

Does that mean a simple scaling of my input will be enough ?

If you normalize the input, you have to deactivate the normalization using scale=False when calling the parent constructor (cf doc about custom policies or code).

And do the values need to be int ?

Values will be cast to float anyway

@jerabaul29
Copy link

So do you mean it is enough to just provide the float input data, and put scale=False, and then it should work? :)

@vbelus
Copy link
Author

vbelus commented Aug 28, 2019

@araffin will a self.scale=False after the super() call in my custom policy work, or do I need to rewrite the whole FeedForwardPolicy class ? scale not being an attribute you can pass when initializing the class.

@jerabaul29
Copy link

As fully convolutional networks are useful for many more applications than image analysis, it would be great to have a flag to disable this renormalization in an easy way for the user. Could this be done @araffin ? :)

@araffin
Copy link
Collaborator

araffin commented Aug 28, 2019

So do you mean it is enough to just provide the float input data, and put scale=False, and then it should work?

That depends on what you mean by "it works". Will you avoid to do a second normalization? yes. Will it succeed to solve the task? maybe not (you may need hyperparameter tuning). Also, CNN assumes some locality property on your input data (like images).
It seems that the data @vbelus is working on are not really images (1D vector) and usually mlp works fine on that type of data.

do I need to rewrite the whole FeedForwardPolicy class ?

It seems you need to either write a custom FeedForwardPolicy class (this should not be too hard) or make sure the data you provide look like images, so that the normalization that is applied does not break the learning.

As fully convolutional networks are useful for many more applications than image analysis

fully convolutional networks for RL? you mean convolution?
I agree for convolution that are not 2D.

The flag is set automatically because the CnnPolicy only uses conv 2D layers afterward, and in most cases when using RL, this correspond to images.
However, it could be good to add a 1D convolution/other convolution type as feature extractor (and maybe add an example of a CNN using 1D convolution in the documentation): this would have also the effect of disabling the normalization.
See here for what I'm talking about:

if feature_extraction == "cnn":

@vbelus
Copy link
Author

vbelus commented Aug 29, 2019

Thank you, creating a custom FeedForwardPolicy class to set scale to False indeed gives me results similar to mlp.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants