keras-js icon indicating copy to clipboard operation
keras-js copied to clipboard

Convolution Layer error

Open Reichenbachian opened this issue 6 years ago • 9 comments

On a deep cnn, I'm getting the error "Incompatible combination of dilation_rate with strides." The model works without problems within keras. Is padding not implemented? Is there a workaround?

Architecture

model = Sequential()
model.add(Conv1D(32, 64, strides=2, padding='same', input_shape=inputshape))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPooling1D(pool_size=8))

model.add(Conv1D(64, 32, strides=2, padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPooling1D(pool_size=8))

model.add(Conv1D(128, 16, strides=2, padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))

model.add(Conv1D(256, 8, strides=2, padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))

model.add(Flatten())
model.add(Dense(128))
model.add(Dropout(p=0.5))

Tensorflow==1.1.0 Keras==2.0.4

Reichenbachian avatar Aug 02 '17 21:08 Reichenbachian

I think I see the problem. It's coming from

 if (dilation_rate !== 1 && strides !== 1) {
      // Currently, specifying any dilation_rate value != 1 is incompatible with specifying any stride value != 1
      // https://keras.io/layers/convolutional/#conv1d
      throw new Error(`${this.name} [Conv1D layer] Incompatible combination of dilation_rate with strides.`)
    }

But I think that the line dilation_rate !== 1 && strides !== 1 isn't correct.

The keras documentation says

dilation_rate: an integer or tuple/list of a single integer, specifying the dilation rate to use for dilated convolution. Currently, specifying any dilation_rate value != 1 is incompatible with specifying any strides value != 1.

It's a confusing sentence, but I think it means this... (dilation_rate !== 1 && strides == 1) || (dilation_rate == 1 && strides !== 1) I'll branch out and try it.

Reichenbachian avatar Aug 03 '17 13:08 Reichenbachian

@Reichenbachian Based on your architecture, shouldn't dilation_rate be 1 (default)? In which case, why is it throwing this error at all? Can you check your model architecture definition and see what dilation_rate for the Conv1D layers actually are?

Btw, I think the original conditional is correct; for strides/dilation_rate pairs, we should have the following:

1/1 -> no error
1/2 -> no error
2/1 -> no error
2/2 -> error

transcranial avatar Aug 03 '17 14:08 transcranial

Yeah. I reread your condition. I think the condition is correct. Which means that at some point before then, those numbers must have been changed. In the model.json file, all the convolution layers are

            "strides": [2],
            "dilation_rate": [1],

I tried printing the values before the error was thrown, but I'm unable to build keras-js on my computer. (Working on that now, but separate error).

Reichenbachian avatar Aug 03 '17 14:08 Reichenbachian

Ah I see, it's because keras is converting these to tuples internally: https://github.com/fchollet/keras/blob/master/keras/layers/convolutional.py#L104-L107, https://github.com/fchollet/keras/blob/master/keras/layers/convolutional.py#L153-L156

Will need to fix.

transcranial avatar Aug 03 '17 14:08 transcranial

I got it building. I put in

    if (dilation_rate !== 1 && strides !== 1) {
      // Currently, specifying any dilation_rate value != 1 is incompatible with specifying any stride value != 1
      // https://keras.io/layers/convolutional/#conv1d
      console.log("Dilation " + dilation_rate + " Strides" + strides + " " + (dilation_rate !== 1 && strides !== 1) + " " + (dilation_rate !== 1) + " " + (strides !== 1));
      console.log(typeof dilation_rate + " " + typeof strides)
      throw new Error(`${this.name} [Conv1D layer] Incompatible combination of dilation_rate with strides.`)
    }

It outputted Dilation 1 Strides2 true true true. Which is very confusing. I'm wondering if the types are screwed up. Checking now.

Reichenbachian avatar Aug 03 '17 15:08 Reichenbachian

Ah, so they're tuples. Just saw your response. I'll write a patch for now.

Reichenbachian avatar Aug 03 '17 16:08 Reichenbachian

Added

    if (Array.isArray(strides)) {
      this.strides = strides[0]
    }
    if (Array.isArray(dilation_rate)) {
      this.dilation_rate = dilation_rate[0]
    }

    if (Array.isArray(kernel_size)) {
      this.kernel_size = kernel_size[0]
    }

and

    var dilation_rate_temp = this.dilation_rate;
    const conv2dAttrs = {
      filters,
      kernel_size: [this.kernel_size, 1],
      strides: [this.strides, 1],
      padding,
      data_format: 'channels_first',
      dilation_rate_temp,
      activation,
      use_bias
    }
    this._conv2dAttrs = conv2dAttrs
    this._conv2d = new Conv2D(Object.assign(conv2dAttrs, { gpu: attrs.gpu }))
  }

It loaded without errors.

Reichenbachian avatar Aug 03 '17 16:08 Reichenbachian

Hi all, is this issue fixed right now? I cloned the repo the day before yesterday and got the same error for Conv1D:

[Conv1D layer: conv1d_1] Incompatible combination of dilation_rate with strides.

I am not sure if it is exactly the same problem, it would be awesome if we could fix this.

I started by analyzing the shapes of the Strides and Dilation (which are now named h and u?):

console.log("[UO] Strides=" + h)
console.log("[UO] Strides isArray=" + Array.isArray(h))
console.log("[UO] DilationRate=" + u)
console.log("[UO] DilationRate isArray=" + Array.isArray(u))
console.log("[UO] (1 !== h)=" + (1 !== h))
console.log("[UO] (1 !== u)=" + (1 !== u))

prints me:

[Log] [UO] Strides=1 (keras.min.js, line 8762)
[Log] [UO] Strides isArray=true (keras.min.js, line 8763)
[Log] [UO] DilationRate=1 (keras.min.js, line 8764)
[Log] [UO] DilationRate isArray=true (keras.min.js, line 8765)
[Log] [UO] (1 !== h)=true (keras.min.js, line 8766)
[Log] [UO] (1 !== u)=true (keras.min.js, line 8767)

which basically is the problem as far as I understood.

I first tried @Reichenbachian 's fix and added:

if (Array.isArray(h)) {
    h =h[0]
}
if (Array.isArray(u)) {
    u = u[0]
}

But this throws me:

Error: cwise: Arrays do not all have the same shape!

But there my knowledge ends and I am not sure if that is the problem I want (need) to solve or just a follow up mistake. It would be great if we could work on this.

Below some additional information regarding the surroundings:


My model architecture:

model = Sequential([
            Conv1D(3, 3, input_shape=(1024, 1,)),
            Conv1D(1, 3),
            Flatten(),
            Dense(32),
            Activation('relu'),
            Dense(13),
            Activation('softmax'),
        ])

The data flowing through has the shape (4000, 1024, 1).

Training is done within: this Docker image. With the version before the latest: Keras Version: 2.0.2 Tensorflow Version: 1.0.1

Data is loaded via jQuery:

$.getJSON( data_path + "spectrum.json", function( json ) {
  data = json.spectrum_00
 });

with spectrum.json looking like:

{"spectrum_00": [[6379], [2568], [2089], [1715], ...]}

see model.bin attached model.bin.zip

Nollde avatar Dec 14 '17 07:12 Nollde

I think I may have fixed it on my local machine and not submitted a PR. I'll do that today.

Reichenbachian avatar Dec 14 '17 12:12 Reichenbachian