-
Notifications
You must be signed in to change notification settings - Fork 427
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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
RFC: Asteroid CLI design #201
Comments
We will also do an inference engine I think with the CLI interface smthing like:
the idea is parsing everything recursively and then using overlap_add to separate every file and save it to an output folder. |
Are you going to use click for CLI interface ? |
Let's discuss implementation later, but yes, my current protoype involves dataclasses (Python 3.x+), click, autoclick (optional; to derive CLI options from dataclasses), and lightning's DataModules |
First, thanks a lot for the detailed design explanation, the time and effort you put into it ! I really love the idea of having a powerful CLI in asteroid, and I'm sure it can be beneficial. But first, I have few questions. In your opinion
Actually, it all boils down to listing use cases that we want to support in asteroid and what type of users we are "targeting", and this is not an easy question. |
(Added the It would replace most recipes (all that we can convert to the new design). Users: People running inference on pretrained models; people training their own models; people working on new models to contribute to Asteroid; people working on new private models/datasets. So I guess everyone :-) In the design there isn't really a training script anymore. The logic has been split entirely between dataset and model. Maybe this assumption doesn't work well with some use cases; if so, can you give an example? Below are some ideas on what the code can look like. Steps to include new modelCreate new Python module (either in class MyModel(...):
name = "mymodel"
def __init__(self, config: MyModelConfig):
self.config = config
def forward(self, ...):
...
class MyModelConfig:
# Note: This is also the single source of truth for what the model's config schema is.
# CLI and YAML format is derived from this
def __init__(self, n_filters=64, ...):
self.n_filters = n_filters
....
asteroid.register_model(MyModel, MyModelConfig) *) If outside of Steps to include new datasetSame as with model: Create new module with Torch code; dataset config definition (e.g. number of speakers); registration code; optionally preparation code (download + mix); optionally additional CLI commands that are specific to the dataset. Sketch: class MyDataset(...):
name = "mydata"
def __init__(self, config: MyDatasetConfig):
self.config = config
# Required for all modules
def get_datamodule(self) -> LightningDataModule:
...
# Optional but implemented by Asteroid
def download(self):
...
# Custom and unknown to Asteroid
def custom_print_stats(self):
...
class MyDatasetConfig:
def __init__(self, n_speakers=2, ...):
self.n_speakers = n_speakers
....
cli = asteroid.register_dataset(MyDataset, MyDatasetConfig)
# Register custom additional command
@cli.command()
def print_stats(...):
"""Can be run with: asteroid data mydata print-stats"""
dataset = asteroid_load_dataset_from_cli_args()
dataset.custom_print_stats() |
This sounds really cool !
I didn't mean training script per se, but we need to do the training at one point. Where does this live? I guess a general and configurable class in asteroid? Just to be clear, I see the advantage in having generic tools that enable training any model on any dataset with no code duplicates, I'm just a bit worried about how general might hurt flexibility / ease of getting into the code. So I'm trying to find the edge cases where having such a general framework would hurt us.
|
Good questions. I'll try to come up with solutions for these. |
I'm afraid to become the Keras of source separation, where research gets difficult, where it's harder and harder to get in the source code. I understand that the current code has a lot of duplicate but it has one advantage: it's pretty easy to get into because the organization is trivial, not too abstracted; so you can easily change things from inside the recipes to make new ones. Yes, training TasNet, ConvTasNet or DPRNNTasNet on wsj0-mix, WHAM, WHAMR or LibriMix doesn't require a large/complex code because the recipes are really the same, and writing a CLI for it would be very nice for the users. In my opinion, having a CLI for "easy" use-cases would be great but it would be hard to have it general, flexible, and modifiable (with ease). If we are able to achieve this, with easy strategies to add custom datasets/models/losses/training loops/, we can replace all the recipes by the CLI. If not, how many of the recipes can we translate? Does it make sense to have two different functioning modes for Asteroid (verbosy recipes with duplicated code -that we can also try to reduce- vs CLI recipes) ? How much effort would it require? |
Register a custom CLI command from a custom module and use that. It may reuse some parts of the default training loop. For example if the "official" train command is defined as # asteroid.cli.default_commands
def train(model: ModelConfig, data: DataConfig, continue_from: Experiment = None, ...):
...
asteroid.register_cmd("train") You can define your own: # myprivatesetuff.cli_commands
TwoStepStep = typing.Literal["filterbank", "separator"]
def mytrain(step: TwoStepStep, ...):
"""Use like this: asteroid train-twostep --step filterbank|separator ..."""
asteroid.register_cmd("train-twostep") Btw, I don't insist on doing this on CLI. Instead of
I think we can cover the common cases in the general training code and special cases need to be special cased in the recipes.
I think things like that should live in their own recipes. But those recipes could be written in a way that allows for any dataset to be used. For TwoStep in particular, another idea would be to split it into two models, since it essentialy is a two-model approach:
|
What do you mean by that?
This is also what I believe. While having CLI for the common cases will be extremely useful, I think we cannot completely replace recipes. So, should CLI and recipes share the same abstraction? i.e should recipes reuse the config organization you mentioned? I would suggest to start with
|
I was just thinking loudly how users were to implement a convenient way to change params when they implement recipes without using the new Asteroid CLI “framework” (ie recipes in the current form, as simple scripts). Like changing number of filters in an entirely custom recipe. Usually you’d use CLI params for that, but that means you’ll have to use a CLI parser, ... so as soon as you start adding a non-trivial amount of options to your recipe you’ll want to use the Asteroid CLI “framework”. Anyways, I think we agree sufficiently for me to come up with a first implementation that covers some of the common use cases, models and datasets. So my goal would be to make these use cases really simple and the “framework” reasonably extensible, and for anything that’s to complex to integrate into the “framework” currently we’ll simply keep it as is for now. (Maybe we can move some duplicated code from these special recipes to Asteroid “core” anyways, without changing their code.) |
Thanks for the clarification. |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Here's my draft for Asteroid CLI design. I guess it's a radical change from what we have at the moment...
Let's discuss only about design here, not implementation. I have already given implementation some thought as well and already have a prototype for some parts of the design, but let's agree to a design first.
Please don't be afraid to critise what you don't like. It is likely that I forgot or did not know of some use cases when coming up with the design.
Design goals
API design
Starting from scratch
Assuming you start with an empty hard disk, and want to train a model from scratch.
Steps:
Create dataset config (Download and prepare dataset)
Prepare = Create mixtures, create JSON files, etc.
Download dataset from official URL:
Prepare dataset, if necessary. Some datasets don't need preparation, there the
prepare
cmd is absent.Generated
dataset.yml
:Pass options to
prepare
:dataset.yml
:Create model config
Models have a separate config from datasets (and from experiments, see below). Create one with
configure
:Generated
convtasnet-default.yml
:Run training
Generated
experiment.yml
(Experiment = train or eval) contains model info, dataset info, training info:Change model, dataset, or training params in place:
Continue training from checkpoint:
Run evaluation
Can change training params for eval:
Eval on different dataset:
Starting from pretrained
Eval pretrained:
Finetune pretrained on custom dataset:
The text was updated successfully, but these errors were encountered: