You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Convolutioneinx.dot("b (s * [ds])... [c_in->c_out]", x, weight, ds=4, c_out=64) # weight shape will be 'ds... c_in c_out'# Depthwise convolution with same weights per channeleinx.dot("b (s * [ds])... c", x, weight, ds=4) # weight shape will be 'ds...'# Depthwise convolution with different weights per channeleinx.dot("b (s * [ds])... [c->c]", x, weight, ds=4) # weight shape will be 'ds... c'# Explicit kernel shape:einx.dot("b (s * [ds])... c, [ds]... -> b s... c")
Unfolding:
# Extract local windows of size 'ds...' for each pixeleinx.rearrange("b (s * ds)... c"->bs... (ds...) c", x, ds=4)
Good
Retains the existing set of elementary operations. No new function names einx.{conv|unfold|mean_pool|max_pool|*_pool}.
Pooling resembles the existing option of using axis compositions:
einx.mean("b (s [ds])... c", x, ds=4) # Existing pooling with kernel_size=stride=4 (works only if evenly divisible)einx.mean("b (s * [ds])... c", x, ds=4) # New general pooling
1x1 convolution resembles the existing option of using a regular dot-product:
New type of notation which is hard to understand without checking the docs or tutorials. Using some kind of einx.conv(...) would be more expressive for anyone not familiar with einx notation.
Maybe unintuitive: (s * ds) does not refer to the result of a convolution between s and ds. It rather means: Convolving (s * ds) with ds will yield an axis s.
* star represents a convolution operator, but might look like it is a placeholder for other axes. It may or may not be better to use a different symbol, e.g. #, to avoid confusion.
Option 2: Just use []-brackets for spatial axes
Thinking through whether it would make sense to use []-brackets to mark spatial axes, and include kernel_size, stride and dilation as additional arguments to a function. This would define unfolding as part of the elementary operation.
The input channel axes should be marked since they represent an operation axis (might potentially include an implicit notation without these brackets similar to einx.dot). This would give something like:
einx.conv("b [h_in w_in] [c_in], [h_kernel w_kernel c_in] c_out -> b [h_out w_out] c_out", x, weight, stride=4)
# kernel_size is given from weight shape.# order of axes should match in all expressions since the axes do not have the same names (h_in vs h_kernel vs h_out).# c_in can be identified as a channel axis in the input because it appears in the weight expression, h_in and w_in don't.
Good
It is obvious for anyone not familiar with einx that einx.conv performs a convolution, and einx.pool performs pooling.
No new expression types that have to be learnt.
Bad
Convolution is tedious and hard to read compared to something like nn.Conv(features=64, kernel_size=4)(x)
Many new function names einx.{conv|unfold|mean_pool|max_pool|*_pool} and larger API.
No obvious commonality between pooling, convolution and unfolding.
Cannot implicitly determine the weight shape similar to einx.dot:
einx.dot("... [c1] -> ... [c2]", x, einn.param(), c2=64)
# -> weight shape is "c1 c2"einx.conv("b [h w] [c_in] -> b [h_out w_out] [c_out]", x, einn.param(), ...)
# -> Which axes are spatial axes, which axes are channel axes?
New pooling operation looks different from existing pooling operation:
einx.mean("b (s [ds])... c", x, ds=4) # Existing pooling with kernel_size=stride=4 (works only if evenly divisible)einx.pool("b [...] c", x, ds=4) # New general pooling
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Considering some potential options here to support convolutions (and related operations like pooling, fold/ unfold) using einx notation.
Option 1: Introduce expression for folded axis
Introduce
(a * b)as a single axis that can be unfolded into axesaandbsimilar to
(a b)representing a single axis that can be decomposed intoaandb, and(a + b)representing a single axis that can be split intoaandb.This would allow expressing different operations using existing functions:
Pooling: (i.e. unfolding + reduction, computed jointly using efficient backend ops)
Convolution: (i.e. unfolding + dot product, computed jointly using efficient backend ops)
Unfolding:
Good
einx.{conv|unfold|mean_pool|max_pool|*_pool}.Bad
einx.conv(...)would be more expressive for anyone not familiar with einx notation.(s * ds)does not refer to the result of a convolution betweensandds. It rather means: Convolving(s * ds)withdswill yield an axiss.*star represents a convolution operator, but might look like it is a placeholder for other axes. It may or may not be better to use a different symbol, e.g.#, to avoid confusion.Option 2: Just use
[]-brackets for spatial axesThinking through whether it would make sense to use
[]-brackets to mark spatial axes, and includekernel_size,strideanddilationas additional arguments to a function. This would define unfolding as part of the elementary operation.Pooling:
Convolution:
The input channel axes should be marked since they represent an operation axis (might potentially include an implicit notation without these brackets similar to
einx.dot). This would give something like:Good
einx.convperforms a convolution, andeinx.poolperforms pooling.Bad
nn.Conv(features=64, kernel_size=4)(x)einx.{conv|unfold|mean_pool|max_pool|*_pool}and larger API.einx.dot:Beta Was this translation helpful? Give feedback.
All reactions