# Convolution with a multi-layer kernel

**URL:** https://discourse.julialang.org/t/convolution-with-a-multi-layer-kernel/48162
**Category:** General Usage
**Tags:** flux
**Created:** [October 11, 2020, 2:47pm UTC](https://discourse.julialang.org/t/convolution-with-a-multi-layer-kernel/48162 "2020-10-11T14:47:33Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![martenlienen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/martenlienen/32/18572_2.png) [@martenlienen](https://discourse.julialang.org/u/martenlienen)
#### Post date: [October 11, 2020, 2:47pm UTC](https://discourse.julialang.org/t/convolution-with-a-multi-layer-kernel/48162/1 "2020-10-11T14:47:33Z")

</div>

I have a 2D input that I would like to run a convolutional model on. However, instead of using a matrix as a convolution kernel, I would like to use something like `Chain(Dense(3^2; 3^2, tanh), ...)` as a kernel. Since `conv2d` in NNlib uses a gemm routine internally, I don’t think I can use it for my purposes. Are there some useful functions that I overlooked to implement this or do I need to roll my own loop-based implementation?

---

<div class="post-metadata">

### Author: ![anon92994695](https://avatars.discourse-cdn.com/v4/letter/a/ce7236/32.png) [@anon92994695](https://discourse.julialang.org/u/anon92994695)
#### Post date: [October 11, 2020, 6:16pm UTC](https://discourse.julialang.org/t/convolution-with-a-multi-layer-kernel/48162/2 "2020-10-11T18:16:28Z")

</div>

Marten I am a little confused by your interest here.

So you would like the output of a chain to be convolved as a filter in a convolution operation?

I’ve never tried this but I don’t see why you couldn’t. Have you tried something like the following?

```nohighlight
a = Chain(Dense(3^2; 3^2, tanh), ...)
b = Conv2d(...)

b.weight = a(x)
b(z)

```

?

---

<div class="post-metadata">

### Author: ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)
#### Post date: [October 11, 2020, 6:24pm UTC](https://discourse.julialang.org/t/convolution-with-a-multi-layer-kernel/48162/3 "2020-10-11T18:24:43Z")

</div>

I was wondering whether the input to this Chain was supposed to be a view of 3x3 pixels, scanned over the array. But what happens to its output? What is `...`, what object does this Chain return?

---

<div class="post-metadata">

### Author: ![martenlienen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/martenlienen/32/18572_2.png) [@martenlienen](https://discourse.julialang.org/u/martenlienen)
#### Post date: [October 11, 2020, 8:27pm UTC](https://discourse.julialang.org/t/convolution-with-a-multi-layer-kernel/48162/4 "2020-10-11T20:27:37Z")

</div>

I just tried and it does not work because `Conv.weight` needs to be of type `Array{Float32,4}`.

---

<div class="post-metadata">

### Author: ![martenlienen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/martenlienen/32/18572_2.png) [@martenlienen](https://discourse.julialang.org/u/martenlienen)
#### Post date: [October 11, 2020, 8:29pm UTC](https://discourse.julialang.org/t/convolution-with-a-multi-layer-kernel/48162/5 "2020-10-11T20:29:35Z")

</div>

In a normal convolutional layer, I map each element with it’s surrounding let’s say 3x3 block to a new value with the filter matrix. I would like to do the same thing but instead of using a matrix, I would like to apply a general neural network at each step.

---

<div class="post-metadata">

### Author: ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)
#### Post date: [October 11, 2020, 8:30pm UTC](https://discourse.julialang.org/t/convolution-with-a-multi-layer-kernel/48162/6 "2020-10-11T20:30:36Z")

</div>

You can emulate “convolution with a chain of dense layers” by using 1x1 conv layers.  
Convolution with `Chain( Dense(3*3, c1), Dense(c1, c2), Dense(c2, c3))` is equivalent to `Chain(Conv((3,3), 1 => c1), Conv((1,1), c1 => c2), Conv((1,1), c2 => c3))`

---

<div class="post-metadata">

### Author: ![anon92994695](https://avatars.discourse-cdn.com/v4/letter/a/ce7236/32.png) [@anon92994695](https://discourse.julialang.org/u/anon92994695)
#### Post date: [October 11, 2020, 8:51pm UTC](https://discourse.julialang.org/t/convolution-with-a-multi-layer-kernel/48162/7 "2020-10-11T20:51:19Z")

</div>

There is a way to solve that problem. I believe `reshape`, or `permutedims` will do the trick.

Googling found this, maybe it will help you:[julia - How do I add a dimension to an array? (opposite of `squeeze`) - Stack Overflow](https://stackoverflow.com/questions/42312319/how-do-i-add-a-dimension-to-an-array-opposite-of-squeeze)

---

<div class="post-metadata">

### Author: ![martenlienen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/martenlienen/32/18572_2.png) [@martenlienen](https://discourse.julialang.org/u/martenlienen)
#### Post date: [October 12, 2020, 8:41am UTC](https://discourse.julialang.org/t/convolution-with-a-multi-layer-kernel/48162/8 "2020-10-12T08:41:20Z")

</div>

I like that solution. I only need dense layers in my convolution anyway and this way I can reuse existing layers.
