Skip to content
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

Should there always be a sample dimension? #127

Open
maxrjones opened this issue Nov 18, 2022 · 6 comments
Open

Should there always be a sample dimension? #127

maxrjones opened this issue Nov 18, 2022 · 6 comments
Labels
question Further information is requested

Comments

@maxrjones
Copy link
Member

What is your issue?

As shown in the section below, , there are a couple cases in which the batch generator will not include a sample dimension in the returned dataset/dataarray:

  1. If the number of dimensions specified in input_dims does not exceed the number of dimensions in the original dataset by more than one. In this case, the original dimension names will be retained as long as concat_input_dims=False.
  2. If all dimensions are included in input_dims and concat_input_dims=True. In this case, an extra dimension called input_batch is created along with the original dimensions appended with _input.

# Add a sample dimension if there's anything to get stacked
if (
generator.concat_input_dims
and (len(generator.ds.dims) - len(generator.input_dims)) == 0
):
expected_dims = {**{"input_batch": expected_sample_length}, **expected_dims}
elif (
generator.concat_input_dims
or (len(generator.ds.dims) - len(generator.input_dims)) > 1
):
expected_dims = {**{"sample": expected_sample_length}, **expected_dims}
else:
expected_dims = {
**non_specified_ds_dims,
**non_input_batch_dims,
**expected_dims,
}

Would it be better to always include a sample dimension in the output batches, for example by renaming the excluded dimension to sample for case 1?

@maxrjones maxrjones added the question Further information is requested label Nov 18, 2022
@cmdupuis3
Copy link

cmdupuis3 commented Jan 18, 2023

I'm looking at this again, and I think the way to understand my PoV is that I want the least friction between the for batch in bgen line and where I call my NN model (e.g., model.fit(...)). In my situation (case 1 I think), the lack of a sample dimension forces you to create a new sample dimension, and I would argue that this is non-trivial, for a few reasons:

  1. It's not obvious to a first-time user that there is a dimension mismatch
  2. When a first-time user's training loop inevitably fails, it's not obvious why there is a dimension mismatch
  3. Creating a new sample dimension requires you to name it something. Ideally it would have the same name as the dimension that was discarded, but in practice, it's probably arbitrary. However, these are things that I don't think a user should even need to think about.
  4. This situation seemingly creates an arbitrary state that the user must manage on their own.

Additionally, as per @weiji14's comments a while back, it's a much lower cognitive load to return an array with an extra sample dimension and use np.squeeze than it is to recreate a dimension inside the training loop.

@cmdupuis3
Copy link

As it so happens, there is a bug with xr.DataSet.expand_dims. You can see the bug report here: pydata/xarray#7456

@cmdupuis3
Copy link

It seems the xarray documentation is partially at fault, at least, according to them.

Apparently, there is no combination of xr.DataSet.expand_dims and xr.DataSet.transpose that will put the sample dimension of the DataSet in the first position. You can use axis=0 to do this for the DataSet's internal arrays, but this transposition does not affect the DataSet itself. According to pydata/xarray#7456, this is the desired behavior (believe it or not). Supposedly, the position of the DataSet dimensions are arbitrary, but Keras disagrees :(

@maxrjones
Copy link
Member Author

Thanks for your thoughts! I commented on the other thread about the expand_dims/transpose behavior, but more generally you're correct that xbatcher will need to be responsible the correct ordering of dimensions as xarray's data model is generally agnostic to axis order.

@cmdupuis3
Copy link

TBH I actually blame Keras/PyTorch for caring about axis order. So passé!

@cmdupuis3
Copy link

Thinking about this some more, the current behavior does make sense if we're not considering an ML context. Like, if you wanted to sample a bunch of patches and average each of them, a sample dimension wouldn't make sense.

I'm thinking that we could have BatchGenerator wrappers for the ML libs, and then we can append a sample dimension there. I had a look at the existing ones, but I think they don't have this.

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

No branches or pull requests

2 participants