skorch: a scikit-learn wrapper around PyTorch estimators
A scikit-learn compatible neural network library that wraps PyTorch
At a glance
- What is it?
- skorch turns a torch.nn.Module into an estimator that sklearn's Pipeline and GridSearchCV can call. The wrapper is thin, which is the point, and also the source of its sharpest edges.
- Who is it for?
- Adopt skorch when your team already thinks in sklearn pipelines and wants torch modules to behave like estimators, and when you accept that the wrapper owns the training loop. Do not adopt it if you need custom training logic that does not fit the fit/predict contract, or if you are already committed to a Lightning-style Trainer.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly Jupyter Notebook, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap skorch fills between a torch Module and an sklearn estimator
A torch.nn.Module knows how to compute a forward pass. It does not know how to fit, how to report predict_proba, or how to expose hyperparameters as constructor arguments that sklearn's clone can copy. sklearn, meanwhile, has no idea what a Module is. The README describes skorch as "a scikit-learn compatible neural network library that wraps PyTorch", and the example makes the boundary concrete: you write a MyModule subclass with an ordinary forward method, then hand the class itself (not an instance) to NeuralNetClassifier along with max_epochs and lr. The audience is anyone who has a working sklearn pipeline and a PyTorch model and does not want to hand-write the glue that lets GridSearchCV vary a hidden layer width. The README's grid search example varies exactly that, using the module__num_units key, which is the naming convention that makes nested parameters addressable.
How the wrapper maps constructor arguments onto the training loop
The mechanism visible in the README is a parameter routing convention. Anything prefixed module__ is passed through to the module constructor, so module__num_units=10 vs 20 rebuilds MyModule with a different width. Unprefixed keys such as lr and max_epochs configure the estimator's own training behaviour. A third convention appears in the example as iterator_train__shuffle=True, which reaches into the training data iterator. That double-underscore scheme is sklearn's own, so the parameter grid is a plain dict that GridSearchCV already understands. The estimator owns the loop: it splits data, iterates epochs, and exposes fit and predict_proba. Callbacks are the extension point for everything else, and the README lists them by name and links each to its API page: LRScheduler, EpochScoring, EarlyStopping, Checkpoint, Freezer, and ProgressBar. EpochScoring is the interesting one, because it lets an sklearn scoring function be evaluated per epoch rather than only at the end, which is how you get early stopping driven by a metric sklearn computed.
Installation and the two commands that matter
skorch requires Python 3.9 or higher. The README gives three routes. Via conda-forge: conda install -c conda-forge skorch, with an explicit note that this channel is not managed by the skorch maintainers, so package lag or build differences are possible and the feedstock link is provided for that reason. Via pip: python -m pip install -U skorch. From source, the README clones the repository, creates a conda environment on Python 3.12, installs torch separately with python -m pip install torch, then runs python -m pip install . for a plain install or python -m pip install '.[test,docs,dev,extended]' for development. The extras are named, which is useful: you can install the test extra without pulling the docs toolchain. The development flow then runs py.test for unit tests and pylint skorch for static checks. Note that torch is not installed by the skorch command in these instructions; the README installs it as a separate step, so you choose your own build.
Where the estimator abstraction stops paying for itself
The fit and predict_proba contract assumes a fairly standard supervised loop. The README's own example contains the tell: before running grid search it calls net.set_params(train_split=False, verbose=0) with the comment "deactivate skorch-internal train-valid split and verbose logging". skorch performs its own train/validation split by default, and that split interacts with the cross-validation folds GridSearchCV is already creating. Turning it off is the documented move, but it means the user has to reason about two splitting layers at once. Anyone doing something the estimator interface does not model, such as multi-stage training, reinforcement learning, or a loss that needs the raw batch rather than a target tensor, will spend more effort bending the wrapper than writing the loop. The README does not present skorch as a general training framework, and it should not be read as one.
skorch against a hand-written PyTorch loop and against Lightning
A hand-written PyTorch loop gives you total control and no parameter-naming convention to learn, but you then reimplement cross-validation, scoring, checkpointing, and early stopping yourself, and none of it plugs into sklearn. skorch's difference in approach is that it does not replace the loop so much as expose it through sklearn's interface, which is why GridSearchCV works on the result. A Lightning-style framework takes the opposite route: it keeps its own Trainer object and its own ecosystem, and sklearn integration is not the design centre. If your goal is to search over architecture and learning rate inside an existing sklearn Pipeline, the README shows that working directly. If your goal is a training framework with its own callbacks, loggers, and distributed backends, the estimator contract is a constraint rather than a feature. The README also points at GPyTorch and Hugging Face integrations, so the wrapper is not limited to plain feed-forward classifiers, but those are documented separately and the details are not in the README itself.
Maintenance, releases and the BSD-3-Clause licence
The repository is not archived and the most recent push is dated 2026-09-08, with releases v1.4.0 in May 2026, v1.3.1 in December 2025, and v1.3.0 in November 2025. That cadence suggests active maintenance rather than a frozen project, though the README gives no support window or deprecation policy, so you cannot infer from it how long a given API will survive. The licence is BSD-3-Clause, a permissive licence that generally allows commercial use and modification provided the copyright notice and disclaimer are retained; the repository states the licence identifier but the README does not reproduce the terms, so read the LICENSE file in the repository rather than treating this as legal advice. One maintenance cost worth naming: the conda-forge channel is community maintained, so conda users depend on someone else's build schedule, while pip users pull from the maintainers' own release. If you pin skorch, pin torch alongside it, because the README treats torch as an independent install step and version drift between the two is your problem, not the package's.
Editorial conclusion
Adopt skorch when your team already thinks in sklearn pipelines and wants torch modules to behave like estimators, and when you accept that the wrapper owns the training loop. Do not adopt it if you need custom training logic that does not fit the fit/predict contract, or if you are already committed to a Lightning-style Trainer. Before committing, verify two things on your own data: that your module's forward signature matches what the task class expects, and that the default train_split behaviour is what you want, since the README's own grid search example disables it with net.set_params(train_split=False, verbose=0).
Community notes