-
-
Notifications
You must be signed in to change notification settings - Fork 104
Upscale2D and ConvTrans2d #603
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
Upscale2D and ConvTrans2d #603
Conversation
PReLU forward and backward now working properly
Actually runs now
Changed some defaults to match Pytorch
just a normal pull
src/tensor_ops/upscale2d/mod.rs
Outdated
impl< | ||
C: Dim, | ||
const H: usize, | ||
const W: usize, | ||
const OH: usize, | ||
const OW: usize, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm actually thinking we don't need const dimensions for upscale. I think we can take the approach we have with broadcast, where we do:
trait Upscale<E> {
fn upscale2d<OH: ConstDim, OW: ConstDim>(self) -> ...;
fn try_upscale2d<OH: ConstDim, OW: ConstDim>(self) -> ...;
fn upscale2d_like<OH: Dim, OW: Dim>(self, size: (OH, OW)) -> ...;
fn try_upscale2d_like<OH: Dim, OW: Dim>(self, size: (OH, OW)) -> ...;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the trait yeah, the module still will though.
src/tensor_ops/upscale2d/mod.rs
Outdated
Meth = nearest_upscale2d, | ||
TryMeth = try_nearest_upscale2d |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we support other options for how to upscale? Could accept an enum, but that'd be much more complex of an implementation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think having an Upscale operation could be a trait, which is then implemented on Nearest and Bilinear, I'd like at least those two.
I think we could probably separate these two into separate PRs if thats easier for you. And then adding nn layers for both can be separate PRs as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the conv transpose still WIP or is it all good for reviewing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is very WIP, I'm pretty sure that the implementation is still straight from Conv
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, it was actually much closer to the forward direction than I thought, all I had to do is switch the index calulating code between forward and backward. I have 2 tests written for it so far.
|
Uses trait bounds instead of individually names types. Formatting
This should be the last non-fix commit
I think this is now officially in the tesing phase, all of the things that needed done are done. |
Awesome work, I'll check this out tomorrow! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking great! Really coming along. Just a few changes that I think would help. Let me know if you want me to help and I can throw some PRs into your branch
@@ -256,6 +259,7 @@ pub mod modules { | |||
TransformerEncoder, TransformerEncoderBlock, | |||
}; | |||
pub use super::unbiased_linear::UnbiasedLinear; | |||
pub use super::upscale::Upscale2D; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need to add to the builders mod below as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did this for ConvTrans2D, but neither upscale has a builder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yeah, but currently builders re-exports modules if there's no existing builder for it. The intent is someone can either do use dfdx::modules::*
or dfdx::builders::*
and get everything either way.
|
||
#[cfg(feature = "nightly")] | ||
#[derive(Debug, Default, Clone)] | ||
pub struct Upscale2DBy<const H: usize, const W: usize = H, M: UpscaleMethod = NearestNeighbor>(M); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
float h_scale = ((float)(inp_strides[1]/inp_strides[2]))/(out_strides[1]/out_strides[2]); | ||
float w_scale = ((float)(inp_strides[2]/inp_strides[3]))/(out_strides[2]/out_strides[3]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you tried this with broadcasted tensors? Should this be using the shape instead of strides?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be yes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be fixed.
while (oh_s*h_scale < y) { | ||
oh_s++; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this size_t oh_s = y / h_scale + 1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dont think so if h_scale divides y.
/// print(x.grad) | ||
/// print(torch.swapaxes(w.grad, 0, 1)) | ||
/// ``` | ||
fn convtrans2d_test() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any thoughts on more easily writing tests & increasing code coverage for complex operations like conv2d & conv transpose? They are some of the more complicated ones to test (along with transformers), and the current method we have for testing leaves a lot to be desired
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think as long as the tests have a tensor with all dimensions of input and output >1 and both the output and grads match with pytorch, I think its fine. Were you thinking more along the lines of tests that don't rely on pytorch/ are randomly generated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah exactly, and in a way where we can test larger tensors. Mostly thinking about testing conv2d in cuda. The kernels are fairly complex, and some issues might not be caught unless we have fairly large sizes on things.
@opfromthestart looks like this contains the changes for leakyrelu/prelu, can you remove those so they stay separate? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me - once the prelu and leakyrelu are removed i'll merge! Will probably be a bunch of other updates to apply to this separately to this pr including:
- Updating conv transpose kernels & launching based on recent updates to conv2d ones
- Making both conv transpose & upscale compatible with runtime dimensions
Awesome work @opfromthestart!! Super great contribution 🚀 |
Fixes #574
Adds the two image operations.
To use upscale, add an
Upscale2D<OH, OW, UpscaleType>
(not yet done, but functionality is there) module, which will upscale the input image to a(B, C, OW, OH)
from a(B, C, W, H)
using a given type of upscaling (planned nearest neighbor and bilinear).It also will have an
Upscale2DBy<S>
module which will upscale the image by an integer factor.It will include a
ConvTrans2D<K,S,P>
module which will give the transpose of theConv2D<K,S,P>
operation, so having Conv2D then ConvTrans2D will result in having the same shape.I may need some help on other upscaling algorithms and the conv transpose implementation.
Add upscale2d interface operations
Add nearest neighbor implementation
Add bilinear implementation
Add Upscale2D module
Add Upscale2DBy module
Add convtrans2d interface operations
Add implementations
Add ConvTrans2D