+
Skip to content

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

Merged
merged 39 commits into from
Mar 30, 2023
Merged

Conversation

opfromthestart
Copy link
Contributor

@opfromthestart opfromthestart commented Mar 23, 2023

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 the Conv2D<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

    • Cpu
    • Cuda
  • Add bilinear implementation

    • Cpu
    • Cuda
  • Add Upscale2D module

  • Add Upscale2DBy module

  • Add convtrans2d interface operations

  • Add implementations

    • Cpu
    • Cuda
  • Add ConvTrans2D

Comment on lines 80 to 85
impl<
C: Dim,
const H: usize,
const W: usize,
const OH: usize,
const OW: usize,
Copy link
Owner

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)) -> ...;
}

Copy link
Contributor Author

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.

Comment on lines 176 to 177
Meth = nearest_upscale2d,
TryMeth = try_nearest_upscale2d
Copy link
Owner

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

Copy link
Contributor Author

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.

@coreylowman
Copy link
Owner

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.

Copy link
Owner

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?

Copy link
Contributor Author

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

Copy link
Contributor Author

@opfromthestart opfromthestart Mar 23, 2023

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.

@opfromthestart
Copy link
Contributor Author

opfromthestart commented Mar 23, 2023

It may be easier as multiple PRs but it isn't really usable until all of those are done, so I think it makes more sense to just have a large PR with all of it.

@opfromthestart
Copy link
Contributor Author

I think this is now officially in the tesing phase, all of the things that needed done are done.

@opfromthestart opfromthestart changed the title [WIP] Upscale2D and ConvTrans2d Upscale2D and ConvTrans2d Mar 24, 2023
@coreylowman
Copy link
Owner

Awesome work, I'll check this out tomorrow!

Copy link
Owner

@coreylowman coreylowman left a 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;
Copy link
Owner

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

Copy link
Contributor Author

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.

Copy link
Owner

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);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Comment on lines 26 to 27
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]);
Copy link
Owner

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be yes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fixed.

Comment on lines +81 to +83
while (oh_s*h_scale < y) {
oh_s++;
}
Copy link
Owner

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?

Copy link
Contributor Author

@opfromthestart opfromthestart Mar 28, 2023

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() {
Copy link
Owner

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

Copy link
Contributor Author

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?

Copy link
Owner

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 and others added 12 commits March 27, 2023 21:20
Co-authored-by: Corey Lowman <coreylowman@users.noreply.github.com>
Co-authored-by: Corey Lowman <coreylowman@users.noreply.github.com>
Co-authored-by: Corey Lowman <coreylowman@users.noreply.github.com>
Co-authored-by: Corey Lowman <coreylowman@users.noreply.github.com>
@coreylowman
Copy link
Owner

@opfromthestart looks like this contains the changes for leakyrelu/prelu, can you remove those so they stay separate?

Copy link
Owner

@coreylowman coreylowman left a 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:

  1. Updating conv transpose kernels & launching based on recent updates to conv2d ones
  2. Making both conv transpose & upscale compatible with runtime dimensions

@coreylowman coreylowman merged commit ec72be1 into coreylowman:main Mar 30, 2023
@coreylowman
Copy link
Owner

Awesome work @opfromthestart!! Super great contribution 🚀

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

Successfully merging this pull request may close these issues.

Add upsample and conv-transpose operations
2 participants
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载