Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add insertdims method which is inverse to dropdims#45793

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
LilithHafner merged 29 commits intoJuliaLang:masterfromroflmaostc:master
Aug 2, 2024

Conversation

roflmaostc
Copy link
Contributor

@roflmaostcroflmaostc commentedJun 23, 2022
edited
Loading

Hi all!

My first attempt to add a method which we think is quite helpful.
It is similar todropdims but basically the inverse to it. I tried to follow the implementation ofdropdims. It also looks good in@code_warntype.

I would be happy to receive some feedback and suggestions :)

Best,

Felix

Example:

julia> a= [12;34]2×2 Matrix{Int64}:1234julia> b=insertdims(a, dims=(1,3))1×2×2×1 Array{Int64,4}:[:, :,1,1]=13[:, :,2,1]=24julia> b[1,1,1,1]=5; a2×2 Matrix{Int64}:5234julia> b=insertdims(a, dims=(1,1))1×1×2×2 Array{Int64,4}:[:, :,1,1]=5[:, :,2,1]=3[:, :,1,2]=2[:, :,2,2]=4julia> b=insertdims(a, dims=(1,2))1×2×1×2 Array{Int64,4}:[:, :,1,1]=53[:, :,1,2]=24

Pangoraw and mbauman reacted with heart emoji
@brenhinkellerbrenhinkeller added the arrays[a, r, r, a, y, s] labelNov 17, 2022
@roflmaostc
Copy link
ContributorAuthor

Haven't looked into the code since then.
One disadvantage of the implementation is that it only works with sorted tuples. But there is not nice way of sorting tuples at the moment so I'm not quite sure how to tackle this best

@roflmaostc
Copy link
ContributorAuthor

@mkitti had a great solution which has slightly differently semantics

julia>functioninsertdims(A; dims)           idx=ntuple(ndims(A)+length(dims))do iif i dims                   [CartesianIndex()]else                   (:)endend@view A[idx...]endinsertdims (genericfunction with1 method)julia> A=zeros(5,4,3);julia>size(insertdims(A; dims= (1,3,6)))(1,5,1,4,3,1)julia>dropdims(b, dims=(1,2))2×2 Matrix{Int64}:1234julia> b=insertdims(a, dims=(1,2))1×1×2×2 Array{Int64,4}:[:, :,1,1]=1[:, :,2,1]=3[:, :,1,2]=2[:, :,2,2]=4julia>dropdims(b, dims=(1,2))2×2 Matrix{Int64}:1234julia> b=insertdims(a, dims=(1,2))1×1×2×2 Array{Int64,4}:[:, :,1,1]=1[:, :,2,1]=3[:, :,1,2]=2[:, :,2,2]=4
mkitti reacted with thumbs up emoji

@aplavin
Copy link
Contributor

Not to discourage/criticize this PR, but: such functionality is available with a nice, consistent, and general syntax in a package:

julia>using Accessorsjulia> A=zeros(5,4,3);# insert singleton dimensionjulia> B=@insertsize(A)[1]=1;julia>size(B)(1,5,4,3)# delete singleton dimension:julia> C=@deletesize(B)[1];julia>size(C)(5,4,3)

Multidim insert/delete not implemented, but can potentially be added as well.

mkitti reacted with thumbs up emoji

@roflmaostc
Copy link
ContributorAuthor

That looks really cool!!

I like that it is implemented but I think it still would be nice to haveinsertdims sincedropdims is already existing.

@aplavin
Copy link
Contributor

aplavin commentedFeb 1, 2023
edited
Loading

That looks really cool!!

Yeah, and the best part - it's all totally composable!

julia> A=zeros(5,4,3,1);# drop singleton dimension, wherever it is:julia> B=@deletesize(A)|> _[findfirst(==(1), _)];julia>size(B)(5,4,3)# insert singleton dimension last:julia> C=@insertlast(size(A))=1);julia>size(C)(5,4,3,1,1)
roflmaostc reacted with rocket emoji

@mkitti
Copy link
Contributor

@mkitti had a great solution which has slightly differently semantics

julia>functioninsertdims(A; dims)           idx=ntuple(ndims(A)+length(dims))do iif i dims                   [CartesianIndex()]else                   (:)endend@view A[idx...]endinsertdims (genericfunction with1 method)

One thing I like about the semantics of my implementation is that the following is mostly true:

julia> A = rand(3,4,5); dims = (1,4,6);julia> dropdims(insertdims(A; dims); dims) == Atrue

There might be a flaw though:

julia> size(insertdims(A; dims=7))(3, 4, 5, 1)

Perhaps we need the following

julia>functioninsertdims(A; dims)           idx=ntuple(maximum((ndims(A)+length(dims), dims...)))do iif i dims                   [CartesianIndex()]else                   (:)endend@view A[idx...]endinsertdims (genericfunction with1 method)julia>size(insertdims(A; dims=7))(3,4,5,1,1,1,1)

@mkitti
Copy link
Contributor

From triage, WWMBD: what would@mbauman do?

Thetraditional answer is just spellinsertdims in the following way:

const newaxis = [CartesianIndex()]@view array[:, newaxis, :, ...]

An alternative to this pull request would be document the above better and/or define the above constant. Has any thinking changed?

@roflmaostc
Copy link
ContributorAuthor

Perhaps we need the following

julia>functioninsertdims(A; dims)           idx=ntuple(maximum((ndims(A)+length(dims), dims...)))do iif i dims                   [CartesianIndex()]else                   (:)endend@view A[idx...]endinsertdims (genericfunction with1 method)julia>size(insertdims(A; dims=7))(3,4,5,1,1,1,1)

That's not type stable, is it?

cossio reacted with thumbs up emoji

@mkitti
Copy link
Contributor

Perhaps we need the following

julia>functioninsertdims(A; dims)           idx=ntuple(maximum((ndims(A)+length(dims), dims...)))do iif i dims                   [CartesianIndex()]else                   (:)endend@view A[idx...]endinsertdims (genericfunction with1 method)julia>size(insertdims(A; dims=7))(3,4,5,1,1,1,1)

That's not type stable, is it?

We could consider a type stable version in some circumstances, such as providingdims as aVal.

@mbauman
Copy link
Member

I think doing this as a reshape operation as initially proposed here makes far more sense than an indexing one. The reshape is going to besignificantly easier on both type stability and preserving strided-ness... and it really is more reshape-y than index-y.

The only reason to use indexing operations is to match thesurface of numpy'snp.newaxis idioms. But I thinkinsertdims is a better API in any case — and then its implementation can just be whatever makes the most sense.

roflmaostc reacted with thumbs up emoji

@mbaumanmbauman added needs newsA NEWS entry is required for this change featureIndicates new feature / enhancement requests labelsMay 30, 2024
@roflmaostc
Copy link
ContributorAuthor

The only issue in my implementation was that it required a sorted input for the inserted dims.
Is there a way to sort tuples with Julia Bases in the meantime?

@LilithHafner
Copy link
Member

Is there a way to sort tuples with Julia Bases in the meantime?

If someone (could it be you?) reviews#54494 there will be

@roflmaostc
Copy link
ContributorAuthor

If@mbauman thinks that requiring sorted tuples as input is fine, we could lift that requirement also later.

@roflmaostc
Copy link
ContributorAuthor

roflmaostc commentedMay 31, 2024
edited
Loading

In NumPy the convention is different:

>>>x=np.array([[1,2], [3,4]])>>>np.expand_dims(x,axis=(0,1,3)).shape(1,1,2,1,2)

Personally I find this a bit confusing since it counts the inserted dims too.

@mkitti
Copy link
Contributor

mkitti commentedJun 2, 2024
edited
Loading

Numpy seems to match the semantics I proposed earlier. I understand this in terms of where I want the singleton dimensions to be in the final result.

@roflmaostcroflmaostc changed the title[WIP] Add insertdims method which is inverse to dropdimsAdd insertdims method which is inverse to dropdimsJul 11, 2024
@nsajkonsajko added the needs docsDocumentation for this change is required labelJul 25, 2024
@nsajko
Copy link
Contributor

The doc string should be included into the docs:

diff --git a/doc/src/base/arrays.md b/doc/src/base/arrays.mdindex ccfb237..66fe5c7 100644--- a/doc/src/base/arrays.md+++ b/doc/src/base/arrays.md@@ -138,6 +138,7 @@ Base.parentindices Base.selectdim Base.reinterpret Base.reshape+Base.insertdims Base.dropdims Base.vec Base.SubArray
roflmaostc reacted with thumbs up emoji

@roflmaostc
Copy link
ContributorAuthor

roflmaostc commentedJul 26, 2024
edited
Loading

It also claims to be the inverse ofdropdims but looking at these examples it clearly isn't.

I thought in the following way:insertdims insert singleton dimensions,dropdims removes them.

The other way of doing it, would be

julia>size(dropdims(ones((1,1,2,3,1,4)), dims=(1,2,5)))(2,3,4)julia>insertdims2(ones((2,3,4)), dims=(1,2,5))(1,1,2,3,1,4)

For me this requires some acrobatics, where the dimension with size 4 ends up, because I need to insert thedims virtually in my head. Would it be before or after the singleton dimension?
On the other hand with my convention, it's immediately clear where the singleton dimensions are (with respect to the input dimensions).

Does it make sense?

@aplavin
Copy link
Contributor

The way it works right now, it inserts singleton dimensions at the position of the dims indicated with respect to the initial input array dimensions.

Hmm, I see... That definitely wasn't my first intuition :)
Maybe, if keeping this semantics, it's cleaner to say "add singleton dimensions before dimensions numberdims in the original array" or something...

But also, maybe the "inverse todropdims" semantics is cleaner? Whenever possible.
This corresponds to interpretingdims as indices in the resulting array dimensions.
Also, nicely meshes with potential extensions by various "named arrays":dims=:mynewdim clearly corresponds to the resulting array.

LilithHafner and mcabbott reacted with thumbs up emoji

@roflmaostc
Copy link
ContributorAuthor

@LilithHafner thanks for your suggestions. To be consistent withpermutedims, I changed it.

I also included your docstring and your tests.

LilithHafner reacted with thumbs up emoji

roflmaostcand others added2 commitsJuly 27, 2024 21:14
Co-authored-by: Lilith Orion Hafner <lilithhafner@gmail.com>
Copy link
Contributor

@nsajkonsajko left a comment

Choose a reason for hiding this comment

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

The type system doesn't ensureN isa Int, but we can be explicit about this to help Julia's abstract type inference.

@LilithHafner
Copy link
Member

Triage is happy with adding this new function and exporting it because it mirrors dropdims.

roflmaostc reacted with heart emoji

@LilithHafnerLilithHafner removed the triageThis should be discussed on a triage call labelAug 1, 2024
roflmaostcand others added3 commitsAugust 1, 2024 17:18
Co-authored-by: Lilith Orion Hafner <lilithhafner@gmail.com>
Co-authored-by: Lilith Orion Hafner <lilithhafner@gmail.com>
Co-authored-by: Lilith Orion Hafner <lilithhafner@gmail.com>
@roflmaostc
Copy link
ContributorAuthor

ok 🆒
Let me know if I can do more.

Co-authored-by: Mark Kittisopikul <mkitti@users.noreply.github.com>
@LilithHafnerLilithHafner merged commit2635dea intoJuliaLang:masterAug 2, 2024
4 of 7 checks passed
@LilithHafner
Copy link
Member

Thank you@roflmaostc! I appreciate your commitment and follow-through.

roflmaostc and xlxs4 reacted with heart emoji

lazarusA pushed a commit to lazarusA/julia that referenced this pull requestAug 17, 2024
Example:```juliajulia> a = [1 2; 3 4]2×2 Matrix{Int64}: 1  2 3  4julia> b = insertdims(a, dims=(1,4))1×2×2×1 Array{Int64, 4}:[:, :, 1, 1] = 1  3[:, :, 2, 1] = 2  4julia> b[1,1,1,1] = 5; a2×2 Matrix{Int64}: 5  2 3  4julia> b = insertdims(a, dims=(1,2))1×1×2×2 Array{Int64, 4}:[:, :, 1, 1] = 5[:, :, 2, 1] = 3[:, :, 1, 2] = 2[:, :, 2, 2] = 4julia> b = insertdims(a, dims=(1,3))1×2×1×2 Array{Int64, 4}:[:, :, 1, 1] = 5  3[:, :, 1, 2] = 2  4```---------Co-authored-by: Neven Sajko <s@purelymail.com>Co-authored-by: Lilith Orion Hafner <lilithhafner@gmail.com>Co-authored-by: Mark Kittisopikul <mkitti@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@mbaumanmbaumanmbauman approved these changes

@aplavinaplavinaplavin left review comments

@nsajkonsajkonsajko left review comments

@mkittimkittimkitti left review comments

@LilithHafnerLilithHafnerLilithHafner left review comments

Assignees
No one assigned
Labels
arrays[a, r, r, a, y, s]featureIndicates new feature / enhancement requests
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

7 participants
@roflmaostc@aplavin@mkitti@mbauman@LilithHafner@nsajko@brenhinkeller

[8]ページ先頭

©2009-2025 Movatter.jp