Repository: sktime/sktime
Pull request #5717 (2024-01-09 14:54:28)

[BUG] Fix dynamic `make_forecasting_scorer` for newer `sklearn` metrics
Fixes https://github.com/sktime/sktime/issues/5715.

The issue with `sklearn` metrics is coming from their decorator which no longer allows inspection of admissible arguments via `python` native `sigature`.

Question for reviewers: is there an `sklearn` native way to inspect permissible signature, without reading private attriutes?


Patch:
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index aa3ef9bde..3d8eec911 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -2,7 +2,7 @@ Contributors
 ============
 
 <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
-[![All Contributors](https://img.shields.io/badge/all_contributors-246-orange.svg)](#contributors)
+[![All Contributors](https://img.shields.io/badge/all_contributors-247-orange.svg)](#contributors)
 <!-- ALL-CONTRIBUTORS-BADGE:END -->
 
 This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
@@ -88,10 +88,11 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/davidbp"><img src="https://avatars3.githubusercontent.com/u/4223580?v=4?s=100" width="100px;" alt="David Buchaca Prats"/><br /><sub><b>David Buchaca Prats</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=davidbp" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/davidgilbertson"><img src="https://avatars.githubusercontent.com/u/4443482?v=4?s=100" width="100px;" alt="David Gilbertson"/><br /><sub><b>David Gilbertson</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=davidgilbertson" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Adavidgilbertson" title="Bug reports">🐛</a></td>
       <td align="center" valign="top" width="11.11%"><a href="http://www.uco.es/grupos/ayrna/index.php/es/publicaciones/articulos?publications_view_all=1&theses_view_all=0&projects_view_all=0&task=show&view=member&id=22"><img src="https://avatars1.githubusercontent.com/u/47889499?v=4?s=100" width="100px;" alt="David Guijo Rubio"/><br /><sub><b>David Guijo Rubio</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=dguijo" title="Code">💻</a> <a href="#ideas-dguijo" title="Ideas, Planning, & Feedback">🤔</a></td>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/DManowitz"><img src="https://avatars.githubusercontent.com/u/66927103?v=4?s=100" width="100px;" alt="David Manowitz"/><br /><sub><b>David Manowitz</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3ADManowitz" title="Bug reports">🐛</a> <a href="#maintenance-DManowitz" title="Maintenance">🚧</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/DmitriyValetov"><img src="https://avatars0.githubusercontent.com/u/27976850?v=4?s=100" width="100px;" alt="Dmitriy Valetov"/><br /><sub><b>Dmitriy Valetov</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=DmitriyValetov" title="Code">💻</a> <a href="#tutorial-DmitriyValetov" title="Tutorials">✅</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/dougollerenshaw"><img src="https://avatars.githubusercontent.com/u/19944442?v=4?s=100" width="100px;" alt="Doug Ollerenshaw"/><br /><sub><b>Doug Ollerenshaw</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=dougollerenshaw" title="Documentation">📖</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/dougollerenshaw"><img src="https://avatars.githubusercontent.com/u/19944442?v=4?s=100" width="100px;" alt="Doug Ollerenshaw"/><br /><sub><b>Doug Ollerenshaw</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=dougollerenshaw" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/Dbhasin1"><img src="https://avatars.githubusercontent.com/u/56479884?v=4?s=100" width="100px;" alt="Drishti Bhasin "/><br /><sub><b>Drishti Bhasin </b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Dbhasin1" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/dsherry"><img src="https://avatars.githubusercontent.com/dsherry?s=100" width="100px;" alt="Dylan Sherry"/><br /><sub><b>Dylan Sherry</b></sub></a><br /><a href="#infra-dsherry" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/Emiliathewolf"><img src="https://avatars2.githubusercontent.com/u/22026218?v=4?s=100" width="100px;" alt="Emilia Rose"/><br /><sub><b>Emilia Rose</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Emiliathewolf" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=Emiliathewolf" title="Tests">⚠️</a></td>
@@ -100,9 +101,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/eyalshafran"><img src="https://avatars.githubusercontent.com/u/16999574?v=4?s=100" width="100px;" alt="Eyal Shafran"/><br /><sub><b>Eyal Shafran</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=eyalshafran" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/eyjo"><img src="https://avatars.githubusercontent.com/eyjo?s=100" width="100px;" alt="Eyjólfur Sigurðsson"/><br /><sub><b>Eyjólfur Sigurðsson</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=eyjo" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=eyjo" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/FedericoGarza"><img src="https://avatars.githubusercontent.com/u/10517170?v=4?s=100" width="100px;" alt="Federico Garza"/><br /><sub><b>Federico Garza</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=FedericoGarza" title="Code">💻</a> <a href="#example-FedericoGarza" title="Examples">💡</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/felipeangelimvieira"><img src="https://avatars.githubusercontent.com/felipeangelimvieira?s=100" width="100px;" alt="Felipe Angelim"/><br /><sub><b>Felipe Angelim</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=felipeangelimvieira" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Afelipeangelimvieira" title="Bug reports">🐛</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/felipeangelimvieira"><img src="https://avatars.githubusercontent.com/felipeangelimvieira?s=100" width="100px;" alt="Felipe Angelim"/><br /><sub><b>Felipe Angelim</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=felipeangelimvieira" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Afelipeangelimvieira" title="Bug reports">🐛</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/flix6x"><img src="https://avatars.githubusercontent.com/u/30658763?v=4?s=100" width="100px;" alt="Felix Claessen"/><br /><sub><b>Felix Claessen</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Flix6x" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=Flix6x" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=Flix6x" title="Tests">⚠️</a> <a href="https://github.com/sktime/sktime/issues?q=author%3AFlix6x" title="Bug reports">🐛</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/fstinner"><img src="https://avatars.githubusercontent.com/u/11679462?v=4?s=100" width="100px;" alt="Florian Stinner"/><br /><sub><b>Florian Stinner</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=fstinner" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=fstinner" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/fspinna"><img src="https://avatars.githubusercontent.com/u/35352023?v=4?s=100" width="100px;" alt="Francesco Spinnato"/><br /><sub><b>Francesco Spinnato</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=fspinna" title="Code">💻</a></td>
@@ -111,9 +112,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/chernika158"><img src="https://avatars.githubusercontent.com/u/43787741?s=400&v=4?s=100" width="100px;" alt="Galina Chernikova"/><br /><sub><b>Galina Chernikova</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=chernika158" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/goastler"><img src="https://avatars0.githubusercontent.com/u/7059456?v=4?s=100" width="100px;" alt="George Oastler"/><br /><sub><b>George Oastler</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=goastler" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=goastler" title="Tests">⚠️</a> <a href="#platform-goastler" title="Packaging/porting to new platform">📦</a> <a href="#example-goastler" title="Examples">💡</a> <a href="https://github.com/sktime/sktime/commits?author=goastler" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/geronimos"><img src="https://avatars.githubusercontent.com/u/29955288?s=96&v=4?s=100" width="100px;" alt="Geronimo Bergk"/><br /><sub><b>Geronimo Bergk</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Ageronimos" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=geronimos" title="Code">💻</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/gracewgao/"><img src="https://avatars0.githubusercontent.com/u/38268331?v=4?s=100" width="100px;" alt="Grace Gao"/><br /><sub><b>Grace Gao</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=gracewgao" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Agracewgao" title="Bug reports">🐛</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/gracewgao/"><img src="https://avatars0.githubusercontent.com/u/38268331?v=4?s=100" width="100px;" alt="Grace Gao"/><br /><sub><b>Grace Gao</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=gracewgao" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Agracewgao" title="Bug reports">🐛</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/GuzalBulatova"><img src="https://avatars.githubusercontent.com/GuzalBulatova?s=100" width="100px;" alt="Guzal Bulatova"/><br /><sub><b>Guzal Bulatova</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3AGuzalBulatova" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=GuzalBulatova" title="Code">💻</a> <a href="#eventOrganizing-GuzalBulatova" title="Event Organizing">📋</a> <a href="#mentoring-GuzalBulatova" title="Mentoring">🧑‍🏫</a> <a href="#projectManagement-GuzalBulatova" title="Project Management">📆</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3AGuzalBulatova" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/sktime/sktime/commits?author=GuzalBulatova" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/HYang1996"><img src="https://avatars0.githubusercontent.com/u/44179303?v=4?s=100" width="100px;" alt="HYang1996"/><br /><sub><b>HYang1996</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=HYang1996" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=HYang1996" title="Tests">⚠️</a> <a href="https://github.com/sktime/sktime/commits?author=HYang1996" title="Documentation">📖</a> <a href="#tutorial-HYang1996" title="Tutorials">✅</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/BensHamza"><img src="https://avatars.githubusercontent.com/u/96446862?v=4?s=100" width="100px;" alt="Hamza Benslimane"/><br /><sub><b>Hamza Benslimane</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3ABensHamza" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=BensHamza" title="Code">💻</a></td>
@@ -122,9 +123,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/huayiwei/"><img src="https://avatars3.githubusercontent.com/u/22870735?v=4?s=100" width="100px;" alt="Huayi Wei"/><br /><sub><b>Huayi Wei</b></sub></a><br /><a href="#tutorial-huayicodes" title="Tutorials">✅</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/Ifeanyi30"><img src="https://avatars.githubusercontent.com/u/49926145?v=4?s=100" width="100px;" alt="Ifeanyi30"/><br /><sub><b>Ifeanyi30</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Ifeanyi30" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/iljamaurer"><img src="https://avatars.githubusercontent.com/u/45882103?v=4?s=100" width="100px;" alt="Ilja Maurer"/><br /><sub><b>Ilja Maurer</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=iljamaurer" title="Code">💻</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/IlyasMoutawwakil"><img src="https://avatars.githubusercontent.com/IlyasMoutawwakil?s=100" width="100px;" alt="Ilyas Moutawwakil"/><br /><sub><b>Ilyas Moutawwakil</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=IlyasMoutawwakil" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=IlyasMoutawwakil" title="Documentation">📖</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/IlyasMoutawwakil"><img src="https://avatars.githubusercontent.com/IlyasMoutawwakil?s=100" width="100px;" alt="Ilyas Moutawwakil"/><br /><sub><b>Ilyas Moutawwakil</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=IlyasMoutawwakil" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=IlyasMoutawwakil" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/ireoluwatomiwa-sanusi/"><img src="https://avatars.githubusercontent.com/u/61966277?v=4?s=100" width="100px;" alt="Ireoluwatomiwa"/><br /><sub><b>Ireoluwatomiwa</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Tomiiwa" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/ishannangia001"><img src="https://avatars.githubusercontent.com/u/29480389?v=4?s=100" width="100px;" alt="Ishan Nangia"/><br /><sub><b>Ishan Nangia</b></sub></a><br /><a href="#ideas-ishannangia001" title="Ideas, Planning, & Feedback">🤔</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/jnrusson1"><img src="https://avatars.githubusercontent.com/u/51986332?v=4?s=100" width="100px;" alt="Jack Russon"/><br /><sub><b>Jack Russon</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=jnrusson1" title="Code">💻</a></td>
@@ -133,9 +134,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/janpipek"><img src="https://avatars.githubusercontent.com/janpipek?s=100" width="100px;" alt="Jan Pipek"/><br /><sub><b>Jan Pipek</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=janpipek" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/jasmineliaw"><img src="?s=100" width="100px;" alt="Jasmine Liaw"/><br /><sub><b>Jasmine Liaw</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=jasmineliaw" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="http://www.timeseriesclassification.com"><img src="https://avatars1.githubusercontent.com/u/38794632?v=4?s=100" width="100px;" alt="Jason Lines"/><br /><sub><b>Jason Lines</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=jasonlines" title="Code">💻</a> <a href="#business-jasonlines" title="Business development">💼</a> <a href="https://github.com/sktime/sktime/commits?author=jasonlines" title="Documentation">📖</a> <a href="#design-jasonlines" title="Design">🎨</a> <a href="#eventOrganizing-jasonlines" title="Event Organizing">📋</a> <a href="#fundingFinding-jasonlines" title="Funding Finding">🔍</a> <a href="#ideas-jasonlines" title="Ideas, Planning, & Feedback">🤔</a> <a href="#projectManagement-jasonlines" title="Project Management">📆</a> <a href="#question-jasonlines" title="Answering Questions">💬</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3Ajasonlines" title="Reviewed Pull Requests">👀</a> <a href="#talk-jasonlines" title="Talks">📢</a> <a href="#example-jasonlines" title="Examples">💡</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/whackteachers"><img src="https://avatars0.githubusercontent.com/u/33785383?v=4?s=100" width="100px;" alt="Jason Pong"/><br /><sub><b>Jason Pong</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=whackteachers" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=whackteachers" title="Tests">⚠️</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/whackteachers"><img src="https://avatars0.githubusercontent.com/u/33785383?v=4?s=100" width="100px;" alt="Jason Pong"/><br /><sub><b>Jason Pong</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=whackteachers" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=whackteachers" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/mateuja"><img src="https://avatars.githubusercontent.com/mateuja?s=100" width="100px;" alt="Jaume Mateu"/><br /><sub><b>Jaume Mateu</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=mateuja" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/pirnerjonas"><img src="https://avatars.githubusercontent.com/u/48887249?v=4?s=100" width="100px;" alt="Jonas Pirner"/><br /><sub><b>Jonas Pirner</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=pirnerjonas" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/JonathanBechtel"><img src="https://avatars.githubusercontent.com/u/481696?v=4?s=100" width="100px;" alt="JonathanBechtel"/><br /><sub><b>JonathanBechtel</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=JonathanBechtel" title="Code">💻</a> <a href="#ideas-JonathanBechtel" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/sktime/sktime/commits?author=JonathanBechtel" title="Tests">⚠️</a></td>
@@ -144,9 +145,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/julia-kraus"><img src="https://avatars.githubusercontent.com/julia-kraus?s=100" width="100px;" alt="Julia Kraus"/><br /><sub><b>Julia Kraus</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=julia-kraus" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=julia-kraus" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=julia-kraus" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/jelc53"><img src="?s=100" width="100px;" alt="Julian Cooper"/><br /><sub><b>Julian Cooper</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=jelc53" title="Code">💻</a> <a href="#ideas-jelc53" title="Ideas, Planning, & Feedback">🤔</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/julnow"><img src="https://avatars.githubusercontent.com/u/21206185?v=4?s=100" width="100px;" alt="Julian Nowak"/><br /><sub><b>Julian Nowak</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Ajulnow" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=julnow" title="Code">💻</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/julianarn/"><img src="https://avatars.githubusercontent.com/u/19613567?v=4?s=100" width="100px;" alt="Juliana"/><br /><sub><b>Juliana</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=julramos" title="Code">💻</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/julianarn/"><img src="https://avatars.githubusercontent.com/u/19613567?v=4?s=100" width="100px;" alt="Juliana"/><br /><sub><b>Juliana</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=julramos" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://www.justinshenk.com/"><img src="https://avatars.githubusercontent.com/u/10270308?v=4?s=100" width="100px;" alt="Justin Shenk"/><br /><sub><b>Justin Shenk</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=justinshenk" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/kcc-lion"><img src="?s=100" width="100px;" alt="Kai Lion"/><br /><sub><b>Kai Lion</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=kcc-lion" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=kcc-lion" title="Tests">⚠️</a> <a href="https://github.com/sktime/sktime/commits?author=kcc-lion" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/kanand77"><img src="https://avatars.githubusercontent.com/kanand77?s=100" width="100px;" alt="Kavin Anand"/><br /><sub><b>Kavin Anand</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=kanand77" title="Documentation">📖</a></td>
@@ -155,9 +156,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://whitakerlab.github.io/"><img src="https://avatars1.githubusercontent.com/u/3626306?v=4?s=100" width="100px;" alt="Kirstie Whitaker"/><br /><sub><b>Kirstie Whitaker</b></sub></a><br /><a href="#ideas-KirstieJane" title="Ideas, Planning, & Feedback">🤔</a> <a href="#fundingFinding-KirstieJane" title="Funding Finding">🔍</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/kishmanani"><img src="https://avatars.githubusercontent.com/u/30973056?v=4?s=100" width="100px;" alt="Kishan Manani"/><br /><sub><b>Kishan Manani</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=KishManani" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=KishManani" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=KishManani" title="Tests">⚠️</a> <a href="https://github.com/sktime/sktime/issues?q=author%3AKishManani" title="Bug reports">🐛</a> <a href="#ideas-KishManani" title="Ideas, Planning, & Feedback">🤔</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/krumeto"><img src="https://avatars3.githubusercontent.com/u/11272436?v=4?s=100" width="100px;" alt="Krum Arnaudov"/><br /><sub><b>Krum Arnaudov</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Akrumeto" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=krumeto" title="Code">💻</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/koralturkk"><img src="https://avatars2.githubusercontent.com/u/18037789?s=460&v=4?s=100" width="100px;" alt="Kutay Koralturk"/><br /><sub><b>Kutay Koralturk</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=koralturkk" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Akoralturkk" title="Bug reports">🐛</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/koralturkk"><img src="https://avatars2.githubusercontent.com/u/18037789?s=460&v=4?s=100" width="100px;" alt="Kutay Koralturk"/><br /><sub><b>Kutay Koralturk</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=koralturkk" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Akoralturkk" title="Bug reports">🐛</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/ltsaprounis"><img src="https://avatars.githubusercontent.com/u/64217214?v=4?s=100" width="100px;" alt="Leonidas Tsaprounis"/><br /><sub><b>Leonidas Tsaprounis</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=ltsaprounis" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Altsaprounis" title="Bug reports">🐛</a> <a href="#mentoring-ltsaprounis" title="Mentoring">🧑‍🏫</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3Altsaprounis" title="Reviewed Pull Requests">👀</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/lielleravid"><img src="https://avatars.githubusercontent.com/u/37774194?v=4?s=100" width="100px;" alt="Lielle Ravid"/><br /><sub><b>Lielle Ravid</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=lielleravid" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=lielleravid" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/chillerobscuro"><img src="https://avatars.githubusercontent.com/u/5232872?v=4?s=100" width="100px;" alt="Logan Duffy"/><br /><sub><b>Logan Duffy</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=chillerobscuro" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=chillerobscuro" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=chillerobscuro" title="Tests">⚠️</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Achillerobscuro" title="Bug reports">🐛</a> <a href="#ideas-chillerobscuro" title="Ideas, Planning, & Feedback">🤔</a></td>
@@ -166,9 +167,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/Lovkush-A"><img src="https://avatars.githubusercontent.com/u/25344832?v=4?s=100" width="100px;" alt="Lovkush"/><br /><sub><b>Lovkush</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Lovkush-A" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=Lovkush-A" title="Tests">⚠️</a> <a href="#ideas-Lovkush-A" title="Ideas, Planning, & Feedback">🤔</a> <a href="#mentoring-Lovkush-A" title="Mentoring">🧑‍🏫</a> <a href="#projectManagement-Lovkush-A" title="Project Management">📆</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/luca-miniati"><img src="https://avatars.githubusercontent.com/u/87467600?v=4?s=100" width="100px;" alt="Luca Miniati"/><br /><sub><b>Luca Miniati</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=luca-miniati" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=luca-miniati" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/lbventura"><img src="https://avatars.githubusercontent.com/u/68004282?s=96&v=4?s=100" width="100px;" alt="Luis Ventura"/><br /><sub><b>Luis Ventura</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=lbventura" title="Code">💻</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/luiszugasti"><img src="https://avatars.githubusercontent.com/u/11198457?s=460&u=0645b72683e491824aca16db9702f1d3eb990389&v=4?s=100" width="100px;" alt="Luis Zugasti"/><br /><sub><b>Luis Zugasti</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=luiszugasti" title="Documentation">📖</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/luiszugasti"><img src="https://avatars.githubusercontent.com/u/11198457?s=460&u=0645b72683e491824aca16db9702f1d3eb990389&v=4?s=100" width="100px;" alt="Luis Zugasti"/><br /><sub><b>Luis Zugasti</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=luiszugasti" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/lmmentel"><img src="https://avatars.githubusercontent.com/u/8989838?v=4?s=100" width="100px;" alt="Lukasz Mentel"/><br /><sub><b>Lukasz Mentel</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=lmmentel" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=lmmentel" title="Documentation">📖</a> <a href="#infra-lmmentel" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/sktime/sktime/commits?author=lmmentel" title="Tests">⚠️</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Almmentel" title="Bug reports">🐛</a> <a href="#maintenance-lmmentel" title="Maintenance">🚧</a> <a href="#mentoring-lmmentel" title="Mentoring">🧑‍🏫</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/marrov"><img src="https://avatars.githubusercontent.com/u/54272586?v=4?s=100" width="100px;" alt="Marc Rovira"/><br /><sub><b>Marc Rovira</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=marrov" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="http://marcelotryle.com"><img src="https://avatars3.githubusercontent.com/u/7353520?v=4?s=100" width="100px;" alt="Marcelo Trylesinski"/><br /><sub><b>Marcelo Trylesinski</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Kludex" title="Documentation">📖</a></td>
@@ -177,9 +178,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/mariamjabara"><img src="?s=100" width="100px;" alt="Mariam Jabara"/><br /><sub><b>Mariam Jabara</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=mariamjabara" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://twitter.com/marielli"><img src="https://avatars2.githubusercontent.com/u/13499809?v=4?s=100" width="100px;" alt="Marielle"/><br /><sub><b>Marielle</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=marielledado" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=marielledado" title="Code">💻</a> <a href="#ideas-marielledado" title="Ideas, Planning, & Feedback">🤔</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/mloning"><img src="https://avatars3.githubusercontent.com/u/21020482?v=4?s=100" width="100px;" alt="Markus Löning"/><br /><sub><b>Markus Löning</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=mloning" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=mloning" title="Tests">⚠️</a> <a href="#maintenance-mloning" title="Maintenance">🚧</a> <a href="#platform-mloning" title="Packaging/porting to new platform">📦</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3Amloning" title="Reviewed Pull Requests">👀</a> <a href="#infra-mloning" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#example-mloning" title="Examples">💡</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Amloning" title="Bug reports">🐛</a> <a href="#tutorial-mloning" title="Tutorials">✅</a> <a href="#business-mloning" title="Business development">💼</a> <a href="https://github.com/sktime/sktime/commits?author=mloning" title="Documentation">📖</a> <a href="#design-mloning" title="Design">🎨</a> <a href="#eventOrganizing-mloning" title="Event Organizing">📋</a> <a href="#fundingFinding-mloning" title="Funding Finding">🔍</a> <a href="#ideas-mloning" title="Ideas, Planning, & Feedback">🤔</a> <a href="#projectManagement-mloning" title="Project Management">📆</a> <a href="#question-mloning" title="Answering Questions">💬</a> <a href="#talk-mloning" title="Talks">📢</a> <a href="#mentoring-mloning" title="Mentoring">🧑‍🏫</a> <a href="#video-mloning" title="Videos">📹</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/martin-walter-1a33b3114/"><img src="https://avatars0.githubusercontent.com/u/29627036?v=4?s=100" width="100px;" alt="Martin Walter"/><br /><sub><b>Martin Walter</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=aiwalter" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Aaiwalter" title="Bug reports">🐛</a> <a href="#projectManagement-aiwalter" title="Project Management">📆</a> <a href="#fundingFinding-aiwalter" title="Funding Finding">🔍</a> <a href="#mentoring-aiwalter" title="Mentoring">🧑‍🏫</a> <a href="#ideas-aiwalter" title="Ideas, Planning, & Feedback">🤔</a> <a href="#design-aiwalter" title="Design">🎨</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3Aaiwalter" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/sktime/sktime/commits?author=aiwalter" title="Documentation">📖</a> <a href="#talk-aiwalter" title="Talks">📢</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/martin-walter-1a33b3114/"><img src="https://avatars0.githubusercontent.com/u/29627036?v=4?s=100" width="100px;" alt="Martin Walter"/><br /><sub><b>Martin Walter</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=aiwalter" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Aaiwalter" title="Bug reports">🐛</a> <a href="#projectManagement-aiwalter" title="Project Management">📆</a> <a href="#fundingFinding-aiwalter" title="Funding Finding">🔍</a> <a href="#mentoring-aiwalter" title="Mentoring">🧑‍🏫</a> <a href="#ideas-aiwalter" title="Ideas, Planning, & Feedback">🤔</a> <a href="#design-aiwalter" title="Design">🎨</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3Aaiwalter" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/sktime/sktime/commits?author=aiwalter" title="Documentation">📖</a> <a href="#talk-aiwalter" title="Talks">📢</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/martinagvilas"><img src="https://avatars2.githubusercontent.com/u/37339384?v=4?s=100" width="100px;" alt="Martina G. Vilas"/><br /><sub><b>Martina G. Vilas</b></sub></a><br /><a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3Amartinagvilas" title="Reviewed Pull Requests">👀</a> <a href="#ideas-martinagvilas" title="Ideas, Planning, & Feedback">🤔</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/MCRE-BE"><img src="https://avatars.githubusercontent.com/u/99316631?s=100" width="100px;" alt="Mathias Creemers"/><br /><sub><b>Mathias Creemers</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3AMCRE-BE" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=MCRE-BE" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="http://www.timeseriesclassification.com"><img src="https://avatars0.githubusercontent.com/u/25731235?v=4?s=100" width="100px;" alt="Matthew Middlehurst"/><br /><sub><b>Matthew Middlehurst</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=MatthewMiddlehurst" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=MatthewMiddlehurst" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=MatthewMiddlehurst" title="Tests">⚠️</a> <a href="#tutorial-MatthewMiddlehurst" title="Tutorials">✅</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3AMatthewMiddlehurst" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/sktime/sktime/issues?q=author%3AMatthewMiddlehurst" title="Bug reports">🐛</a></td>
@@ -188,9 +189,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="michaelfeil.eu"><img src="https://avatars.githubusercontent.com/u/63565275?v=4?s=100" width="100px;" alt="Michael Feil"/><br /><sub><b>Michael Feil</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=michaelfeil" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=michaelfeil" title="Tests">⚠️</a> <a href="#ideas-michaelfeil" title="Ideas, Planning, & Feedback">🤔</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/mgazian000"><img src="https://avatars.githubusercontent.com/mgazian000?s=100" width="100px;" alt="Michael Gaziani"/><br /><sub><b>Michael Gaziani</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=mgazian000" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/MichalChromcak"><img src="https://avatars1.githubusercontent.com/u/12393430?v=4?s=100" width="100px;" alt="Michal Chromcak"/><br /><sub><b>Michal Chromcak</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=MichalChromcak" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=MichalChromcak" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=MichalChromcak" title="Tests">⚠️</a> <a href="#tutorial-MichalChromcak" title="Tutorials">✅</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/miraep8"><img src="https://avatars.githubusercontent.com/u/10511777?s=400&u=10a774fd4be767fa3b23a82a98bbfe102c17f0f3&v=4?s=100" width="100px;" alt="Mirae Parker"/><br /><sub><b>Mirae Parker</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=miraep8" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=miraep8" title="Tests">⚠️</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/miraep8"><img src="https://avatars.githubusercontent.com/u/10511777?s=400&u=10a774fd4be767fa3b23a82a98bbfe102c17f0f3&v=4?s=100" width="100px;" alt="Mirae Parker"/><br /><sub><b>Mirae Parker</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=miraep8" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=miraep8" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/MBristle"><img src="https://avatars.githubusercontent.com/MBristle?s=100" width="100px;" alt="Mirko Bristle"/><br /><sub><b>Mirko Bristle</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=MBristle" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://mo-saif.github.io/"><img src="https://avatars0.githubusercontent.com/u/27867617?v=4?s=100" width="100px;" alt="Mohammed Saif Kazamel"/><br /><sub><b>Mohammed Saif Kazamel</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3AMo-Saif" title="Bug reports">🐛</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://moradabaz.github.io/"><img src="https://avatars.githubusercontent.com/u/29915156?v=4?s=100" width="100px;" alt="Morad :)"/><br /><sub><b>Morad :)</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=moradabaz" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=moradabaz" title="Tests">⚠️</a> <a href="https://github.com/sktime/sktime/commits?author=moradabaz" title="Documentation">📖</a></td>
@@ -199,9 +200,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/niekvanderlaan"><img src="https://avatars.githubusercontent.com/u/9962825?v=4?s=100" width="100px;" alt="Niek van der Laan"/><br /><sub><b>Niek van der Laan</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=niekvanderlaan" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/ngupta23"><img src="https://avatars0.githubusercontent.com/u/33585645?v=4?s=100" width="100px;" alt="Nikhil Gupta"/><br /><sub><b>Nikhil Gupta</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=ngupta23" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Angupta23" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=ngupta23" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/nshahpazov/"><img src="https://avatars.githubusercontent.com/nshahpazov?s=100" width="100px;" alt="Nikola Shahpazov"/><br /><sub><b>Nikola Shahpazov</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=nshahpazov" title="Documentation">📖</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/nilesh05apr"><img src="https://avatars.githubusercontent.com/u/65773314?v=4?s=100" width="100px;" alt="Nilesh Kumar"/><br /><sub><b>Nilesh Kumar</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=nilesh05apr" title="Code">💻</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/nilesh05apr"><img src="https://avatars.githubusercontent.com/u/65773314?v=4?s=100" width="100px;" alt="Nilesh Kumar"/><br /><sub><b>Nilesh Kumar</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=nilesh05apr" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/ninfueng"><img src="https://avatars2.githubusercontent.com/u/28499769?v=4?s=100" width="100px;" alt="Ninnart Fuengfusin"/><br /><sub><b>Ninnart Fuengfusin</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=ninfueng" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/NoaBenAmi"><img src="https://avatars.githubusercontent.com/u/37590002?v=4?s=100" width="100px;" alt="Noa Ben Ami"/><br /><sub><b>Noa Ben Ami</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=NoaBenAmi" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=NoaBenAmi" title="Tests">⚠️</a> <a href="https://github.com/sktime/sktime/commits?author=NoaBenAmi" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/shchur"><img src="https://avatars.githubusercontent.com/u/6944857?v=4?s=100" width="100px;" alt="Oleksandr Shchur"/><br /><sub><b>Oleksandr Shchur</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Ashchur" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=shchur" title="Code">💻</a></td>
@@ -210,9 +211,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/prockenschaub"><img src="https://avatars0.githubusercontent.com/u/15381732?v=4?s=100" width="100px;" alt="Patrick Rockenschaub"/><br /><sub><b>Patrick Rockenschaub</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=prockenschaub" title="Code">💻</a> <a href="#design-prockenschaub" title="Design">🎨</a> <a href="#ideas-prockenschaub" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/sktime/sktime/commits?author=prockenschaub" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="http://www2.informatik.hu-berlin.de/~schaefpa/"><img src="https://avatars0.githubusercontent.com/u/7783034?v=4?s=100" width="100px;" alt="Patrick Schäfer"/><br /><sub><b>Patrick Schäfer</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=patrickzib" title="Code">💻</a> <a href="#tutorial-patrickzib" title="Tutorials">✅</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://ber.gp"><img src="https://avatars1.githubusercontent.com/u/9824244?v=4?s=100" width="100px;" alt="Paul"/><br /><sub><b>Paul</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Pangoraw" title="Documentation">📖</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/paulyim97/"><img src="https://avatars.githubusercontent.com/pyyim?s=100" width="100px;" alt="Paul Yim"/><br /><sub><b>Paul Yim</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=pyyim" title="Code">💻</a> <a href="#example-pyyim" title="Examples">💡</a> <a href="https://github.com/sktime/sktime/commits?author=pyyim" title="Tests">⚠️</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/paulyim97/"><img src="https://avatars.githubusercontent.com/pyyim?s=100" width="100px;" alt="Paul Yim"/><br /><sub><b>Paul Yim</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=pyyim" title="Code">💻</a> <a href="#example-pyyim" title="Examples">💡</a> <a href="https://github.com/sktime/sktime/commits?author=pyyim" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://www.imes.uni-hannover.de/de/institut/team/m-sc-karl-philipp-kortmann/"><img src="https://avatars.githubusercontent.com/u/20466981?v=4?s=100" width="100px;" alt="Philipp Kortmann"/><br /><sub><b>Philipp Kortmann</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=MrPr3ntice" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=MrPr3ntice" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/Piyush1729"><img src="https://avatars2.githubusercontent.com/u/64950012?v=4?s=100" width="100px;" alt="Piyush Gade"/><br /><sub><b>Piyush Gade</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Piyush1729" title="Code">💻</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3APiyush1729" title="Reviewed Pull Requests">👀</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/rahulporuri"><img src="https://avatars.githubusercontent.com/u/1926457?v=4?s=100" width="100px;" alt="Poruri Sai Rahul"/><br /><sub><b>Poruri Sai Rahul</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=rahulporuri" title="Documentation">📖</a></td>
@@ -221,9 +222,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/Quaterion"><img src="https://avatars2.githubusercontent.com/u/23200273?v=4?s=100" width="100px;" alt="Quaterion"/><br /><sub><b>Quaterion</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3AQuaterion" title="Bug reports">🐛</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/rakshitha123"><img src="https://avatars.githubusercontent.com/u/7654679?v=4?s=100" width="100px;" alt="Rakshitha Godahewa"/><br /><sub><b>Rakshitha Godahewa</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=rakshitha123" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=rakshitha123" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/Ram0nB"><img src="https://avatars.githubusercontent.com/u/45173421?s=100" width="100px;" alt="Ramon Bussing"/><br /><sub><b>Ramon Bussing</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Ram0nB" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=Ram0nB" title="Code">💻</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/RavenRudi"><img src="https://avatars.githubusercontent.com/u/46402968?v=4?s=100" width="100px;" alt="RavenRudi"/><br /><sub><b>RavenRudi</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=RavenRudi" title="Code">💻</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/RavenRudi"><img src="https://avatars.githubusercontent.com/u/46402968?v=4?s=100" width="100px;" alt="RavenRudi"/><br /><sub><b>RavenRudi</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=RavenRudi" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/wolph"><img src="?s=100" width="100px;" alt="Rick van Hattem"/><br /><sub><b>Rick van Hattem</b></sub></a><br /><a href="#infra-wolph" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/Ris-Bali"><img src="https://avatars.githubusercontent.com/u/81592570?v=4?s=100" width="100px;" alt="Rishabh Bali"/><br /><sub><b>Rishabh Bali</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Ris-Bali" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/RishiKumarRay"><img src="https://avatars.githubusercontent.com/u/87641376?v=4?s=100" width="100px;" alt="Rishi Kumar Ray"/><br /><sub><b>Rishi Kumar Ray</b></sub></a><br /><a href="#infra-RishiKumarRay" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
@@ -232,9 +233,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/ronnie-llamado"><img src="https://avatars.githubusercontent.com/ronnie-llamado?s=100" width="100px;" alt="Ronnie Llamado"/><br /><sub><b>Ronnie Llamado</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=ronnie-llamado" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/rnkuhns"><img src="https://avatars0.githubusercontent.com/u/26907244?v=4?s=100" width="100px;" alt="Ryan Kuhns"/><br /><sub><b>Ryan Kuhns</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=RNKuhns" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=RNKuhns" title="Documentation">📖</a> <a href="#tutorial-RNKuhns" title="Tutorials">✅</a> <a href="#example-RNKuhns" title="Examples">💡</a> <a href="#ideas-RNKuhns" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3ARNKuhns" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/sktime/sktime/commits?author=RNKuhns" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/achieveordie"><img src="https://avatars.githubusercontent.com/u/54197164?v=4?s=100" width="100px;" alt="Sagar Mishra"/><br /><sub><b>Sagar Mishra</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=achieveordie" title="Tests">⚠️</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://sajay.online"><img src="https://avatars2.githubusercontent.com/u/25329624?v=4?s=100" width="100px;" alt="Sajaysurya Ganesh"/><br /><sub><b>Sajaysurya Ganesh</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=sajaysurya" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=sajaysurya" title="Documentation">📖</a> <a href="#design-sajaysurya" title="Design">🎨</a> <a href="#example-sajaysurya" title="Examples">💡</a> <a href="#ideas-sajaysurya" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/sktime/sktime/commits?author=sajaysurya" title="Tests">⚠️</a> <a href="#tutorial-sajaysurya" title="Tutorials">✅</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://sajay.online"><img src="https://avatars2.githubusercontent.com/u/25329624?v=4?s=100" width="100px;" alt="Sajaysurya Ganesh"/><br /><sub><b>Sajaysurya Ganesh</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=sajaysurya" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=sajaysurya" title="Documentation">📖</a> <a href="#design-sajaysurya" title="Design">🎨</a> <a href="#example-sajaysurya" title="Examples">💡</a> <a href="#ideas-sajaysurya" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/sktime/sktime/commits?author=sajaysurya" title="Tests">⚠️</a> <a href="#tutorial-sajaysurya" title="Tutorials">✅</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/SamiAlavi"><img src="https://avatars.githubusercontent.com/u/32700289?v=4?s=100" width="100px;" alt="Sami Alavi"/><br /><sub><b>Sami Alavi</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=SamiAlavi" title="Code">💻</a> <a href="#maintenance-SamiAlavi" title="Maintenance">🚧</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/sssilvar"><img src="https://avatars.githubusercontent.com/u/16252054?v=4?s=100" width="100px;" alt="Santiago Smith Silva"/><br /><sub><b>Santiago Smith Silva</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=sssilvar" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/Saransh-cpp"><img src="https://avatars.githubusercontent.com/u/74055102?v=4?s=100" width="100px;" alt="Saransh Chopra"/><br /><sub><b>Saransh Chopra</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Saransh-cpp" title="Documentation">📖</a> <a href="#infra-Saransh-cpp" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
@@ -243,9 +244,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/SebasKoel"><img src="https://avatars3.githubusercontent.com/u/66252156?v=4?s=100" width="100px;" alt="Sebastiaan Koel"/><br /><sub><b>Sebastiaan Koel</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=SebasKoel" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=SebasKoel" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/shagn"><img src="https://avatars.githubusercontent.com/u/16029092?v=4?s=100" width="100px;" alt="Sebastian Hagn"/><br /><sub><b>Sebastian Hagn</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=shagn" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/ShivamPathak99"><img src="https://avatars.githubusercontent.com/u/98941325?s=400&v=4?s=100" width="100px;" alt="Shivam Pathak"/><br /><sub><b>Shivam Pathak</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=ShivamPathak99" title="Documentation">📖</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/AurumnPegasus"><img src="https://avatars.githubusercontent.com/u/54315149?v=4?s=100" width="100px;" alt="Shivansh Subramanian"/><br /><sub><b>Shivansh Subramanian</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=AurumnPegasus" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=AurumnPegasus" title="Code">💻</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/AurumnPegasus"><img src="https://avatars.githubusercontent.com/u/54315149?v=4?s=100" width="100px;" alt="Shivansh Subramanian"/><br /><sub><b>Shivansh Subramanian</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=AurumnPegasus" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=AurumnPegasus" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/sbuse"><img src="https://avatars.githubusercontent.com/u/24408707?v=4?s=100" width="100px;" alt="Simon B."/><br /><sub><b>Simon B.</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=sbuse" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/solomon-botchway-a1383821b/"><img src="https://avatars.githubusercontent.com/u/62394255?v=4?s=100" width="100px;" alt="Solomon Botchway"/><br /><sub><b>Solomon Botchway</b></sub></a><br /><a href="#maintenance-snnbotchway" title="Maintenance">🚧</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/khrapovs"><img src="https://avatars.githubusercontent.com/u/3774663?v=4?s=100" width="100px;" alt="Stanislav Khrapov"/><br /><sub><b>Stanislav Khrapov</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=khrapovs" title="Code">💻</a></td>
@@ -254,9 +255,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/Taise228"><img src="https://avatars.githubusercontent.com/u/95762401?s=400&v=4?s=100" width="100px;" alt="Taisei Yamamoto"/><br /><sub><b>Taisei Yamamoto</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Taise228" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://thayeylolu.github.io/portfolio/"><img src="https://avatars.githubusercontent.com/u/13348874?v=4?s=100" width="100px;" alt="Taiwo Owoseni"/><br /><sub><b>Taiwo Owoseni</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=thayeylolu" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/lnthach"><img src="https://avatars0.githubusercontent.com/u/7788363?v=4?s=100" width="100px;" alt="Thach Le Nguyen"/><br /><sub><b>Thach Le Nguyen</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=lnthach" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=lnthach" title="Tests">⚠️</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/mathco-wf"><img src="https://avatars.githubusercontent.com/mathco-wf?s=100" width="100px;" alt="TheMathcompay Widget Factory Team"/><br /><sub><b>TheMathcompay Widget Factory Team</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=mathco-wf" title="Documentation">📖</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/mathco-wf"><img src="https://avatars.githubusercontent.com/mathco-wf?s=100" width="100px;" alt="TheMathcompay Widget Factory Team"/><br /><sub><b>TheMathcompay Widget Factory Team</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=mathco-wf" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/tombh"><img src="https://avatars.githubusercontent.com/u/160835?s=80&v=4?s=100" width="100px;" alt="Thomas Buckley-Houston"/><br /><sub><b>Thomas Buckley-Houston</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Atombh" title="Bug reports">🐛</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/xxl4tomxu98"><img src="https://avatars.githubusercontent.com/u/62292177?s=40&v=4?s=100" width="100px;" alt="Tom Xu"/><br /><sub><b>Tom Xu</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=xxl4tomxu98" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=xxl4tomxu98" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/tpvasconcelos"><img src="https://avatars.githubusercontent.com/u/17701527?v=4?s=100" width="100px;" alt="Tomas P. de Vasconcelos"/><br /><sub><b>Tomas P. de Vasconcelos</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Atpvasconcelos" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=tpvasconcelos" title="Code">💻</a></td>
@@ -265,9 +266,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/utsavcoding"><img src="https://avatars3.githubusercontent.com/u/55446385?v=4?s=100" width="100px;" alt="Utsav Kumar Tiwari"/><br /><sub><b>Utsav Kumar Tiwari</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=utsavcoding" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=utsavcoding" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/Vasudeva-bit"><img src="https://avatars.githubusercontent.com/u/70791259?v=4?s=100" width="100px;" alt="Vasudeva Kilaru"/><br /><sub><b>Vasudeva Kilaru</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=Vasudeva-bit" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=Vasudeva-bit" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/victordremov"><img src="https://avatars.githubusercontent.com/u/32140716?s=100" width="100px;" alt="Viktor Dremov"/><br /><sub><b>Viktor Dremov</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=victordremov" title="Code">💻</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/ViktorKaz"><img src="https://avatars0.githubusercontent.com/u/33499138?v=4?s=100" width="100px;" alt="ViktorKaz"/><br /><sub><b>ViktorKaz</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=ViktorKaz" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=ViktorKaz" title="Documentation">📖</a> <a href="#design-ViktorKaz" title="Design">🎨</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/ViktorKaz"><img src="https://avatars0.githubusercontent.com/u/33499138?v=4?s=100" width="100px;" alt="ViktorKaz"/><br /><sub><b>ViktorKaz</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=ViktorKaz" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=ViktorKaz" title="Documentation">📖</a> <a href="#design-ViktorKaz" title="Design">🎨</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/VyomkeshVyas"><img src="?s=100" width="100px;" alt="Vyomkesh Vyas"/><br /><sub><b>Vyomkesh Vyas</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=VyomkeshVyas" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=VyomkeshVyas" title="Documentation">📖</a> <a href="#example-VyomkeshVyas" title="Examples">💡</a> <a href="https://github.com/sktime/sktime/commits?author=VyomkeshVyas" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/wayneadams"><img src="https://avatars.githubusercontent.com/u/15034841?s=400&u=d717e9945910bcc844c5e64cd56d570c6cc4e8e6&v=4?s=100" width="100px;" alt="Wayne Adams"/><br /><sub><b>Wayne Adams</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=wayneadams" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/templierw/"><img src="https://github.com/templierw.png?s=100" width="100px;" alt="William Templier"/><br /><sub><b>William Templier</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=templierw" title="Documentation">📖</a></td>
@@ -276,9 +277,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://www.linkedin.com/in/yann-hallouard/"><img src="https://avatars.githubusercontent.com/YHallouard?s=100" width="100px;" alt="Yann Hallouard"/><br /><sub><b>Yann Hallouard</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=YHallouard" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=YHallouard" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/yashlamba"><img src="https://avatars.githubusercontent.com/u/44164398?v=4?s=100" width="100px;" alt="Yash Lamba"/><br /><sub><b>Yash Lamba</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=yashlamba" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/xuyxu"><img src="https://avatars2.githubusercontent.com/u/22359569?v=4?s=100" width="100px;" alt="Yi-Xuan Xu"/><br /><sub><b>Yi-Xuan Xu</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=xuyxu" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=xuyxu" title="Tests">⚠️</a> <a href="#maintenance-xuyxu" title="Maintenance">🚧</a> <a href="https://github.com/sktime/sktime/commits?author=xuyxu" title="Documentation">📖</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/sz85512678"><img src="https://avatars.githubusercontent.com/sz85512678?s=100" width="100px;" alt="Zhen Shao"/><br /><sub><b>Zhen Shao</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=sz85512678" title="Code">💻</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/sz85512678"><img src="https://avatars.githubusercontent.com/sz85512678?s=100" width="100px;" alt="Zhen Shao"/><br /><sub><b>Zhen Shao</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=sz85512678" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/ZiyaoWei"><img src="https://avatars.githubusercontent.com/u/940823?v=4?s=100" width="100px;" alt="Ziyao Wei"/><br /><sub><b>Ziyao Wei</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=ZiyaoWei" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/aa25desh"><img src="https://avatars1.githubusercontent.com/u/29518290?v=4?s=100" width="100px;" alt="aa25desh"/><br /><sub><b>aa25desh</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=aa25desh" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Aaa25desh" title="Bug reports">🐛</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/abandus"><img src="https://avatars2.githubusercontent.com/u/46486474?v=4?s=100" width="100px;" alt="abandus"/><br /><sub><b>abandus</b></sub></a><br /><a href="#ideas-abandus" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/sktime/sktime/commits?author=abandus" title="Code">💻</a></td>
@@ -287,9 +288,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/big-o"><img src="https://avatars1.githubusercontent.com/u/1134151?v=4?s=100" width="100px;" alt="big-o"/><br /><sub><b>big-o</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=big-o" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=big-o" title="Tests">⚠️</a> <a href="#design-big-o" title="Design">🎨</a> <a href="#ideas-big-o" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3Abig-o" title="Reviewed Pull Requests">👀</a> <a href="#tutorial-big-o" title="Tutorials">✅</a> <a href="#mentoring-big-o" title="Mentoring">🧑‍🏫</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/bobbys-dev"><img src="https://avatars.githubusercontent.com/bobbys-dev?s=100" width="100px;" alt="bobbys"/><br /><sub><b>bobbys</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=bobbys-dev" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/brettkoonce"><img src="https://avatars2.githubusercontent.com/u/11281814?v=4?s=100" width="100px;" alt="brett koonce"/><br /><sub><b>brett koonce</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=brettkoonce" title="Documentation">📖</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/btrtts"><img src="https://avatars3.githubusercontent.com/u/66252156?v=4?s=100" width="100px;" alt="btrtts"/><br /><sub><b>btrtts</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=btrtts" title="Documentation">📖</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/btrtts"><img src="https://avatars3.githubusercontent.com/u/66252156?v=4?s=100" width="100px;" alt="btrtts"/><br /><sub><b>btrtts</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=btrtts" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/chizzi25"><img src="https://avatars3.githubusercontent.com/u/67911243?v=4?s=100" width="100px;" alt="chizzi25"/><br /><sub><b>chizzi25</b></sub></a><br /><a href="#blog-chizzi25" title="Blogposts">📝</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/chrisholder"><img src="https://avatars.githubusercontent.com/u/4674372?v=4?s=100" width="100px;" alt="chrisholder"/><br /><sub><b>chrisholder</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=chrisholder" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=chrisholder" title="Tests">⚠️</a> <a href="https://github.com/sktime/sktime/commits?author=chrisholder" title="Documentation">📖</a> <a href="#design-chrisholder" title="Design">🎨</a> <a href="#example-chrisholder" title="Examples">💡</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/danbartl"><img src="https://avatars.githubusercontent.com/u/19947407?v=4?s=100" width="100px;" alt="danbartl"/><br /><sub><b>danbartl</b></sub></a><br /><a href="https://github.com/sktime/sktime/issues?q=author%3Adanbartl" title="Bug reports">🐛</a> <a href="https://github.com/sktime/sktime/commits?author=danbartl" title="Code">💻</a> <a href="https://github.com/sktime/sktime/pulls?q=is%3Apr+reviewed-by%3Adanbartl" title="Reviewed Pull Requests">👀</a> <a href="#talk-danbartl" title="Talks">📢</a> <a href="https://github.com/sktime/sktime/commits?author=danbartl" title="Tests">⚠️</a> <a href="#tutorial-danbartl" title="Tutorials">✅</a> <a href="#video-danbartl" title="Videos">📹</a></td>
@@ -298,9 +299,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/jesellier"><img src="https://avatars0.githubusercontent.com/u/51952076?v=4?s=100" width="100px;" alt="jesellier"/><br /><sub><b>jesellier</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=jesellier" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/jschemm"><img src="https://avatars.githubusercontent.com/u/81151346?v=4?s=100" width="100px;" alt="jschemm"/><br /><sub><b>jschemm</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=jschemm" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/kkoziara"><img src="https://avatars1.githubusercontent.com/u/4346849?v=4?s=100" width="100px;" alt="kkoziara"/><br /><sub><b>kkoziara</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=kkoziara" title="Code">💻</a> <a href="https://github.com/sktime/sktime/issues?q=author%3Akkoziara" title="Bug reports">🐛</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/matteogales"><img src="https://avatars0.githubusercontent.com/u/9269326?v=4?s=100" width="100px;" alt="matteogales"/><br /><sub><b>matteogales</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=matteogales" title="Code">💻</a> <a href="#design-matteogales" title="Design">🎨</a> <a href="#ideas-matteogales" title="Ideas, Planning, & Feedback">🤔</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/matteogales"><img src="https://avatars0.githubusercontent.com/u/9269326?v=4?s=100" width="100px;" alt="matteogales"/><br /><sub><b>matteogales</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=matteogales" title="Code">💻</a> <a href="#design-matteogales" title="Design">🎨</a> <a href="#ideas-matteogales" title="Ideas, Planning, & Feedback">🤔</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/oleskiewicz"><img src="https://avatars1.githubusercontent.com/u/5682158?v=4?s=100" width="100px;" alt="oleskiewicz"/><br /><sub><b>oleskiewicz</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=oleskiewicz" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=oleskiewicz" title="Documentation">📖</a> <a href="https://github.com/sktime/sktime/commits?author=oleskiewicz" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/pabworks"><img src="https://avatars.githubusercontent.com/u/32725127?v=4?s=100" width="100px;" alt="pabworks"/><br /><sub><b>pabworks</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=pabworks" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=pabworks" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/xloem"><img src="?s=100" width="100px;" alt="patiently pending world peace"/><br /><sub><b>patiently pending world peace</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=xloem" title="Code">💻</a></td>
@@ -309,9 +310,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/sophijka"><img src="https://avatars2.githubusercontent.com/u/47450591?v=4?s=100" width="100px;" alt="sophijka"/><br /><sub><b>sophijka</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=sophijka" title="Documentation">📖</a> <a href="#maintenance-sophijka" title="Maintenance">🚧</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/sri1419"><img src="https://avatars2.githubusercontent.com/u/65078278?v=4?s=100" width="100px;" alt="sri1419"/><br /><sub><b>sri1419</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=sri1419" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/tensorflow-as-tf"><img src="https://avatars.githubusercontent.com/u/51345718?v=4?s=100" width="100px;" alt="tensorflow-as-tf"/><br /><sub><b>tensorflow-as-tf</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=tensorflow-as-tf" title="Code">💻</a></td>
-      <td align="center" valign="top" width="11.11%"><a href="https://github.com/vedazeren"><img src="https://avatars3.githubusercontent.com/u/63582874?v=4?s=100" width="100px;" alt="vedazeren"/><br /><sub><b>vedazeren</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=vedazeren" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=vedazeren" title="Tests">⚠️</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="11.11%"><a href="https://github.com/vedazeren"><img src="https://avatars3.githubusercontent.com/u/63582874?v=4?s=100" width="100px;" alt="vedazeren"/><br /><sub><b>vedazeren</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=vedazeren" title="Code">💻</a> <a href="https://github.com/sktime/sktime/commits?author=vedazeren" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/vincent-nich12"><img src="https://avatars3.githubusercontent.com/u/36476633?v=4?s=100" width="100px;" alt="vincent-nich12"/><br /><sub><b>vincent-nich12</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=vincent-nich12" title="Code">💻</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/vollmersj"><img src="https://avatars2.githubusercontent.com/u/12613127?v=4?s=100" width="100px;" alt="vollmersj"/><br /><sub><b>vollmersj</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=vollmersj" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="11.11%"><a href="https://github.com/xiaobenbenecho"><img src="https://avatars.githubusercontent.com/u/17461849?v=4?s=100" width="100px;" alt="xiaobenbenecho"/><br /><sub><b>xiaobenbenecho</b></sub></a><br /><a href="https://github.com/sktime/sktime/commits?author=xiaobenbenecho" title="Code">💻</a></td>
diff --git a/README.md b/README.md
index bd4cae0c5..89c679a9c 100644
--- a/README.md
+++ b/README.md
@@ -82,6 +82,7 @@ sktime also provides **interfaces to related libraries**, for example [scikit-le
 | **[Time Series Distances/Kernels]** | maturing | [Tutorial](https://github.com/sktime/sktime/blob/main/examples/03_transformers.ipynb) · [API Reference](https://www.sktime.net/en/latest/api_reference/dists_kernels.html) · [Extension Template](https://github.com/sktime/sktime/blob/main/extension_templates/dist_kern_panel.py) |
 | **[Time Series Alignment]** | experimental | [API Reference](https://www.sktime.net/en/latest/api_reference/alignment.html) · [Extension Template](https://github.com/sktime/sktime/blob/main/extension_templates/alignment.py) |
 | **[Annotation]** | experimental | [Extension Template](https://github.com/sktime/sktime/blob/main/extension_templates/annotation.py) |
+| **[Time Series Splitters]** | maturing | [Extension Template](https://github.com/sktime/sktime/blob/main/extension_templates/split.py) | |
 | **[Distributions and simulation]** | experimental |  |
 
 [forecasting]: https://github.com/sktime/sktime/tree/main/sktime/forecasting
@@ -93,6 +94,7 @@ sktime also provides **interfaces to related libraries**, for example [scikit-le
 [time series alignment]: https://github.com/sktime/sktime/tree/main/sktime/alignment
 [transformations]: https://github.com/sktime/sktime/tree/main/sktime/transformations
 [distributions and simulation]: https://github.com/sktime/sktime/tree/main/sktime/proba
+[time series splitters]: https://github.com/sktime/sktime/tree/main/sktime/split
 [parameter fitting]: https://github.com/sktime/sktime/tree/main/sktime/param_est
 
 
diff --git a/docs/source/api_reference/alignment.rst b/docs/source/api_reference/alignment.rst
index 5306ed44c..eecec7e7e 100644
--- a/docs/source/api_reference/alignment.rst
+++ b/docs/source/api_reference/alignment.rst
@@ -6,6 +6,12 @@ Time series alignment
 The :mod:`sktime.alignment` module contains time series aligners, such as
 dynamic time warping aligners.
 
+All time series aligners in ``sktime`` can be listed using the
+``sktime.registry.all_estimators`` utility,
+using ``estimator_types="aligner"``, optionally filtered by tags.
+Valid tags can be listed using ``sktime.registry.all_tags``.
+
+
 Naive aligners
 --------------
 
diff --git a/docs/source/api_reference/classification.rst b/docs/source/api_reference/classification.rst
index 9a2d3ee19..b003e5097 100644
--- a/docs/source/api_reference/classification.rst
+++ b/docs/source/api_reference/classification.rst
@@ -23,6 +23,17 @@ Composition
     SklearnClassifierPipeline
     MultiplexClassifier
 
+Model selection and tuning
+--------------------------
+
+.. currentmodule:: sktime.classification.model_selection
+
+.. autosummary::
+    :toctree: auto_generated/
+    :template: class.rst
+
+    TSCGridSearchCV
+
 Ensembles
 ---------
 
@@ -182,8 +193,15 @@ Shapelet-based
     MrSEQL
     MrSQM
 
-sklearn
--------
+
+sklearn classifiers
+-------------------
+
+This section contains classifiers which are not time series classifiers but
+simple tabular classifiers in ``sklearn`` compatible API.
+
+They are used internally in time series classifiers, but can also be used
+directly in a tabular setting.
 
 .. currentmodule:: sktime.classification.sklearn
 
diff --git a/docs/source/api_reference/param_est.rst b/docs/source/api_reference/param_est.rst
index d8d22f427..9bb1a2cdd 100644
--- a/docs/source/api_reference/param_est.rst
+++ b/docs/source/api_reference/param_est.rst
@@ -14,10 +14,6 @@ All parameter estimators in ``sktime`` can be listed using the
 using ``estimator_types="param_est"``, optionally filtered by tags.
 Valid tags can be listed using ``sktime.registry.all_tags``.
 
-.. automodule:: sktime.param_est
-    :no-members:
-    :no-inherited-members:
-
 Parameter estimators
 --------------------
 
diff --git a/docs/source/api_reference/split.rst b/docs/source/api_reference/split.rst
index 7e8228f22..493ae07c3 100644
--- a/docs/source/api_reference/split.rst
+++ b/docs/source/api_reference/split.rst
@@ -21,6 +21,8 @@ Forecasting users interested in performance evaluation are advised
 to use full backtesting instead of a single split, e.g., via ``evaluate``,
 see :ref:`forecasting API reference <forecasting_ref>`.
 
+.. currentmodule:: sktime.split
+
 .. autosummary::
     :toctree: auto_generated/
     :template: function.rst
diff --git a/extension_templates/split.py b/extension_templates/split.py
new file mode 100644
index 000000000..d795d298f
--- /dev/null
+++ b/extension_templates/split.py
@@ -0,0 +1,269 @@
+"""Extension template for parameter estimators.
+
+Purpose of this implementation template:
+    quick implementation of new estimators following the template
+    NOT a concrete class to import! This is NOT a base class or concrete class!
+    This is to be used as a "fill-in" coding template.
+
+How to use this implementation template to implement a new estimator:
+- make a copy of the template in a suitable location, give it a descriptive name.
+- work through all the "todo" comments below
+- fill in code for mandatory methods, and optionally for optional methods
+- do not write to reserved variables: _tags, _tags_dynamic
+- you can add more private methods, but do not override BaseEstimator's private methods
+    an easy way to be safe is to prefix your methods with "_custom"
+- change docstrings for functions and the file
+- ensure interface compatibility by sktime.utils.estimator_checks.check_estimator
+- once complete: use as a local library, or contribute to sktime via PR
+- more details:
+  https://www.sktime.net/en/stable/developer_guide/add_estimators.html
+
+Mandatory implements:
+    splitting (iloc reference)            - _split(self, y)
+
+Optional implements:
+    splitting (loc reference)             - _split_loc(self, y)
+    get number of splits                  - get_n_splits(self, y)
+
+Testing - required for sktime test framework and check_estimator usage:
+    get default parameters for test instance(s) - get_test_params(cls)
+
+copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
+"""
+# todo: write an informative docstring for the file or module, remove the above
+# todo: add an appropriate copyright notice for your estimator
+#       estimators contributed to sktime should have the copyright notice at the top
+#       estimators of your own do not need to have permissive or BSD-3 copyright
+
+# todo: uncomment the following line, enter authors' GitHub IDs
+# __author__ = [authorGitHubID, anotherAuthorGitHubID]
+
+
+from sktime.split.base import BaseSplitter
+
+# todo: add any necessary imports here
+
+# todo: if any imports are sktime soft dependencies:
+# make sure to fill in the "python_dependencies" tag with the package import name
+
+
+class MySplitter(BaseSplitter):
+    """Custom splitter. todo: write docstring.
+
+    todo: describe your custom splitter here
+
+    Parameters
+    ----------
+    parama : int
+        descriptive explanation of parama
+    paramb : string, optional (default='default')
+        descriptive explanation of paramb
+    paramc : boolean, optional (default= whether paramb is not the default)
+        descriptive explanation of paramc
+    and so on
+    est : sktime.estimator, BaseEstimator descendant
+        descriptive explanation of est
+    est2: another estimator
+        descriptive explanation of est2
+    and so on
+    """
+
+    # todo: fill out estimator tags here
+    #  tags are inherited from parent class if they are not set
+    _tags = {
+        #
+        # behavioural tags
+        # ----------------
+        #
+        # internal support for hierarchical and panel data
+        "split_hierarchical": False,
+        # valid values: True, False
+        # if False, splitter broadcasts over instances for hierarchical data
+        # if True, internal _split must support pd.MultiIndex
+        #
+        # which of _split and _split_loc is called in split_series by default
+        "split_series_uses": "iloc",
+        # valid values: "iloc" or "loc"
+        # determines whether split_series under the hood
+        # calls split ("iloc") or split_loc ("loc"). Setting this can give
+        # performance advantages, e.g., if "loc" is faster to obtain.
+        #
+        # dependency tags: python version and soft dependencies
+        # -----------------------------------------------------
+        #
+        # python version requirement
+        "python_version": None,
+        # valid values: str, PEP 440 valid python version specifiers
+        # raises exception at construction if local python version is incompatible
+        #
+        # soft dependency requirement
+        "python_dependencies": None
+        # valid values: str or list of str
+        # raises exception at construction if modules at strings cannot be imported
+    }
+
+    # todo: add any hyper-parameters and components to constructor
+    def __init__(self, est, parama, est2=None, paramb="default", paramc=None):
+        # estimators should precede parameters
+        #  if estimators have default values, set None and initialize below
+
+        # todo: write any hyper-parameters and components to self
+        self.est = est
+        self.parama = parama
+        self.paramb = paramb
+        self.paramc = paramc
+
+        # leave this as is
+        super().__init__()
+
+        # todo: optional, parameter checking logic (if applicable) should happen here
+        # if writes derived values to self, should *not* overwrite self.parama etc
+        # instead, write to self._parama, self._newparam (starting with _)
+
+        # todo: default estimators should have None arg defaults
+        #  and be initialized here
+        #  do this only with default estimators, not with parameters
+        # if est2 is None:
+        #     self.estimator = MyDefaultEstimator()
+
+        # todo: if tags of estimator depend on component tags, set these here
+        #  only needed if estimator is a composite
+        #  tags set in the constructor apply to the object and override the class
+        #
+        # example 1: conditional setting of a tag
+        # if est.foo == 42:
+        #   self.set_tags(handles-missing-data=True)
+        # example 2: cloning tags from component
+        #   self.clone_tags(est2, ["enforce_index_type", "handles-missing-data"])
+
+    # todo: implement this, mandatory
+    def _split(self, y):
+        """Get iloc references to train/test splits of `y`.
+
+        private _split containing the core logic, called from split
+
+        Parameters
+        ----------
+        y : pd.Index
+            Index of time series to split
+
+        Yields
+        ------
+        train : 1D np.ndarray of dtype int
+            Training window indices, iloc references to training indices in y
+        test : 1D np.ndarray of dtype int
+            Test window indices, iloc references to test indices in y
+        """
+        # todo: implement the core logic of your splitter here
+        # ensure to avoid side effects to self or y
+        #
+        # example:
+        # for train, test in some_logic(y):
+        #     yield train, test
+
+    # todo: consider implementing this, optional
+    # if not implementing, delete this - default is as below and present in base class
+    def _split_loc(self, y):
+        """Get loc references to train/test splits of `y`.
+
+        private _split containing the core logic, called from split_loc
+
+        Default implements using split and y.index to look up the loc indices.
+        Can be overridden for faster implementation.
+
+        Parameters
+        ----------
+        y : pd.Index
+            index of time series to split
+
+        Yields
+        ------
+        train : pd.Index
+            Training window indices, loc references to training indices in y
+        test : pd.Index
+            Test window indices, loc references to test indices in y
+        """
+        for train, test in self.split(y):
+            # default gets loc index from iloc index
+            yield y[train], y[test]
+
+    # todo: consider implementing this, optional
+    # only implement if the result does not depend on y
+    # if not implementing, delete this - default is as below and present in base class
+    def get_n_splits(self, y) -> int:
+        """Return the number of splits.
+
+        Parameters
+        ----------
+        y : pd.Series or pd.Index, optional (default=None)
+            Time series to split
+
+        Returns
+        -------
+        n_splits : int
+            The number of splits.
+        """
+        return len(list(self.split(y)))
+
+    @classmethod
+    def get_test_params(cls, parameter_set="default"):
+        """Return testing parameter settings for the splitter.
+
+        Parameters
+        ----------
+        parameter_set : str, default="default"
+            Name of the set of test parameters to return, for use in tests. If no
+            special parameters are defined for a value, will return `"default"` set.
+
+        Returns
+        -------
+        params : dict or list of dict, default = {}
+            Parameters to create testing instances of the class
+            Each dict are parameters to construct an "interesting" test instance, i.e.,
+            `MyClass(**params)` or `MyClass(**params[i])` creates a valid test instance.
+            `create_test_instance` uses the first (or only) dictionary in `params`
+        """
+
+        # todo: set the testing parameters for the object
+        # Testing parameters can be dictionary or list of dictionaries
+        # Testing parameter choice should cover internal cases well.
+        #
+        # this method can, if required, use:
+        #   class properties (e.g., inherited); parent class test case
+        #   imported objects such as estimators from sktime or sklearn
+        # important: all such imports should be *inside get_test_params*, not at the top
+        #            since imports are used only at testing time
+        #
+        # The parameter_set argument is not used for automated, module level tests.
+        #   It can be used in custom, estimator specific tests, for "special" settings.
+        # A parameter dictionary must be returned *for all values* of parameter_set,
+        #   i.e., "parameter_set not available" errors should never be raised.
+        #
+        # A good parameter set should primarily satisfy two criteria,
+        #   1. Chosen set of parameters should have a low testing time,
+        #      ideally in the magnitude of few seconds for the entire test suite.
+        #       This is vital for the cases where default values result in
+        #       "big" models which not only increases test time but also
+        #       run into the risk of test workers crashing.
+        #   2. There should be a minimum two such parameter sets with different
+        #      sets of values to ensure a wide range of code coverage is provided.
+        #
+        # example 1: specify params as dictionary
+        # any number of params can be specified
+        # params = {"est": value0, "parama": value1, "paramb": value2}
+        #
+        # example 2: specify params as list of dictionary
+        # note: Only first dictionary will be used by create_test_instance
+        # params = [{"est": value1, "parama": value2},
+        #           {"est": value3, "parama": value4}]
+        # return params
+        #
+        # example 3: parameter set depending on param_set value
+        #   note: only needed if a separate parameter set is needed in tests
+        # if parameter_set == "special_param_set":
+        #     params = {"est": value1, "parama": value2}
+        #     return params
+        #
+        # # "default" params - always returned except for "special_param_set" value
+        # params = {"est": value3, "parama": value4}
+        # return params
diff --git a/pyproject.toml b/pyproject.toml
index 17aa0bdca..6e45ddd20 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -200,7 +200,7 @@ regression = [
 transformations = [
   'esig<0.10,>=0.9.7; python_version < "3.11"',
   "filterpy<1.5,>=1.4.5",
-  "holidays>=0.29,<0.40",
+  "holidays>=0.29,<0.41",
   "mne<1.6,>=1.5",
   'numba<0.59,>=0.53; python_version < "3.12"',
   "pycatch22>=0.4,<0.4.4",
diff --git a/sktime/base/_base.py b/sktime/base/_base.py
index 677b35257..f9d4c9c66 100644
--- a/sktime/base/_base.py
+++ b/sktime/base/_base.py
@@ -622,12 +622,12 @@ class BaseEstimator(BaseObject):
 
         # default retrieves all self attributes ending in "_"
         # and returns them with keys that have the "_" removed
-        fitted_params = [attr for attr in dir(obj) if attr.endswith("_")]
-        fitted_params = [x for x in fitted_params if not x.startswith("_")]
-        fitted_params = [x for x in fitted_params if hasattr(obj, x)]
-        fitted_param_dict = {p[:-1]: getattr(obj, p) for p in fitted_params}
-
-        return fitted_param_dict
+        fitted_params = {
+            attr[:-1]: getattr(obj, attr)
+            for attr in dir(obj)
+            if attr.endswith("_") and not attr.startswith("_") and hasattr(obj, attr)
+        }
+        return fitted_params
 
     def _get_fitted_params(self):
         """Get fitted parameters.
diff --git a/sktime/classification/dictionary_based/_boss.py b/sktime/classification/dictionary_based/_boss.py
index 8a1eaae13..de9e3be35 100644
--- a/sktime/classification/dictionary_based/_boss.py
+++ b/sktime/classification/dictionary_based/_boss.py
@@ -7,6 +7,7 @@ BOSS ensemble.
 __author__ = ["MatthewMiddlehurst", "patrickzib"]
 __all__ = ["BOSSEnsemble", "IndividualBOSS", "pairwise_distances"]
 
+from copy import copy
 from itertools import compress
 
 import numpy as np
@@ -648,27 +649,22 @@ class IndividualBOSS(BaseClassifier):
         return self._class_vals[min_pos]
 
     def _shorten_bags(self, word_len, y):
-        new_boss = IndividualBOSS(
-            self.window_size,
-            word_len,
-            self.norm,
-            self.alphabet_size,
-            save_words=self.save_words,
-            use_boss_distance=self.use_boss_distance,
-            feature_selection=self.feature_selection,
-            n_jobs=self.n_jobs,
-            random_state=self.random_state,
-        )
+        new_boss = copy(self)
+
+        # change word length parameter
+        new_boss.word_length = word_len
+
+        # reset internal variables
+        new_boss._accuracy = 0
+        new_boss._subsample = []
+        new_boss._train_predictions = []
+
+        # copy fitted transformer as reference
         new_boss._transformer = self._transformer
+
+        # update shortened bags
         new_bag = new_boss._transformer._shorten_bags(word_len, y)
         new_boss._transformed_data = new_bag
-        new_boss._class_vals = self._class_vals
-        new_boss.n_classes_ = self.n_classes_
-        new_boss.classes_ = self.classes_
-        new_boss._class_dictionary = self._class_dictionary
-        new_boss._y_metadata = self._y_metadata
-        new_boss._y_inner_mtype = self._y_inner_mtype
-        new_boss._is_fitted = True
 
         return new_boss
 
diff --git a/sktime/classification/model_selection/__init__.py b/sktime/classification/model_selection/__init__.py
new file mode 100644
index 000000000..72343b457
--- /dev/null
+++ b/sktime/classification/model_selection/__init__.py
@@ -0,0 +1,6 @@
+"""Tuning of time series classifiers."""
+# copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
+
+from sktime.classification.model_selection._tune import TSCGridSearchCV
+
+__all__ = ["TSCGridSearchCV"]
diff --git a/sktime/classification/model_selection/_tune.py b/sktime/classification/model_selection/_tune.py
new file mode 100644
index 000000000..add7ea31b
--- /dev/null
+++ b/sktime/classification/model_selection/_tune.py
@@ -0,0 +1,442 @@
+"""Tuning for time series classifiers."""
+
+__author__ = ["fkiraly", "achieveordie"]
+
+import numpy as np
+from sklearn.model_selection import GridSearchCV
+
+from sktime.classification._delegate import _DelegatedClassifier
+
+
+class TSCGridSearchCV(_DelegatedClassifier):
+    """Exhaustive search over specified parameter values for an estimator.
+
+    Adapts sklearn GridSearchCV for sktime time series classifiers
+
+    Optimizes hyper-parameters of `estimators` by exhaustive grid search.
+
+    Parameters
+    ----------
+    estimator : estimator object
+        This is assumed to implement the scikit-learn estimator interface.
+        Either estimator needs to provide a ``score`` function,
+        or ``scoring`` must be passed.
+
+    param_grid : dict or list of dictionaries
+        Dictionary with parameters names (`str`) as keys and lists of
+        parameter settings to try as values, or a list of such
+        dictionaries, in which case the grids spanned by each dictionary
+        in the list are explored. This enables searching over any sequence
+        of parameter settings.
+
+    scoring : str, callable, list, tuple or dict, default=None
+        Strategy to evaluate the performance of the cross-validated model on
+        the test set.
+
+        If `scoring` represents a single score, one can use:
+
+        - a single string (see :ref:`scoring_parameter`);
+        - a callable (see :ref:`scoring`) that returns a single value.
+
+        If `scoring` represents multiple scores, one can use:
+
+        - a list or tuple of unique strings;
+        - a callable returning a dictionary where the keys are the metric
+          names and the values are the metric scores;
+        - a dictionary with metric names as keys and callables a values.
+
+    n_jobs : int, default=None
+        Number of jobs to run in parallel.
+        ``None`` means 1 unless in a :obj:`joblib.parallel_backend` context.
+        ``-1`` means using all processors. See :term:`Glossary <n_jobs>`
+        for more details.
+
+    refit : bool, str, or callable, default=True
+        Refit an estimator using the best found parameters on the whole
+        dataset. If ``False``, the ``predict`` and ``predict_probab`` will not work.
+
+        For multiple metric evaluation, this needs to be a `str` denoting the
+        scorer that would be used to find the best parameters for refitting
+        the estimator at the end.
+
+        Where there are considerations other than maximum score in
+        choosing a best estimator, ``refit`` can be set to a function which
+        returns the selected ``best_index_`` given ``cv_results_``. In that
+        case, the ``best_estimator_`` and ``best_params_`` will be set
+        according to the returned ``best_index_`` while the ``best_score_``
+        attribute will not be available.
+
+        The refitted estimator is made available at the ``best_estimator_``
+        attribute and permits using ``predict`` directly on this
+        ``GridSearchCV`` instance.
+
+        Also for multiple metric evaluation, the attributes ``best_index_``,
+        ``best_score_`` and ``best_params_`` will only be available if
+        ``refit`` is set and all of them will be determined w.r.t this specific
+        scorer.
+
+        See ``scoring`` parameter to know more about multiple metric
+        evaluation.
+
+    cv : int, cross-validation generator or an iterable, default=None
+        Determines the cross-validation splitting strategy.
+        Possible inputs for cv are:
+
+        - None, to use the default 5-fold cross validation,
+        - integer, to specify the number of folds in a `(Stratified)KFold`,
+        - :term:`CV splitter`,
+        - An iterable yielding (train, test) splits as arrays of indices.
+
+        For integer/None inputs, if the estimator is a classifier and ``y`` is
+        either binary or multiclass, :class:`StratifiedKFold` is used. In all
+        other cases, :class:`KFold` is used. These splitters are instantiated
+        with `shuffle=False` so the splits will be the same across calls.
+
+        Refer :ref:`User Guide <cross_validation>` for the various
+        cross-validation strategies that can be used here.
+
+    verbose : int
+        Controls the verbosity: the higher, the more messages.
+
+        - >1 : the computation time for each fold and parameter candidate is
+          displayed;
+        - >2 : the score is also displayed;
+        - >3 : the fold and candidate parameter indexes are also displayed
+          together with the starting time of the computation.
+
+    pre_dispatch : int, or str, default='2*n_jobs'
+        Controls the number of jobs that get dispatched during parallel
+        execution. Reducing this number can be useful to avoid an
+        explosion of memory consumption when more jobs get dispatched
+        than CPUs can process. This parameter can be:
+
+            - None, in which case all the jobs are immediately
+              created and spawned. Use this for lightweight and
+              fast-running jobs, to avoid delays due to on-demand
+              spawning of the jobs
+
+            - An int, giving the exact number of total jobs that are
+              spawned
+
+            - A str, giving an expression as a function of n_jobs,
+              as in '2*n_jobs'
+
+    error_score : 'raise' or numeric, default=np.nan
+        Value to assign to the score if an error occurs in estimator fitting.
+        If set to 'raise', the error is raised. If a numeric value is given,
+        FitFailedWarning is raised. This parameter does not affect the refit
+        step, which will always raise the error.
+
+    return_train_score : bool, default=False
+        If ``False``, the ``cv_results_`` attribute will not include training
+        scores.
+        Computing training scores is used to get insights on how different
+        parameter settings impact the overfitting/underfitting trade-off.
+        However computing the scores on the training set can be computationally
+        expensive and is not strictly required to select the parameters that
+        yield the best generalization performance.
+
+    tune_by_variable : bool, optional (default=False)
+        Whether to tune parameter by each time series variable separately,
+        in case of multivariate data passed to the tuning estimator.
+        Only applies if time series passed are strictly multivariate.
+        If True, clones of the estimator will be fit to each variable separately,
+        and are available in fields of the classifiers_ attribute.
+        Has the same effect as applying ColumnEnsembleClassifier wrapper to self.
+        If False, the same best parameter is selected for all variables.
+
+    Attributes
+    ----------
+    cv_results_ : dict of numpy (masked) ndarrays
+        A dict with keys as column headers and values as columns, that can be
+        imported into a pandas ``DataFrame``.
+
+        For multi-metric evaluation, the scores for all the scorers are
+        available in the ``cv_results_`` dict at the keys ending with that
+        scorer's name (``'_<scorer_name>'``) instead of ``'_score'`` shown
+        above. ('split0_test_precision', 'mean_train_precision' etc.)
+
+    best_estimator_ : estimator
+        Estimator that was chosen by the search, i.e. estimator
+        which gave highest score (or smallest loss if specified)
+        on the left out data. Not available if ``refit=False``.
+
+        See ``refit`` parameter for more information on allowed values.
+
+    best_score_ : float
+        Mean cross-validated score of the best_estimator
+
+        For multi-metric evaluation, this is present only if ``refit`` is
+        specified.
+
+        This attribute is not available if ``refit`` is a function.
+
+    best_params_ : dict
+        Parameter setting that gave the best results on the hold out data.
+
+        For multi-metric evaluation, this is present only if ``refit`` is
+        specified.
+
+    best_index_ : int
+        The index (of the ``cv_results_`` arrays) which corresponds to the best
+        candidate parameter setting.
+
+        The dict at ``search.cv_results_['params'][search.best_index_]`` gives
+        the parameter setting for the best model, that gives the highest
+        mean score (``search.best_score_``).
+
+        For multi-metric evaluation, this is present only if ``refit`` is
+        specified.
+
+    scorer_ : function or a dict
+        Scorer function used on the held out data to choose the best
+        parameters for the model.
+
+        For multi-metric evaluation, this attribute holds the validated
+        ``scoring`` dict which maps the scorer key to the scorer callable.
+
+    n_splits_ : int
+        The number of cross-validation splits (folds/iterations).
+
+    refit_time_ : float
+        Seconds used for refitting the best model on the whole dataset.
+
+        This is present only if ``refit`` is not False.
+
+    multimetric_ : bool
+        Whether or not the scorers compute several metrics.
+
+    classes_ : ndarray of shape (n_classes,)
+        The classes labels. This is present only if ``refit`` is specified and
+        the underlying estimator is a classifier.
+
+    n_features_in_ : int
+        Number of features seen during :term:`fit`. Only defined if
+        `best_estimator_` is defined (see the documentation for the `refit`
+        parameter for more details) and that `best_estimator_` exposes
+        `n_features_in_` when fit.
+
+    feature_names_in_ : ndarray of shape (`n_features_in_`,)
+        Names of features seen during :term:`fit`. Only defined if
+        `best_estimator_` is defined (see the documentation for the `refit`
+        parameter for more details) and that `best_estimator_` exposes
+        `feature_names_in_` when fit.
+
+    See Also
+    --------
+    ParameterGrid : Generates all the combinations of a hyperparameter grid.
+    train_test_split : Utility function to split the data into a development
+        set usable for fitting a GridSearchCV instance and an evaluation set
+        for its final evaluation.
+    sklearn.metrics.make_scorer : Make a scorer from a performance metric or
+        loss function.
+    """
+
+    _tags = {
+        "X_inner_mtype": ["nested_univ", "numpy3D"],
+        "y_inner_mtype": ["numpy2D"],
+        "capability:multivariate": True,
+        "capability:multioutput": True,
+        "capability:unequal_length": True,
+        "capability:missing_values": True,
+        "capability:multithreading": True,
+        "capability:predict_proba": True,
+    }
+
+    def __init__(
+        self,
+        estimator,
+        param_grid,
+        scoring=None,
+        n_jobs=None,
+        refit=True,
+        cv=None,
+        verbose=0,
+        pre_dispatch="2*n_jobs",
+        error_score=np.nan,
+        return_train_score=False,
+        tune_by_variable=False,
+    ):
+        self.estimator = estimator
+        self.param_grid = param_grid
+        self.scoring = scoring
+        self.n_jobs = n_jobs
+        self.refit = refit
+        self.cv = cv
+        self.verbose = verbose
+        self.pre_dispatch = pre_dispatch
+        self.error_score = error_score
+        self.return_train_score = return_train_score
+        self.tune_by_variable = tune_by_variable
+
+        super().__init__()
+
+        DELEGATED_PARAMS = [
+            "estimator",
+            "param_grid",
+            "scoring",
+            "n_jobs",
+            "refit",
+            "cv",
+            "verbose",
+            "pre_dispatch",
+            "error_score",
+            "return_train_score",
+        ]
+
+        gcsvargs = {k: getattr(self, k) for k in DELEGATED_PARAMS}
+
+        self.estimator_ = GridSearchCV(**gcsvargs)
+
+        if self.tune_by_variable:
+            self.set_tags(**{"capability:multioutput": False})
+
+    def _fit(self, X, y):
+        """Fit time series classifier to training data.
+
+        private _fit containing the core logic, called from fit
+
+        Writes to self:
+            Sets fitted model attributes ending in "_".
+
+        Parameters
+        ----------
+        X : guaranteed to be of a type in self.get_tag("X_inner_mtype")
+            if self.get_tag("X_inner_mtype") = "numpy3D":
+            3D np.ndarray of shape = [n_instances, n_dimensions, series_length]
+            if self.get_tag("X_inner_mtype") = "pd-multiindex:":
+            pd.DataFrame with columns = variables,
+            index = pd.MultiIndex with first level = instance indices,
+            second level = time indices
+            for list of other mtypes, see datatypes.SCITYPE_REGISTER
+            for specifications, see examples/AA_datatypes_and_datasets.ipynb
+        y : guaranteed to be of a type in self.get_tag("y_inner_mtype")
+            1D iterable, of shape [n_instances]
+            or 2D iterable, of shape [n_instances, n_dimensions]
+            class labels for fitting
+            if self.get_tag("capaility:multioutput") = False, guaranteed to be 1D
+            if self.get_tag("capaility:multioutput") = True, guaranteed to be 2D
+
+        Returns
+        -------
+        self : Reference to self.
+        """
+        if y.shape[1] == 1:
+            y = y.flatten()
+
+        estimator = self._get_delegate()
+        estimator.fit(X=X, y=y)
+
+        fitted_param_names = [
+            "cv_results_",
+            "best_estimator_",
+            "best_score_",
+            "best_params_",
+            "best_index_",
+            "scorer_",
+            "n_splits_",
+            "refit_time_",
+            "multimetric_",
+            "classes_",
+        ]
+
+        for p in fitted_param_names:
+            if hasattr(estimator, p):
+                val = getattr(estimator, p)
+                setattr(self, p, val)
+
+        return self
+
+    def _predict(self, X):
+        """Predict labels for sequences in X.
+
+        private _predict containing the core logic, called from predict
+
+        State required:
+            Requires state to be "fitted".
+
+        Accesses in self:
+            Fitted model attributes ending in "_"
+
+        Parameters
+        ----------
+        X : guaranteed to be of a type in self.get_tag("X_inner_mtype")
+            if self.get_tag("X_inner_mtype") = "numpy3D":
+                3D np.ndarray of shape = [n_instances, n_dimensions, series_length]
+            if self.get_tag("X_inner_mtype") = "nested_univ":
+                pd.DataFrame with each column a dimension, each cell a pd.Series
+            for list of other mtypes, see datatypes.SCITYPE_REGISTER
+            for specifications, see examples/AA_datatypes_and_datasets.ipynb
+
+        Returns
+        -------
+        y : 1D np.array of int, of shape [n_instances] - predicted class labels
+            indices correspond to instance indices in X
+        """
+        estimator = self._get_delegate()
+        y_pred = estimator.predict(X=X)
+        if y_pred.ndim == 1:
+            y_pred = y_pred.reshape(-1, 1)
+        return y_pred
+
+    # the delegate is an sklearn estimator and it does not have get_fitted_params
+    # therefore we have to override _get_fitted_params from the delegator,
+    # which would otherwise call it
+    def _get_fitted_params(self):
+        """Get fitted parameters.
+
+        private _get_fitted_params, called from get_fitted_params
+
+        State required:
+            Requires state to be "fitted".
+
+        Returns
+        -------
+        fitted_params : dict with str keys
+            fitted parameters, keyed by names of fitted parameter
+        """
+        return {}
+
+    @classmethod
+    def get_test_params(cls, parameter_set="default"):
+        """Return testing parameter settings for the estimator.
+
+        Parameters
+        ----------
+        parameter_set : str, default="default"
+            Name of the set of test parameters to return, for use in tests. If no
+            special parameters are defined for a value, will return `"default"` set.
+            For classifiers, a "default" set of parameters should be provided for
+            general testing, and a "results_comparison" set for comparing against
+            previously recorded results if the general set does not produce suitable
+            probabilities to compare against.
+
+        Returns
+        -------
+        params : dict or list of dict, default={}
+            Parameters to create testing instances of the class.
+            Each dict are parameters to construct an "interesting" test instance, i.e.,
+            `MyClass(**params)` or `MyClass(**params[i])` creates a valid test instance.
+            `create_test_instance` uses the first (or only) dictionary in `params`.
+        """
+        from sklearn.gaussian_process.kernels import RBF, DotProduct
+        from sklearn.metrics import accuracy_score
+
+        from sktime.classification.kernel_based import TimeSeriesSVC
+        from sktime.dists_kernels import AggrDist
+
+        mean_eucl_tskernel = AggrDist(DotProduct())
+        mean_rbf_tskernel = AggrDist(RBF())
+
+        param1 = {
+            "estimator": TimeSeriesSVC(kernel=mean_rbf_tskernel, probability=True),
+            "param_grid": {"C": [0.1, 1]},
+        }
+
+        param2 = {
+            "estimator": TimeSeriesSVC(kernel=mean_eucl_tskernel, probability=True),
+            "param_grid": {"kernel__transformer": [DotProduct(), RBF()]},
+            "scoring": accuracy_score,
+        }
+
+        return [param1, param2]
diff --git a/sktime/datatypes/_vectorize.py b/sktime/datatypes/_vectorize.py
index f8755d435..fb1a96154 100644
--- a/sktime/datatypes/_vectorize.py
+++ b/sktime/datatypes/_vectorize.py
@@ -61,9 +61,16 @@ class VectorizedDF:
     SERIES_SCITYPES = ["Series", "Panel", "Hierarchical"]
 
     def __init__(
-        self, X, y=None, iterate_as="Series", is_scitype="Panel", iterate_cols=False
+        self,
+        X,
+        y=None,
+        iterate_as="Series",
+        is_scitype="Panel",
+        iterate_cols=False,
+        remember_data=True,
     ):
-        self.X = X
+        if remember_data:
+            self.X = X
 
         if is_scitype is None:
             _, _, metadata = check_is_scitype(
@@ -89,9 +96,15 @@ class VectorizedDF:
         self._check_iterate_cols(iterate_cols)
         self.iterate_cols = iterate_cols
 
+        self.remember_data = remember_data
+
         self.converter_store = dict()
 
-        self.X_multiindex = self._init_conversion(X)
+        X_multiindex = self._init_conversion(X)
+        self.X_mi_columns = X_multiindex.columns
+        self.X_mi_index = X_multiindex.index
+        if remember_data:
+            self.X_multiindex = X_multiindex
         self.iter_indices = self._init_iter_indices()
 
         self.shape = self._iter_shape()
@@ -148,14 +161,14 @@ class VectorizedDF:
         iterate_as = self.iterate_as
         is_scitype = self.is_scitype
         iterate_cols = self.iterate_cols
-        X = self.X_multiindex
+        X_ix = self.X_mi_index
 
         if iterate_as == is_scitype:
             row_ix = None
         elif iterate_as == "Series":
-            row_ix = X.index.droplevel(-1).unique()
+            row_ix = X_ix.droplevel(-1).unique()
         elif iterate_as == "Panel":
-            row_ix = X.index.droplevel([-1, -2]).unique()
+            row_ix = X_ix.droplevel([-1, -2]).unique()
         else:
             raise RuntimeError(
                 f"unexpected value found for attribute self.iterate_as: {iterate_as}"
@@ -163,7 +176,7 @@ class VectorizedDF:
             )
 
         if iterate_cols:
-            col_ix = X.columns
+            col_ix = self.X_mi_columns
         else:
             col_ix = None
 
@@ -172,7 +185,7 @@ class VectorizedDF:
     @property
     def index(self):
         """Defaults to pandas index of X converted to pandas type."""
-        return self.X_multiindex.index
+        return self.X_mi_index
 
     def get_iter_indices(self):
         """Get indices that are iterated over in vectorization.
@@ -257,7 +270,7 @@ class VectorizedDF:
                 yield group_name, None, _enforce_index_freq(inst)
 
         iter_levels = self._iter_levels(iterate_as)
-        is_self_iter = len(iter_levels) == self.X_multiindex.index.nlevels
+        is_self_iter = len(iter_levels) == self.X_mi_index.nlevels
 
         if is_self_iter:
             yield from _iter_cols(self.X_multiindex)
@@ -285,7 +298,7 @@ class VectorizedDF:
                 iter_levels = 2
             elif iterate_as == "Series":
                 iter_levels = 1
-        return list(range(self.X_multiindex.index.nlevels - iter_levels))
+        return list(range(self.X_mi_index.nlevels - iter_levels))
 
     def _iter_shape(self, iterate_as=None, iterate_cols=None):
         """Get the number of groups and columns to iterate over.
@@ -306,11 +319,11 @@ class VectorizedDF:
             iterate_cols = self.iterate_cols
 
         iter_levels = self._iter_levels(iterate_as)
-        is_self_iter = len(iter_levels) == self.X_multiindex.index.nlevels
+        is_self_iter = len(iter_levels) == self.X_mi_index.nlevels
 
         return (
             1 if is_self_iter else self.X_multiindex.groupby(level=iter_levels).ngroups,
-            len(self.X_multiindex.columns) if iterate_cols else 1,
+            len(self.X_mi_columns) if iterate_cols else 1,
         )
 
     def as_list(self):
@@ -383,7 +396,7 @@ class VectorizedDF:
         row_ix, col_ix = self.get_iter_indices()
         force_flat = False
         if row_ix is None and col_ix is None:
-            X_mi_reconstructed = self.X_multiindex
+            X_mi_reconstructed = pd.DataFrame(df_list[0])
         elif col_ix is None:
             X_mi_reconstructed = pd.concat(df_list, keys=row_ix, axis=0)
         elif row_ix is None:
@@ -409,7 +422,7 @@ class VectorizedDF:
             X_mi_reconstructed = pd.concat(col_concats, keys=row_ix, axis=0)
 
         X_mi_index = X_mi_reconstructed.index
-        X_orig_row_index = self.X_multiindex.index
+        X_orig_row_index = self.X_mi_index
 
         flatten = col_multiindex == "flat" or (col_multiindex == "none" and force_flat)
         if flatten and isinstance(X_mi_reconstructed.columns, pd.MultiIndex):
diff --git a/sktime/forecasting/base/_fh.py b/sktime/forecasting/base/_fh.py
index 7a71c6e9a..39ba31283 100644
--- a/sktime/forecasting/base/_fh.py
+++ b/sktime/forecasting/base/_fh.py
@@ -682,12 +682,13 @@ class ForecastingHorizon:
         y : pd.DataFrame, pd.Series, pd.Index, or None
             data to compute fh relative to,
             assumed in sktime pandas based mtype or index thereof
-        cutoff : pd.Period, pd.Timestamp, int, optional (default=None)
+            if None, assumes no MultiIndex
+        cutoff : pd.Period, pd.Timestamp, int, or pd.Index, optional (default=None)
             Cutoff value to use in computing resulting index.
             If cutoff is not provided, is computed from ``y`` via ``get_cutoff``.
         sort_by_time : bool, optional (default=False)
             for MultiIndex returns, whether to sort by time index (level -1)
-            - If True, result Index is sorted sort by time index (level -1)
+            - If True, result Index is sorted by time index (level -1)
             - If False, result Index is sorted overall
 
         Returns
@@ -707,9 +708,11 @@ class ForecastingHorizon:
         elif isinstance(y, pd.Index):
             y_index = y
             y = pd.DataFrame(index=y_index)
-        else:
+        elif cutoff is None:
             y_index = pd.Index(y)
             y = pd.DataFrame(index=y_index)
+        else:
+            y_index = None
 
         if cutoff is None and not isinstance(y_index, pd.MultiIndex):
             _cutoff = get_cutoff(y)
@@ -720,15 +723,15 @@ class ForecastingHorizon:
             fh_idx = pd.Index(self.to_absolute_index(_cutoff))
 
         if cutoff is not None and isinstance(y_index, pd.MultiIndex):
-            y_inst_idx = y_index.droplevel(-1).unique()
+            y_inst_idx = y_index.droplevel(-1).unique().sort_values()
             if isinstance(y_inst_idx, pd.MultiIndex) and sort_by_time:
-                fh_list = [x + (y,) for x in y_inst_idx for y in fh_idx]
-            elif isinstance(y_inst_idx, pd.MultiIndex) and not sort_by_time:
                 fh_list = [x + (y,) for y in fh_idx for x in y_inst_idx]
+            elif isinstance(y_inst_idx, pd.MultiIndex) and not sort_by_time:
+                fh_list = [x + (y,) for x in y_inst_idx for y in fh_idx]
             elif sort_by_time:  # and not isinstance(y_inst_idx, pd.MultiIndex):
-                fh_list = [(x, y) for x in y_inst_idx for y in fh_idx]
-            else:  # not sort_by_time and not isinstance(y_inst_idx, pd.MultiIndex):
                 fh_list = [(x, y) for y in fh_idx for x in y_inst_idx]
+            else:  # not sort_by_time and not isinstance(y_inst_idx, pd.MultiIndex):
+                fh_list = [(x, y) for x in y_inst_idx for y in fh_idx]
 
             fh_idx = pd.Index(fh_list)
 
diff --git a/sktime/forecasting/base/_sktime.py b/sktime/forecasting/base/_sktime.py
index 681f7b808..47755bd3d 100644
--- a/sktime/forecasting/base/_sktime.py
+++ b/sktime/forecasting/base/_sktime.py
@@ -8,7 +8,7 @@ __all__ = ["_BaseWindowForecaster"]
 import numpy as np
 import pandas as pd
 
-from sktime.forecasting.base._base import DEFAULT_ALPHA, BaseForecaster
+from sktime.forecasting.base._base import BaseForecaster
 from sktime.split import CutoffSplitter
 from sktime.utils.datetime import _shift
 
@@ -21,41 +21,50 @@ class _BaseWindowForecaster(BaseForecaster):
         self.window_length = window_length
         self.window_length_ = None
 
-    def _predict(self, fh, X):
-        """Predict core logic."""
-        kwargs = {"X": X}
+    def _predict_boilerplate(self, fh, **kwargs):
+        """Dispatcher to in-sample and out-of-sample logic.
+
+        In-sample logic is implemented in _predict_in_sample.
+        Out-of-sample logic is implemented in _predict_fixed_cutoff.
+        """
+        cutoff = self._cutoff
 
         # all values are out-of-sample
-        if fh.is_all_out_of_sample(self.cutoff):
-            y_pred = self._predict_fixed_cutoff(
-                fh.to_out_of_sample(self.cutoff), **kwargs
-            )
+        if fh.is_all_out_of_sample(cutoff):
+            y_pred = self._predict_fixed_cutoff(fh.to_out_of_sample(cutoff), **kwargs)
 
         # all values are in-sample
         elif fh.is_all_in_sample(self.cutoff):
-            y_pred = self._predict_in_sample(fh.to_in_sample(self.cutoff), **kwargs)
+            y_pred = self._predict_in_sample(fh.to_in_sample(cutoff), **kwargs)
 
         # both in-sample and out-of-sample values
         else:
-            y_ins = self._predict_in_sample(fh.to_in_sample(self.cutoff), **kwargs)
-            y_oos = self._predict_fixed_cutoff(
-                fh.to_out_of_sample(self.cutoff), **kwargs
-            )
+            y_ins = self._predict_in_sample(fh.to_in_sample(cutoff), **kwargs)
+            y_oos = self._predict_fixed_cutoff(fh.to_out_of_sample(cutoff), **kwargs)
 
             if isinstance(y_ins, pd.DataFrame) and isinstance(y_oos, pd.Series):
                 y_oos = y_oos.to_frame(y_ins.columns[0])
 
             y_pred = pd.concat([y_ins, y_oos])
 
+        return y_pred
+
+    def _predict(self, fh, X):
+        """Predict core logic."""
+        kwargs = {"X": X}
+
+        y_pred = self._predict_boilerplate(fh, **kwargs)
+
         # ensure pd.Series name attribute is preserved
         if isinstance(y_pred, pd.Series) and isinstance(self._y, pd.Series):
             y_pred.name = self._y.name
+        if isinstance(y_pred, pd.DataFrame) and isinstance(self._y, pd.Series):
+            y_pred = y_pred.iloc[:, 0]
+            y_pred.name = self._y.name
 
         return y_pred
 
-    def _predict_fixed_cutoff(
-        self, fh, X=None, return_pred_int=False, alpha=DEFAULT_ALPHA
-    ):
+    def _predict_fixed_cutoff(self, fh, X=None, **kwargs):
         """Make single-step or multi-step fixed cutoff predictions.
 
         Parameters
@@ -63,26 +72,20 @@ class _BaseWindowForecaster(BaseForecaster):
         fh : np.array
             all positive (> 0)
         X : pd.DataFrame
-        return_pred_int : bool
-        alpha : float or array-like
 
         Returns
         -------
         y_pred = pd.Series or pd.DataFrame
         """
         # assert all(fh > 0)
-        y_pred = self._predict_last_window(
-            fh, X, return_pred_int=return_pred_int, alpha=alpha
-        )
+        y_pred = self._predict_last_window(fh, X=X, **kwargs)
         if isinstance(y_pred, pd.Series) or isinstance(y_pred, pd.DataFrame):
             return y_pred
         else:
             index = fh.to_absolute_index(self.cutoff)
             return pd.Series(y_pred, index=index)
 
-    def _predict_in_sample(
-        self, fh, X=None, return_pred_int=False, alpha=DEFAULT_ALPHA
-    ):
+    def _predict_in_sample(self, fh, X=None, **kwargs):
         """Make in-sample prediction using single-step moving-cutoff predictions.
 
         Parameters
@@ -90,16 +93,11 @@ class _BaseWindowForecaster(BaseForecaster):
         fh : np.array
             all non-positive (<= 0)
         X : pd.DataFrame
-        return_pred_int : bool
-        alpha : float or array-like
 
         Returns
         -------
         y_pred : pd.DataFrame or pd.Series
         """
-        if return_pred_int:
-            raise NotImplementedError()
-
         y_train = self._y
 
         # generate cutoffs from forecasting horizon, note that cutoffs are
@@ -108,17 +106,13 @@ class _BaseWindowForecaster(BaseForecaster):
         cv = CutoffSplitter(cutoffs, fh=1, window_length=self.window_length_)
         return self._predict_moving_cutoff(y_train, cv, X, update_params=False)
 
-    def _predict_last_window(
-        self, fh, X=None, return_pred_int=False, alpha=DEFAULT_ALPHA
-    ):
+    def _predict_last_window(self, fh, X=None, **kwargs):
         """Predict core logic.
 
         Parameters
         ----------
         fh : np.array
         X : pd.DataFrame
-        return_pred_int : bool
-        alpha : float or list of floats
 
         Returns
         -------
@@ -141,7 +135,32 @@ class _BaseWindowForecaster(BaseForecaster):
 
         return y, X
 
-    @staticmethod
-    def _predict_nan(fh):
-        """Predict nan if predictions are not possible."""
-        return np.full(len(fh), np.nan)
+    def _predict_nan(self, fh=None, method="predict", **kwargs):
+        """Create a return DataFrame for predict-like method, with all np.nan entries.
+
+        Parameters
+        ----------
+        fh : ForecastingHorizon of self, optional (default=None)
+            retrieved from self.fh if None
+        method : str, optional (default="predict")
+            method name to generate return DataFrame for
+            name of one of the BaseForecaster predict-like methods
+        **kwargs : optional
+            further kwargs to predict-like methods, e.g., coverage for predict_interval
+            passed to self._get_columns
+
+        Returns
+        -------
+        y_pred : pd.DataFrame
+            return DataFrame
+            index, columns are as expected
+            all entries are np.nan
+        """
+        if fh is None:
+            fh = self.fh
+
+        index = fh.get_expected_pred_idx(y=self._y, cutoff=self.cutoff)
+        columns = self._get_columns(method=method, **kwargs)
+
+        y_pred = pd.DataFrame(np.nan, index=index, columns=columns)
+        return y_pred
diff --git a/sktime/forecasting/compose/_ensemble.py b/sktime/forecasting/compose/_ensemble.py
index f523479d6..e4211319b 100644
--- a/sktime/forecasting/compose/_ensemble.py
+++ b/sktime/forecasting/compose/_ensemble.py
@@ -364,8 +364,14 @@ class EnsembleForecaster(_HeterogenousEnsembleForecaster):
         """
         names, _ = self._check_forecasters()
         y_pred = pd.concat(self._predict_forecasters(fh, X), axis=1, keys=names)
-        y_pred = y_pred.groupby(level=1, axis=1).agg(
-            _aggregate, self.aggfunc, self.weights
+        y_pred = (
+            y_pred.T.groupby(level=1)
+            .agg(
+                lambda y, aggfunc, weights: _aggregate(y.T, aggfunc, weights),
+                self.aggfunc,
+                self.weights,
+            )
+            .T
         )
         return y_pred
 
diff --git a/sktime/forecasting/compose/_reduce.py b/sktime/forecasting/compose/_reduce.py
index 460080070..d8c727cb6 100644
--- a/sktime/forecasting/compose/_reduce.py
+++ b/sktime/forecasting/compose/_reduce.py
@@ -32,7 +32,6 @@ from sklearn.multioutput import MultiOutputRegressor
 
 from sktime.datatypes._utilities import get_time_index
 from sktime.forecasting.base import BaseForecaster, ForecastingHorizon
-from sktime.forecasting.base._base import DEFAULT_ALPHA
 from sktime.forecasting.base._fh import _index_range
 from sktime.forecasting.base._sktime import _BaseWindowForecaster
 from sktime.regression.base import BaseRegressor
@@ -184,13 +183,13 @@ def _sliding_window_transform(
         Xt = Zt[:, :, :window_length]
     # Pre-allocate array for sliding windows.
     # If the scitype is tabular regression, we have to convert X into a 2d array.
-    if scitype == "tabular-regressor":
-        if transformers is not None:
-            return yt, Xt
-        else:
-            return yt, Xt.reshape(Xt.shape[0], -1)
-    else:
-        return yt, Xt
+    if scitype == "tabular-regressor" and transformers is None:
+        Xt = Xt.reshape(Xt.shape[0], -1)
+
+    assert Xt.ndim == 2 or Xt.ndim == 3
+    assert yt.ndim == 2
+
+    return yt, Xt
 
 
 class _Reducer(_BaseWindowForecaster):
@@ -200,6 +199,7 @@ class _Reducer(_BaseWindowForecaster):
         "ignores-exogeneous-X": False,  # reduction uses X in non-trivial way
         "handles-missing-data": True,
         "capability:insample": False,
+        "capability:pred_int": True,
     }
 
     def __init__(
@@ -221,6 +221,25 @@ class _Reducer(_BaseWindowForecaster):
         # therefore this is commented out until sktime and sklearn are better aligned
         # self.set_tags(**{"handles-missing-data": estimator._get_tags()["allow_nan"]})
 
+        # for dealing with probabilistic regressors:
+        # self._est_type encodes information what type of estimator is passed
+        if hasattr(estimator, "get_tags"):
+            _est_type = estimator.get_tag("object_type", "regressor", False)
+        else:
+            _est_type = "regressor"
+
+        if _est_type not in ["regressor", "regressor_proba"]:
+            raise TypeError(
+                f"error in {type(self).__name}, "
+                "estimator must be either an sklearn compatible "
+                "regressor, or an skpro probabilistic regressor."
+            )
+
+        # has probabilistic mode iff the estimator is of type regressor_proba
+        self.set_tags(**{"capability:pred_int": _est_type == "regressor_proba"})
+
+        self._est_type = _est_type
+
     def _is_predictable(self, last_window):
         """Check if we can make predictions from last window."""
         return (
@@ -229,7 +248,26 @@ class _Reducer(_BaseWindowForecaster):
             and np.sum(np.isinf(last_window)) == 0
         )
 
-    def _predict_in_sample(self, fh, X=None, return_pred_int=False, alpha=None):
+    def _predict_quantiles(self, fh, X, alpha):
+        """Compute/return prediction quantiles for a forecast.
+
+        Parameters
+        ----------
+        fh : guaranteed to be ForecastingHorizon
+            The forecasting horizon with the steps ahead to to predict.
+        X :  sktime time series object, optional (default=None)
+            guaranteed to be of an mtype in self.get_tag("X_inner_mtype")
+            Exogeneous time series for the forecast
+        alpha : list of float (guaranteed not None and floats in [0,1] interval)
+            A list of probabilities at which quantile forecasts are computed.
+        """
+        kwargs = {"X": X, "alpha": alpha, "method": "predict_quantiles"}
+
+        y_pred = self._predict_boilerplate(fh, **kwargs)
+
+        return y_pred
+
+    def _predict_in_sample(self, fh, X=None, **kwargs):
         # Note that we currently only support out-of-sample predictions. For the
         # direct and multioutput strategy, we need to check this already during fit,
         # as the fh is required for fitting.
@@ -260,6 +298,7 @@ class _Reducer(_BaseWindowForecaster):
         from sklearn.pipeline import make_pipeline
 
         from sktime.transformations.panel.reduce import Tabularizer
+        from sktime.utils.validation._dependencies import _check_soft_dependencies
 
         # naming convention is as follows:
         #   reducers with Tabular take an sklearn estimator, e.g., LinearRegressor
@@ -270,7 +309,26 @@ class _Reducer(_BaseWindowForecaster):
         if "TimeSeries" in cls.__name__:
             est = make_pipeline(Tabularizer(), est)
 
-        params = {"estimator": est, "window_length": 3}
+        params = [{"estimator": est, "window_length": 3}]
+
+        PROBA_IMPLEMENTED = ["DirectTabularRegressionForecaster"]
+        self_supports_proba = cls.__name__ in PROBA_IMPLEMENTED
+
+        if _check_soft_dependencies("skpro", severity="none") and self_supports_proba:
+            from skpro.regression.residual import ResidualDouble
+
+            params_proba_local = {
+                "estimator": ResidualDouble.create_test_instance(),
+                "pooling": "local",
+                "window_length": 3,
+            }
+            params_proba_global = {
+                "estimator": ResidualDouble.create_test_instance(),
+                "pooling": "global",
+                "window_length": 4,
+            }
+            params = params + [params_proba_local, params_proba_global]
+
         return params
 
     def _get_shifted_window(self, shift=0, y_update=None, X_update=None):
@@ -511,6 +569,8 @@ class _DirectReducer(_Reducer):
             raise NotImplementedError("In-sample predictions are not implemented.")
 
         yt, Xt = self._transform(y, X)
+        if hasattr(Xt, "columns"):
+            Xt.columns = Xt.columns.astype(str)
 
         # Iterate over forecasting horizon, fitting a separate estimator for each step.
         self.estimators_ = []
@@ -520,23 +580,26 @@ class _DirectReducer(_Reducer):
 
             if self.transformers_ is not None:
                 fh_rel = fh.to_relative(self.cutoff)
-                yt = _cut_df(yt, n_timepoints - fh_rel[i] + 1)
-                Xt = _cut_df(Xt, n_timepoints - fh_rel[i] + 1, type="head")
-                estimator.fit(Xt, yt)
+                Xt_cut = _cut_df(Xt, n_timepoints - fh_rel[i] + 1, type="head")
+                yt_cut = _cut_df(yt, n_timepoints - fh_rel[i] + 1)
+            elif self.windows_identical is True or (fh_rel[i] - 1) == 0:
+                Xt_cut = Xt
+                yt_cut = yt[:, i]
             else:
-                if self.windows_identical is True:
-                    estimator.fit(Xt, yt[:, i])
-                else:
-                    if (fh_rel[i] - 1) == 0:
-                        estimator.fit(Xt, yt[:, i])
-                    else:
-                        estimator.fit(Xt[: -(fh_rel[i] - 1)], yt[: -(fh_rel[i] - 1), i])
+                Xt_cut = Xt[: -(fh_rel[i] - 1)]
+                yt_cut = yt[: -(fh_rel[i] - 1), i]
+
+            # coercion to pandas for skpro proba regressors
+            if self._est_type != "regressor" and not isinstance(Xt, pd.DataFrame):
+                Xt_cut = pd.DataFrame(Xt_cut)
+            if self._est_type != "regressor" and not isinstance(yt, pd.DataFrame):
+                yt_cut = pd.DataFrame(yt_cut)
+
+            estimator.fit(Xt_cut, yt_cut)
             self.estimators_.append(estimator)
         return self
 
-    def _predict_last_window(
-        self, fh, X=None, return_pred_int=False, alpha=DEFAULT_ALPHA
-    ):
+    def _predict_last_window(self, fh, X=None, **kwargs):
         """.
 
         In recursive reduction, iteration must be done over the
@@ -551,13 +614,20 @@ class _DirectReducer(_Reducer):
             Forecasting horizon
         X : pd.DataFrame, optional (default=None)
             Exogenous time series
-        return_pred_int : bool
-        alpha : float or array-like
 
         Returns
         -------
         y_return = pd.Series or pd.DataFrame
         """
+        if "method" in kwargs:
+            method = kwargs.pop("method")
+        else:
+            method = "predict"
+
+        # estimator type for case branches
+        est_type = self._est_type
+        # "regressor" for sklearn, "regressor_proba" for skpro
+
         if self._X is not None and X is None:
             raise ValueError(
                 "`X` must be passed to `predict` if `X` is given in `fit`."
@@ -567,22 +637,51 @@ class _DirectReducer(_Reducer):
             y_last, X_last = self._get_shifted_window(X_update=X)
             ys = np.array(y_last)
             if not np.sum(np.isnan(ys)) == 0 and np.sum(np.isinf(ys)) == 0:
-                return self._predict_nan(fh)
+                return self._predict_nan(fh, method=method, **kwargs)
         else:
             y_last, X_last = self._get_last_window()
             if not self._is_predictable(y_last):
-                return self._predict_nan(fh)
+                return self._predict_nan(fh, method=method, **kwargs)
         # Get last window of available data.
         # If we cannot generate a prediction from the available data, return nan.
 
+        if isinstance(X_last, pd.DataFrame):
+            X_last = prep_skl_df(X_last)
+
+        def pool_preds(y_preds):
+            """Pool predictions from different estimators.
+
+            Parameters
+            ----------
+            y_preds : list of pd.DataFrame
+                List of predictions from different estimators.
+            """
+            y_pred = y_preds.pop(0)
+            for y_pred_i in y_preds:
+                y_pred = y_pred.combine_first(y_pred_i)
+            return y_pred
+
+        def _coerce_to_numpy(y_pred):
+            """Coerce predictions to numpy array, assumes pd.DataFram or numpy."""
+            if isinstance(y_pred, pd.DataFrame):
+                return y_pred.values
+            else:
+                return y_pred
+
         if self.pooling == "global":
             fh_abs = fh.to_absolute_index(self.cutoff)
-            y_pred = _create_fcst_df(fh_abs, self._y)
+            y_preds = []
 
             for i, estimator in enumerate(self.estimators_):
-                y_pred_short = estimator.predict(X_last)
-                y_pred_curr = _create_fcst_df([fh_abs[i]], self._y, fill=y_pred_short)
-                y_pred.update(y_pred_curr)
+                y_pred_est = getattr(estimator, method)(X_last, **kwargs)
+                if est_type == "regressor":
+                    y_pred_i = _create_fcst_df([fh_abs[i]], self._y, fill=y_pred_est)
+                else:  # est_type == "regressor_proba"
+                    y_pred_v = _coerce_to_numpy(y_pred_est)
+                    y_pred_i = _create_fcst_df([fh_abs[i]], y_pred_est, fill=y_pred_v)
+                y_preds.append(y_pred_i)
+            y_pred = pool_preds(y_preds)
+
         else:
             # Pre-allocate arrays.
             if self._X is None:
@@ -606,11 +705,33 @@ class _DirectReducer(_Reducer):
                 X_pred = X_pred.reshape(1, -1)
 
             # Allocate array for predictions.
-            y_pred = np.zeros(len(fh))
+            if est_type == "regressor":
+                y_pred = np.zeros(len(fh))
+            else:  # est_type == "regressor_proba"
+                y_preds = []
 
             # Iterate over estimators/forecast horizon
             for i, estimator in enumerate(self.estimators_):
-                y_pred[i] = estimator.predict(X_pred)
+                y_pred_est = getattr(estimator, method)(X_pred, **kwargs)
+                if est_type == "regressor":
+                    y_pred[i] = y_pred_est
+                else:  # est_type == "regressor_proba"
+                    y_pred_v = _coerce_to_numpy(y_pred_est)
+                    y_pred_i = _create_fcst_df([fh[i]], y_pred_est, fill=y_pred_v)
+                    y_preds.append(y_pred_i)
+
+            if est_type != "regressor":
+                y_pred = pool_preds(y_preds)
+
+        # coerce index and columns to expected
+        index = fh.get_expected_pred_idx(y=self._y, cutoff=self.cutoff)
+        columns = self._get_columns(method=method, **kwargs)
+        if isinstance(y_pred, pd.DataFrame):
+            y_pred.index = index
+            y_pred.columns = columns
+        else:
+            y_pred = pd.DataFrame(y_pred, index=index, columns=columns)
+
         return y_pred
 
 
@@ -663,9 +784,7 @@ class _MultioutputReducer(_Reducer):
         self.estimator_.fit(Xt, yt)
         return self
 
-    def _predict_last_window(
-        self, fh, X=None, return_pred_int=False, alpha=DEFAULT_ALPHA
-    ):
+    def _predict_last_window(self, fh, X=None, **kwargs):
         """Predict to training data.
 
         Parameters
@@ -674,8 +793,6 @@ class _MultioutputReducer(_Reducer):
             Forecasting horizon
         X : pd.DataFrame, optional (default=None)
             Exogenous time series
-        return_pred_int : bool
-        alpha : float or array-like
 
         Returns
         -------
@@ -826,9 +943,7 @@ class _RecursiveReducer(_Reducer):
         self.estimator_.fit(Xt, yt)
         return self
 
-    def _predict_last_window(
-        self, fh, X=None, return_pred_int=False, alpha=DEFAULT_ALPHA
-    ):
+    def _predict_last_window(self, fh, X=None, **kwargs):
         """.
 
         In recursive reduction, iteration must be done over the
@@ -1034,9 +1149,7 @@ class _DirRecReducer(_Reducer):
             self.estimators_.append(estimator)
         return self
 
-    def _predict_last_window(
-        self, fh, X=None, return_pred_int=False, alpha=DEFAULT_ALPHA
-    ):
+    def _predict_last_window(self, fh, X=None, **kwargs):
         """Fit to training data.
 
         Parameters
@@ -1045,8 +1158,6 @@ class _DirRecReducer(_Reducer):
             Forecasting horizon
         X : pd.DataFrame, optional (default=None)
             Exogenous time series
-        return_pred_int : bool
-        alpha : float or array-like
 
         Returns
         -------
@@ -1406,20 +1517,27 @@ def make_reduction(
 
     Parameters
     ----------
-    estimator : an estimator instance
-        Either a tabular regressor from scikit-learn or a time series regressor from
-        sktime.
+    estimator : an estimator instance, can be:
+
+        * scikit-learn regressor or interface compatible
+        * sktime time series regressor
+        * skpro tabular probabilistic supervised regressor, only for direct reduction
+          this will result in a probabilistic forecaster
+
     strategy : str, optional (default="recursive")
         The strategy to generate forecasts. Must be one of "direct", "recursive" or
         "multioutput".
+
     window_length : int, optional (default=10)
         Window length used in sliding window transformation.
+
     scitype : str, optional (default="infer")
         Legacy argument for downwards compatibility, should not be used.
         `make_reduction` will automatically infer the correct type of `estimator`.
         This internal inference can be force-overridden by the `scitype` argument.
         Must be one of "infer", "tabular-regressor" or "time-series-regressor".
         If the scitype cannot be inferred, this is a bug and should be reported.
+
     transformers: list of transformers (default = None)
         A suitable list of transformers that allows for using an en-bloc approach with
         make_reduction. This means that instead of using the raw past observations of
@@ -1427,10 +1545,12 @@ def make_reduction(
         the past raw observations. Currently only supports WindowSummarizer (or a list
         of WindowSummarizers) to generate features e.g. the mean of the past 7
         observations. Currently only works for RecursiveTimeSeriesRegressionForecaster.
+
     pooling: str {"local", "global"}, optional
         Specifies whether separate models will be fit at the level of each instance
         (local) of if you wish to fit a single model to all instances ("global").
         Currently only works for RecursiveTimeSeriesRegressionForecaster.
+
     windows_identical: bool, (default = True)
         Direct forecasting only.
         Specifies whether all direct models use the same X windows from y (True: Number
@@ -1441,8 +1561,9 @@ def make_reduction(
 
     Returns
     -------
-    estimator : an Estimator instance
-        A reduction forecaster
+    forecaster : an sktime forecaster object
+        the reduction forecaster, wrapping ``estimator``
+        class is determined by the ``strategy`` argument and type of ``estimator``.
 
     Examples
     --------
@@ -1545,11 +1666,11 @@ def _cut_df(X, n_obs=1, type="tail"):
     if n_obs == 0:
         return X.copy()
     if isinstance(X.index, pd.MultiIndex):
-        Xi_grp = X.index.names[0:-1]
+        levels = list(range(X.index.nlevels - 1))
         if type == "tail":
-            X = X.groupby(Xi_grp, as_index=False).tail(n_obs)
+            X = X.groupby(level=levels, as_index=False).tail(n_obs)
         elif type == "head":
-            X = X.groupby(Xi_grp, as_index=False).head(n_obs)
+            X = X.groupby(level=levels, as_index=False).head(n_obs)
     else:
         if type == "tail":
             X = X.tail(n_obs)
diff --git a/sktime/forecasting/model_selection/_tune.py b/sktime/forecasting/model_selection/_tune.py
index 5c11825bf..0a68e35b9 100644
--- a/sktime/forecasting/model_selection/_tune.py
+++ b/sktime/forecasting/model_selection/_tune.py
@@ -401,16 +401,16 @@ class ForecastingGridSearchCV(BaseGridSearch):
 
     Parameters
     ----------
-    forecaster : estimator object
-        The estimator should implement the sktime or scikit-learn estimator
-        interface. Either the estimator must contain a "score" function,
-        or a scoring function must be passed.
+    forecaster : sktime forecaster, BaseForecaster instance or interface compatible
+        The forecaster to tune, must implement the sktime forecaster interface.
+        sklearn regressors can be used, but must first be converted to forecasters
+        via one of the reduction compositors, e.g., via ``make_reduction``
     cv : cross-validation generator or an iterable
         e.g. SlidingWindowSplitter()
     strategy : {"refit", "update", "no-update_params"}, optional, default="refit"
         data ingestion strategy in fitting cv, passed to `evaluate` internally
         defines the ingestion mode when the forecaster sees new data when window expands
-        "refit" = forecaster is refitted to each training window
+        "refit" = a new copy of the forecaster is fitted to each training window
         "update" = forecaster is updated with training window data, in sequence provided
         "no-update_params" = fit to first training window, re-used without fit or update
     update_behaviour : str, optional, default = "full_refit"
@@ -728,16 +728,16 @@ class ForecastingRandomizedSearchCV(BaseGridSearch):
 
     Parameters
     ----------
-    forecaster : estimator object
-        The estimator should implement the sktime or scikit-learn estimator
-        interface. Either the estimator must contain a "score" function,
-        or a scoring function must be passed.
+    forecaster : sktime forecaster, BaseForecaster instance or interface compatible
+        The forecaster to tune, must implement the sktime forecaster interface.
+        sklearn regressors can be used, but must first be converted to forecasters
+        via one of the reduction compositors, e.g., via ``make_reduction``
     cv : cross-validation generator or an iterable
         e.g. SlidingWindowSplitter()
     strategy : {"refit", "update", "no-update_params"}, optional, default="refit"
         data ingestion strategy in fitting cv, passed to `evaluate` internally
         defines the ingestion mode when the forecaster sees new data when window expands
-        "refit" = forecaster is refitted to each training window
+        "refit" = a new copy of the forecaster is fitted to each training window
         "update" = forecaster is updated with training window data, in sequence provided
         "no-update_params" = fit to first training window, re-used without fit or update
     update_behaviour: str, optional, default = "full_refit"
@@ -973,10 +973,10 @@ class ForecastingSkoptSearchCV(BaseGridSearch):
 
     Parameters
     ----------
-    forecaster : estimator object.
-        The estimator should implement the sktime or scikit-learn estimator interface.
-        Either the estimator must contain a "score" function,
-        or a scoring function must be passed.
+    forecaster : sktime forecaster, BaseForecaster instance or interface compatible
+        The forecaster to tune, must implement the sktime forecaster interface.
+        sklearn regressors can be used, but must first be converted to forecasters
+        via one of the reduction compositors, e.g., via ``make_reduction``
     cv : cross-validation generator or an iterable
         Splitter used for generating validation folds.
         e.g. SlidingWindowSplitter()
@@ -1034,7 +1034,7 @@ class ForecastingSkoptSearchCV(BaseGridSearch):
     strategy : {"refit", "update", "no-update_params"}, optional, default="refit"
         data ingestion strategy in fitting cv, passed to `evaluate` internally
         defines the ingestion mode when the forecaster sees new data when window expands
-        "refit" = forecaster is refitted to each training window
+        "refit" = a new copy of the forecaster is fitted to each training window
         "update" = forecaster is updated with training window data, in sequence provided
         "no-update_params" = fit to first training window, re-used without fit or update
     update_behaviour: str, optional, default = "full_refit"
diff --git a/sktime/param_est/base.py b/sktime/param_est/base.py
index d1a430e76..9f4bb8335 100644
--- a/sktime/param_est/base.py
+++ b/sktime/param_est/base.py
@@ -381,23 +381,3 @@ class BaseParamFitter(BaseEstimator):
         # but looping to self.fit for now to avoid interface break
 
         return self
-
-    def _get_fitted_params(self):
-        """Get fitted parameters.
-
-        private _get_fitted_params, called from get_fitted_params
-
-        State required:
-            Requires state to be "fitted".
-
-        Returns
-        -------
-        fitted_params : dict
-        """
-        # default retrieves all self attributes ending in "_"
-        # and returns them with keys that have the "_" removed
-        fitted_params = [attr for attr in dir(self) if attr.endswith("_")]
-        fitted_params = [x for x in fitted_params if not x.startswith("_")]
-        fitted_param_dict = {p[:-1]: getattr(self, p) for p in fitted_params}
-
-        return fitted_param_dict
diff --git a/sktime/param_est/stationarity/_statsmodels.py b/sktime/param_est/stationarity/_statsmodels.py
index 21813a4b7..20bd57e64 100644
--- a/sktime/param_est/stationarity/_statsmodels.py
+++ b/sktime/param_est/stationarity/_statsmodels.py
@@ -158,7 +158,7 @@ class StationarityADF(BaseParamFitter):
 class StationarityKPSS(BaseParamFitter):
     """Test for stationarity via the Kwiatkowski-Phillips-Schmidt-Shin Test.
 
-    Uses ``statsmodels.tsa.stattools.kpss`` as a test for trend-stationairty,
+    Uses ``statsmodels.tsa.stattools.kpss`` as a test for trend-stationarity,
     and derives a boolean statement whether a series is (trend-)stationary.
 
     Also returns test results for the trend-stationarity test as fitted parameters.
diff --git a/sktime/performance_metrics/forecasting/_classes.py b/sktime/performance_metrics/forecasting/_classes.py
index 08d331383..e8311bd53 100644
--- a/sktime/performance_metrics/forecasting/_classes.py
+++ b/sktime/performance_metrics/forecasting/_classes.py
@@ -573,6 +573,10 @@ class BaseForecastingErrorMetricFunc(BaseForecastingErrorMetric):
         else:
             func = self.func
 
+        return self._evaluate_func(func=func, y_true=y_true, y_pred=y_pred, **params)
+
+    def _evaluate_func(self, func, y_true, y_pred, **params):
+        """Call func with kwargs subset to func parameters."""
         # import here for now to avoid interaction with getmembers in tests
         # todo: clean up ancient getmembers in test_metrics_classes
         from functools import partial
@@ -584,6 +588,15 @@ class BaseForecastingErrorMetricFunc(BaseForecastingErrorMetric):
             func_params = func_params.intersection(params.keys())
             params = {key: params[key] for key in func_params}
 
+        # deal with sklearn specific parameter constraints
+        # as these are a decorator, they obfuscate python native inspection
+        # via signature, so have to be dealt with separately
+        if hasattr(func, "_skl_parameter_constraints"):
+            constr = func._skl_parameter_constraints
+            if isinstance(constr, dict):
+                constr_params = set(constr.keys()).intersection(params.keys())
+                params = {key: params[key] for key in constr_params}
+
         res = func(y_true=y_true, y_pred=y_pred, **params)
         return res
 
@@ -609,6 +622,16 @@ class _DynamicForecastingErrorMetric(BaseForecastingErrorMetricFunc):
 
         self.set_tags(**{"lower_is_better": lower_is_better})
 
+    def _evaluate(self, y_true, y_pred, **kwargs):
+        """Evaluate the desired metric on given inputs."""
+        # this dict should contain all parameters
+        params = kwargs
+        params.update({"multioutput": self.multioutput, "multilevel": self.multilevel})
+
+        func = self.func
+
+        return self._evaluate_func(func=func, y_true=y_true, y_pred=y_pred, **params)
+
     @classmethod
     def get_test_params(cls, parameter_set="default"):
         """Return testing parameter settings for the estimator.
diff --git a/sktime/performance_metrics/forecasting/probabilistic/_classes.py b/sktime/performance_metrics/forecasting/probabilistic/_classes.py
index 2c6d07223..9208d73c3 100644
--- a/sktime/performance_metrics/forecasting/probabilistic/_classes.py
+++ b/sktime/performance_metrics/forecasting/probabilistic/_classes.py
@@ -119,16 +119,16 @@ class _BaseProbaForecastingErrorMetric(BaseForecastingErrorMetric):
 
         if isinstance(multioutput, str):
             if self.score_average and multioutput == "uniform_average":
-                out = float(out.mean(axis=1).iloc[0])  # average over all
+                out = out.mean(axis=1).iloc[0]  # average over all
             if self.score_average and multioutput == "raw_values":
-                out = out.groupby(axis=1, level=0).mean()  # average over scores
+                out = out.T.groupby(level=0).mean().T  # average over scores
             if not self.score_average and multioutput == "uniform_average":
-                out = out.groupby(axis=1, level=1).mean()  # average over variables
+                out = out.T.groupby(level=1).mean().T  # average over variables
             if not self.score_average and multioutput == "raw_values":
                 out = out  # don't average
         else:  # is np.array with weights
             if self.score_average:
-                out_raw = out.groupby(axis=1, level=0).mean()
+                out_raw = out.T.groupby(level=0).mean().T
                 out = out_raw.dot(multioutput)[0]
             else:
                 out = _groupby_dot(out, multioutput)
@@ -215,14 +215,14 @@ class _BaseProbaForecastingErrorMetric(BaseForecastingErrorMetric):
             if self.score_average and multioutput == "uniform_average":
                 out = out.mean(axis=1)  # average over all
             if self.score_average and multioutput == "raw_values":
-                out = out.groupby(axis=1, level=0).mean()  # average over scores
+                out = out.T.groupby(level=0).mean().T  # average over scores
             if not self.score_average and multioutput == "uniform_average":
-                out = out.groupby(axis=1, level=1).mean()  # average over variables
+                out = out.T.groupby(level=1).mean().T  # average over variables
             if not self.score_average and multioutput == "raw_values":
                 out = out  # don't average
         else:  # numpy array
             if self.score_average:
-                out_raw = out.groupby(axis=1, level=0).mean()
+                out_raw = out.T.groupby(level=0).mean().T
                 out = out_raw.dot(multioutput)
             else:
                 out = _groupby_dot(out, multioutput)
diff --git a/sktime/proba/base.py b/sktime/proba/base.py
index a1dd59f9a..8dc315094 100644
--- a/sktime/proba/base.py
+++ b/sktime/proba/base.py
@@ -29,6 +29,7 @@ class BaseDistribution(BaseObject):
         "approx_var_spl": 1000,  # sample size used in MC estimates of var
         "approx_energy_spl": 1000,  # sample size used in MC estimates of energy
         "approx_spl": 1000,  # sample size used in other MC estimates
+        "bisect_iter": 1000,  # max iters for bisection method in ppf
     }
 
     def __init__(self, index=None, columns=None):
@@ -42,15 +43,15 @@ class BaseDistribution(BaseObject):
     def loc(self):
         """Location indexer.
 
-        Use `my_distribution.loc[index]` for `pandas`-like row/column subsetting of
-        `BaseDistribution` descendants.
+        Use `my_distribution.loc[index]` for `pandas`-like row/column subsetting
+        of `BaseDistribution` descendants.
 
         `index` can be any `pandas` `loc` compatible index subsetter.
 
         `my_distribution.loc[index]` or `my_distribution.loc[row_index, col_index]`
-        subset `my_distribution` to rows defined by `row_index`, cols by `col_index`, to
-        exactly the same/cols rows as `pandas` `loc` would subset rows in
-        `my_distribution.index` and columns in `my_distribution.columns`.
+        subset `my_distribution` to rows defined by `row_index`, cols by `col_index`,
+        to exactly the same/cols rows as `pandas` `loc` would subset
+        rows in `my_distribution.index` and columns in `my_distribution.columns`.
         """
         return _Indexer(ref=self, method="_loc")
 
@@ -58,15 +59,15 @@ class BaseDistribution(BaseObject):
     def iloc(self):
         """Integer location indexer.
 
-        Use `my_distribution.iloc[index]` for `pandas`-like row/column subsetting of
-        `BaseDistribution` descendants.
+        Use `my_distribution.iloc[index]` for `pandas`-like row/column subsetting
+        of `BaseDistribution` descendants.
 
         `index` can be any `pandas` `iloc` compatible index subsetter.
 
         `my_distribution.iloc[index]` or `my_distribution.iloc[row_index, col_index]`
-        subset `my_distribution` to rows defined by `row_index`, cols by `col_index`, to
-        exactly the same/cols rows as `pandas` `iloc` would subset rows in
-        `my_distribution.index` and columns in `my_distribution.columns`.
+        subset `my_distribution` to rows defined by `row_index`, cols by `col_index`,
+        to exactly the same/cols rows as `pandas` `iloc` would subset
+        rows in `my_distribution.index` and columns in `my_distribution.columns`.
         """
         return _Indexer(ref=self, method="_iloc")
 
@@ -91,9 +92,12 @@ class BaseDistribution(BaseObject):
 
         subset_param_dict = {}
         for param, val in params.items():
-            arr = np.array(val)
-            if len(arr.shape) == 0:
-                subset_param_dict
+            if val is not None:
+                arr = np.array(val)
+            else:
+                arr = None
+            # if len(arr.shape) == 0:
+            # do nothing with arr
             if len(arr.shape) >= 1 and rowidx is not None:
                 arr = arr[rowidx]
             if len(arr.shape) >= 2 and colidx is not None:
@@ -283,10 +287,42 @@ class BaseDistribution(BaseObject):
         spl = self.sample(N)
         ind = splx <= spl
 
-        return ind.groupby(level=1).mean()
+        return ind.groupby(level=1, sort=False).mean()
 
     def ppf(self, p):
         """Quantile function = percent point function = inverse cdf."""
+        if self._has_implementation_of("cdf"):
+            from scipy.optimize import bisect
+
+            max_iter = self.get_tag("bisect_iter")
+            approx_method = (
+                "by using the bisection method (scipy.optimize.bisect) on "
+                f"the cdf, at {max_iter} maximum iterations"
+            )
+            warn(self._method_error_msg("cdf", fill_in=approx_method))
+
+            result = pd.DataFrame(index=p.index, columns=p.columns, dtype="float")
+            for ix in p.index:
+                for col in p.columns:
+                    d_ix = self.loc[[ix], [col]]
+                    p_ix = p.loc[ix, col]
+
+                    def opt_fun(x):
+                        """Optimization function, to find x s.t. cdf(x) = p_ix."""
+                        x = pd.DataFrame(x, index=[ix], columns=[col])  # noqa: B023
+                        return d_ix.cdf(x).values[0][0] - p_ix  # noqa: B023
+
+                    left_bd = -1e6
+                    right_bd = 1e6
+                    while opt_fun(left_bd) > 0:
+                        left_bd *= 10
+                    while opt_fun(right_bd) < 0:
+                        right_bd *= 10
+                    result.loc[ix, col] = bisect(
+                        opt_fun, left_bd, right_bd, maxiter=max_iter
+                    )
+            return result
+
         raise NotImplementedError(self._method_error_msg("ppf", "error"))
 
     def energy(self, x=None):
@@ -331,7 +367,8 @@ class BaseDistribution(BaseObject):
 
         # approx E[abs(X-Y)] via mean of samples of abs(X-Y) obtained from splx, sply
         spl = splx - sply
-        energy = spl.apply(np.linalg.norm, axis=1, ord=1).groupby(level=1).mean()
+        energy = spl.apply(np.linalg.norm, axis=1, ord=1)
+        energy = energy.groupby(level=1, sort=False).mean()
         energy = pd.DataFrame(energy, index=self.index, columns=["energy"])
         return energy
 
@@ -354,7 +391,7 @@ class BaseDistribution(BaseObject):
         warn(self._method_error_msg("mean", fill_in=approx_method))
 
         spl = self.sample(approx_spl_size)
-        return spl.groupby(level=1).mean()
+        return spl.groupby(level=1, sort=False).mean()
 
     def var(self):
         r"""Return element/entry-wise variance of the distribution.
@@ -377,10 +414,10 @@ class BaseDistribution(BaseObject):
         spl1 = self.sample(approx_spl_size)
         spl2 = self.sample(approx_spl_size)
         spl = (spl1 - spl2) ** 2
-        return spl.groupby(level=1).mean()
+        return spl.groupby(level=1, sort=False).mean()
 
     def pdfnorm(self, a=2):
-        r"""A-norm of pdf, defaults to 2-norm.
+        r"""a-norm of pdf, defaults to 2-norm.
 
         computes a-norm of the entry marginal pdf, i.e.,
         :math:`\mathbb{E}[p_X(X)^{a-1}] = \int p(x)^a dx`,
@@ -409,7 +446,7 @@ class BaseDistribution(BaseObject):
 
         # uses formula int p(x)^a dx = E[p(X)^{a-1}], and MC approximates the RHS
         spl = [self.pdf(self.sample()) ** (a - 1) for _ in range(approx_spl_size)]
-        return pd.concat(spl, axis=0).groupby(level=1).mean()
+        return pd.concat(spl, axis=0).groupby(level=1, sort=False).mean()
 
     def _coerce_to_self_index_df(self, x):
         x = np.array(x)
@@ -431,7 +468,7 @@ class BaseDistribution(BaseObject):
         The `ppf` method also computes quantiles, but broadcasts differently, in
         `numpy` style closer to `tensorflow`.
         In contrast, this `quantile` method broadcasts
-        as forecaster `predict_quantiles`, i.e., columns first.
+        as ``sktime`` forecaster `predict_quantiles`, i.e., columns first.
 
         Parameters
         ----------
diff --git a/sktime/proba/empirical.py b/sktime/proba/empirical.py
index b19ab5f0e..f348c6e11 100644
--- a/sktime/proba/empirical.py
+++ b/sktime/proba/empirical.py
@@ -16,12 +16,12 @@ class Empirical(BaseDistribution):
     ----------
     spl : pd.DataFrame with pd.MultiIndex
         empirical sample
-        last (highest) index is time, first (lowest) index is sample
+        last (highest) index is instance, first (lowest) index is sample
     weights : pd.Series, with same index and length as spl, optional, default=None
         if not passed, ``spl`` is assumed to be unweighted
     time_indep : bool, optional, default=True
-        if True, ``sample`` will sample individual time indices independently
-        if False, ``sample`` will sample etire instances from ``spl``
+        if True, ``sample`` will sample individual instance indices independently
+        if False, ``sample`` will sample entire instances from ``spl``
     index : pd.Index, optional, default = RangeIndex
     columns : pd.Index, optional, default = RangeIndex
 
@@ -79,7 +79,6 @@ class Empirical(BaseDistribution):
 
         sorted = {}
         weights = {}
-        weights
         for t in times:
             sorted[t] = {}
             weights[t] = {}
@@ -124,8 +123,42 @@ class Empirical(BaseDistribution):
                     x_t = x.loc[ix, col]
                 else:
                     x_t = x
-                res.loc[ix, col] = func(spl=spl_t, weights=weights_t, x=x_t, **params)
-        return res.convert_dtypes()
+                res.at[ix, col] = func(spl=spl_t, weights=weights_t, x=x_t, **params)
+        return res.apply(pd.to_numeric)
+
+    def _iloc(self, rowidx=None, colidx=None):
+        index = self.index
+        columns = self.columns
+        weights = self.weights
+
+        spl_subset = self.spl
+
+        if rowidx is not None:
+            rowidx_loc = index[rowidx]
+            # subset multiindex to rowidx by last level
+            spl_subset = self.spl.loc[(slice(None), rowidx_loc), :]
+            if weights is not None:
+                weights_subset = weights.loc[(slice(None), rowidx_loc)]
+            else:
+                weights_subset = None
+            subs_rowidx = index[rowidx]
+        else:
+            subs_rowidx = index
+            weights_subset = weights
+
+        if colidx is not None:
+            spl_subset = spl_subset.iloc[:, colidx]
+            subs_colidx = columns[colidx]
+        else:
+            subs_colidx = columns
+
+        return Empirical(
+            spl_subset,
+            weights=weights_subset,
+            time_indep=self.time_indep,
+            index=subs_rowidx,
+            columns=subs_colidx,
+        )
 
     def energy(self, x=None):
         r"""Energy of self, w.r.t. self or a constant frame x.
@@ -162,9 +195,9 @@ class Empirical(BaseDistribution):
         """
         spl = self.spl
         if self.weights is None:
-            mean_df = spl.groupby(level=-1).mean()
+            mean_df = spl.groupby(level=-1, sort=False).mean()
         else:
-            mean_df = spl.groupby(level=-1).apply(
+            mean_df = spl.groupby(level=-1, sort=False).apply(
                 lambda x: np.average(x, weights=self.weights.loc[x.index], axis=0)
             )
             mean_df = pd.DataFrame(mean_df.tolist(), index=mean_df.index)
@@ -186,11 +219,11 @@ class Empirical(BaseDistribution):
         spl = self.spl
         N = self._N
         if self.weights is None:
-            var_df = spl.groupby(level=-1).var(ddof=0)
+            var_df = spl.groupby(level=-1, sort=False).var(ddof=0)
         else:
             mean = self.mean()
             means = pd.concat([mean] * N, axis=0, keys=self._spl_instances)
-            var_df = spl.groupby(level=-1).apply(
+            var_df = spl.groupby(level=-1, sort=False).apply(
                 lambda x: np.average(
                     (x - means.loc[x.index]) ** 2,
                     weights=self.weights.loc[x.index],
@@ -334,7 +367,7 @@ def _energy_np(spl, x=None, weights=None, assume_sorted=False):
 
     if x is None:
         cum_fwd = np.cumsum(weights[:-1])
-        cum_back = np.cumsum(weights[1::-1])[::-1]
+        cum_back = np.cumsum(weights[1:][::-1])[::-1]
         energy = 2 * np.sum(cum_fwd * cum_back * spl_diff)
     else:
         spl_diff = np.abs(spl - x)
diff --git a/sktime/proba/laplace.py b/sktime/proba/laplace.py
index 8f8345c61..274ce012b 100644
--- a/sktime/proba/laplace.py
+++ b/sktime/proba/laplace.py
@@ -43,7 +43,7 @@ class Laplace(BaseDistribution):
         # todo: untangle index handling
         # and broadcast of parameters.
         # move this functionality to the base class
-        self._mu, self._scale = self._get_bc_params()
+        self._mu, self._scale = self._get_bc_params(self.mu, self.scale)
         shape = self._mu.shape
 
         if index is None:
@@ -54,16 +54,6 @@ class Laplace(BaseDistribution):
 
         super().__init__(index=index, columns=columns)
 
-    def _get_bc_params(self):
-        """Fully broadcast parameters of self, given param shapes and index, columns."""
-        to_broadcast = [self.mu, self.scale]
-        if hasattr(self, "index") and self.index is not None:
-            to_broadcast += [self.index.to_numpy().reshape(-1, 1)]
-        if hasattr(self, "columns") and self.columns is not None:
-            to_broadcast += [self.columns.to_numpy()]
-        bc = np.broadcast_arrays(*to_broadcast)
-        return bc[0], bc[1]
-
     def energy(self, x=None):
         r"""Energy of self, w.r.t. self or a constant frame x.
 
diff --git a/sktime/proba/normal.py b/sktime/proba/normal.py
index 6de59c06e..3d51a19bb 100644
--- a/sktime/proba/normal.py
+++ b/sktime/proba/normal.py
@@ -44,7 +44,6 @@ class Normal(BaseDistribution):
         # todo: untangle index handling
         # and broadcast of parameters.
         # move this functionality to the base class
-        # 0.19.0?
         self._mu, self._sigma = self._get_bc_params(self.mu, self.sigma)
         shape = self._mu.shape
 
diff --git a/sktime/registry/_tags.py b/sktime/registry/_tags.py
index b40bb47b3..61da77999 100644
--- a/sktime/registry/_tags.py
+++ b/sktime/registry/_tags.py
@@ -492,6 +492,12 @@ ESTIMATOR_TAG_REGISTER = [
         "int",
         "sample size used in approximating other statistics if not available",
     ),
+    (
+        "bisect_iter",
+        "distribution",
+        "int",
+        "max iters for bisection method in ppf",
+    ),
     (
         "capability:multioutput",
         ["classifier", "regressor"],  # might need to add "early_classifier" here
diff --git a/sktime/split/base/_base_splitter.py b/sktime/split/base/_base_splitter.py
index b1325307e..64a3564df 100644
--- a/sktime/split/base/_base_splitter.py
+++ b/sktime/split/base/_base_splitter.py
@@ -113,10 +113,10 @@ class BaseSplitter(BaseObject):
         Parameters
         ----------
         y : pd.Index or time series in sktime compatible time series format,
-                time series can be in any Series, Panel, or Hierarchical mtype format
+            time series can be in any Series, Panel, or Hierarchical mtype format
             Index of time series to split, or time series to split
             If time series, considered as index of equivalent pandas type container:
-                pd.DataFrame, pd.Series, pd-multiindex, or pd_multiindex_hier mtype
+            pd.DataFrame, pd.Series, pd-multiindex, or pd_multiindex_hier mtype
 
         Yields
         ------
@@ -144,8 +144,8 @@ class BaseSplitter(BaseObject):
 
         Parameters
         ----------
-        y : pd.Index or time series in sktime compatible time series format
-            Time series to split, or index of time series to split
+        y : pd.Index
+            Index of time series to split
 
         Yields
         ------
@@ -197,8 +197,10 @@ class BaseSplitter(BaseObject):
         Parameters
         ----------
         y : pd.Index or time series in sktime compatible time series format,
-                time series can be in any Series, Panel, or Hierarchical mtype format
-            Time series to split, or index of time series to split
+            time series can be in any Series, Panel, or Hierarchical mtype format
+            Index of time series to split, or time series to split
+            If time series, considered as index of equivalent pandas type container:
+            pd.DataFrame, pd.Series, pd-multiindex, or pd_multiindex_hier mtype
 
         Yields
         ------
@@ -240,10 +242,11 @@ class BaseSplitter(BaseObject):
 
         Parameters
         ----------
-        y : time series in sktime compatible time series format,
-                time series can be in any Series, Panel, or Hierarchical mtype format
-            e.g., pd.Series, pd.DataFrame, np.ndarray
-            Time series to split, or index of time series to split
+        y : pd.Index or time series in sktime compatible time series format,
+            time series can be in any Series, Panel, or Hierarchical mtype format
+            Index of time series to split, or time series to split
+            If time series, considered as index of equivalent pandas type container:
+            pd.DataFrame, pd.Series, pd-multiindex, or pd_multiindex_hier mtype
 
         Yields
         ------
@@ -387,8 +390,11 @@ class BaseSplitter(BaseObject):
 
         Parameters
         ----------
-        y : pd.Series or pd.Index, optional (default=None)
-            Time series to split
+        y : pd.Index or time series in sktime compatible time series format,
+            time series can be in any Series, Panel, or Hierarchical mtype format
+            Index of time series to split, or time series to split
+            If time series, considered as index of equivalent pandas type container:
+            pd.DataFrame, pd.Series, pd-multiindex, or pd_multiindex_hier mtype
 
         Returns
         -------
diff --git a/sktime/transformations/panel/rocket/_multirocket.py b/sktime/transformations/panel/rocket/_multirocket.py
index 4cc186e17..3310eff46 100644
--- a/sktime/transformations/panel/rocket/_multirocket.py
+++ b/sktime/transformations/panel/rocket/_multirocket.py
@@ -8,6 +8,8 @@ import pandas as pd
 from sktime.datatypes import convert
 from sktime.transformations.base import BaseTransformer
 
+__author__ = ["ChangWeiTan", "fstinner", "angus924"]
+
 
 class MultiRocket(BaseTransformer):
     """Multi RandOm Convolutional KErnel Transform (MultiRocket).
diff --git a/sktime/transformations/panel/rocket/_multirocket_multivariate.py b/sktime/transformations/panel/rocket/_multirocket_multivariate.py
index 1fe4813f4..dc7ed5c2a 100644
--- a/sktime/transformations/panel/rocket/_multirocket_multivariate.py
+++ b/sktime/transformations/panel/rocket/_multirocket_multivariate.py
@@ -5,6 +5,8 @@ import pandas as pd
 
 from sktime.transformations.base import BaseTransformer
 
+__author__ = ["ChangWeiTan", "fstinner", "angus924"]
+
 
 class MultiRocketMultivariate(BaseTransformer):
     """Multi RandOm Convolutional KErnel Transform (MultiRocket).
@@ -198,6 +200,9 @@ class MultiRocketMultivariate(BaseTransformer):
             _quantiles,
         )
 
+        if self.random_state is not None:
+            np.random.seed(self.random_state)
+
         _, num_channels, input_length = X.shape
 
         num_kernels = 84
diff --git a/sktime/utils/index.py b/sktime/utils/index.py
new file mode 100644
index 000000000..c9c4cde9f
--- /dev/null
+++ b/sktime/utils/index.py
@@ -0,0 +1,20 @@
+"""Utility functions for working with indices."""
+
+import numpy as np
+
+
+def random_ss_ix(ix, size, replace=True):
+    """Randomly uniformly sample indices from a list of indices.
+
+    Parameters
+    ----------
+    ix : pd.Index or subsettable iterable via getitem
+        list of indices to sample from
+    size : int
+        number of indices to sample
+    replace : bool, default=True
+        whether to sample with replacement
+    """
+    a = range(len(ix))
+    ixs = ix[np.random.choice(a, size=size, replace=replace)]
+    return ixs
diff --git a/sktime/utils/parallel.py b/sktime/utils/parallel.py
index 6a8fb4090..fbfb9de63 100644
--- a/sktime/utils/parallel.py
+++ b/sktime/utils/parallel.py
@@ -108,13 +108,13 @@ def _parallelize_joblib(fun, iter, meta, backend, backend_params):
             raise ValueError(
                 '"joblib" was selected as first layer parallelization backend, '
                 "but no backend string was "
-                '"passed in the backend parameters dict, e.g., "spark". '
+                'passed in the backend parameters dict, e.g., "spark". '
                 "Please specify a backend to joblib as a key-value pair "
                 "in the backend_params arg or the backend:parallel:params config "
                 'when using "joblib". '
                 'For clarity, "joblib" should only be used for two-layer '
                 "backend dispatch, where the first layer is joblib, "
-                "and the second layer is a custom backend of joblib, e.g., spark."
+                "and the second layer is a custom backend of joblib, e.g., spark. "
                 "For first-party joblib backends, please use the backend string "
                 'of sktime directly, e.g., by specifying "multiprocessing" or "loky".'
             )
@@ -149,11 +149,29 @@ def _parallelize_dask(fun, iter, meta, backend, backend_params):
 para_dict["dask"] = _parallelize_dask
 
 
-def _get_parallel_test_fixtures():
+def _get_parallel_test_fixtures(naming="estimator"):
     """Return fixtures for parallelization tests.
 
     Returns a list of parameter fixtures, where each fixture
     is a dict with keys "backend" and "backend_params".
+
+    Parameters
+    ----------
+    naming : str, optional
+        naming convention for the parameters, one of
+
+        "estimator": for use in estimator constructors,
+        ``backend`` and ``backend_params``
+        "config": for use in ``set_config``,
+        ``backend:parallel`` and ``backend:parallel:params``
+
+    Returns
+    -------
+    fixtures : list of dict
+        list of backend parameter fixtures
+        keys depend on ``naming`` parameter, see above
+        values are backend strings and backend parameter dicts
+        only backends that are available in the environment are included
     """
     from sktime.utils.validation._dependencies import _check_soft_dependencies
 


Test patch:
diff --git a/sktime/classification/tests/test_all_classifiers.py b/sktime/classification/tests/test_all_classifiers.py
index cda9a0245..173edc08a 100644
--- a/sktime/classification/tests/test_all_classifiers.py
+++ b/sktime/classification/tests/test_all_classifiers.py
@@ -229,7 +229,8 @@ class TestAllClassifiers(ClassifierFixtureGenerator, QuickTester):
         assert isinstance(y_pred, pd.DataFrame)
         assert y_pred.shape == y_mult.shape
 
-        vectorized = estimator_instance.get_tag("capability:multioutput")
+        # the estimator vectorizes iff it does not have the multioutput capability
+        vectorized = not estimator_instance.get_tag("capability:multioutput")
         if vectorized:
             assert hasattr(estimator_instance, "classifiers_")
             assert isinstance(estimator_instance.classifiers_, pd.DataFrame)
diff --git a/sktime/forecasting/base/tests/test_base.py b/sktime/forecasting/base/tests/test_base.py
index b2dc5c0d1..a0d04b69b 100644
--- a/sktime/forecasting/base/tests/test_base.py
+++ b/sktime/forecasting/base/tests/test_base.py
@@ -20,6 +20,7 @@ from sktime.forecasting.var import VAR
 from sktime.utils._testing.hierarchical import _make_hierarchical
 from sktime.utils._testing.panel import _make_panel
 from sktime.utils._testing.series import _make_series
+from sktime.utils.parallel import _get_parallel_test_fixtures
 from sktime.utils.validation._dependencies import _check_estimator_deps
 
 PANEL_MTYPES = ["pd-multiindex", "nested_univ", "numpy3D"]
@@ -30,7 +31,7 @@ HIER_MTYPES = ["pd_multiindex_hier"]
     not _check_estimator_deps(ARIMA, severity="none"),
     reason="skip test if required soft dependency for ARIMA not available",
 )
-@pytest.mark.parametrize("backend", [None, "joblib", "loky", "threading"])
+@pytest.mark.parametrize("backend", _get_parallel_test_fixtures("config"))
 @pytest.mark.parametrize("mtype", PANEL_MTYPES)
 def test_vectorization_series_to_panel(mtype, backend):
     """Test that forecaster vectorization works for Panel data.
@@ -43,7 +44,7 @@ def test_vectorization_series_to_panel(mtype, backend):
     y = _make_panel(n_instances=n_instances, random_state=42, return_mtype=mtype)
 
     f = ARIMA()
-    f.set_config(**{"backend:parallel": backend})
+    f.set_config(**backend.copy())
     y_pred = f.fit(y).predict([1, 2, 3])
     valid, _, metadata = check_is_mtype(
         y_pred, mtype, return_metadata=True, msg_return_dict="list"
diff --git a/sktime/forecasting/model_selection/tests/test_tune.py b/sktime/forecasting/model_selection/tests/test_tune.py
index fa52904df..e1cb65dd6 100644
--- a/sktime/forecasting/model_selection/tests/test_tune.py
+++ b/sktime/forecasting/model_selection/tests/test_tune.py
@@ -325,7 +325,7 @@ def test_skoptcv_multiple_forecaster():
     assert len(sscv.cv_results_) == 5
 
 
-BACKEND_TEST = _get_parallel_test_fixtures()
+BACKEND_TEST = _get_parallel_test_fixtures("estimator")
 
 
 @pytest.mark.skipif(
diff --git a/sktime/performance_metrics/forecasting/tests/test_metrics.py b/sktime/performance_metrics/forecasting/tests/test_metrics.py
index 1b2d07c4f..12f9709bf 100644
--- a/sktime/performance_metrics/forecasting/tests/test_metrics.py
+++ b/sktime/performance_metrics/forecasting/tests/test_metrics.py
@@ -129,3 +129,18 @@ def test_make_scorer():
     scorer = make_forecasting_scorer(rmsle, name="RMSLE")
 
     scorer.evaluate(pd.Series([1, 2, 3]), pd.Series([1, 2, 4]))
+
+
+def test_make_scorer_sklearn():
+    """Test make_forecasting_scorer and the failure case in #5715.
+
+    Naive adaptation fails on newer sklearn versions due to
+    decoration with sklearn's custom input constraint wrapper.
+    """
+    from sklearn.metrics import mean_absolute_error
+
+    from sktime.performance_metrics.forecasting import make_forecasting_scorer
+
+    scorer = make_forecasting_scorer(mean_absolute_error, name="RMSLE")
+
+    scorer.evaluate(pd.Series([1, 2, 3]), pd.Series([1, 2, 4]))
diff --git a/sktime/proba/tests/test_all_distrs.py b/sktime/proba/tests/test_all_distrs.py
index ae5a3334c..0a12fc98c 100644
--- a/sktime/proba/tests/test_all_distrs.py
+++ b/sktime/proba/tests/test_all_distrs.py
@@ -1,7 +1,7 @@
 # copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
 """Tests for BaseDistribution API points."""
 
-__author__ = ["fkiraly"]
+__author__ = ["fkiraly", "Alex-JG3"]
 
 import numpy as np
 import pandas as pd
@@ -9,6 +9,7 @@ import pytest
 
 from sktime.datatypes import check_is_mtype
 from sktime.tests.test_all_estimators import BaseFixtureGenerator, QuickTester
+from sktime.utils.index import random_ss_ix
 
 
 class DistributionFixtureGenerator(BaseFixtureGenerator):
@@ -54,12 +55,16 @@ METHODS_ROWWISE = ["energy"]  # results in one column
 
 
 class TestAllDistributions(DistributionFixtureGenerator, QuickTester):
-    """Module level tests for all sktime parameter fitters."""
+    """Module level tests for all sktime distributions."""
 
-    def test_sample(self, estimator_instance):
+    @pytest.mark.parametrize("shuffled", [False, True])
+    def test_sample(self, estimator_instance, shuffled):
         """Test sample expected return."""
         d = estimator_instance
 
+        if shuffled:
+            d = _shuffle_distr(d)
+
         res = d.sample()
 
         assert d.shape == res.shape
@@ -72,36 +77,50 @@ class TestAllDistributions(DistributionFixtureGenerator, QuickTester):
         assert (res_panel.index == dummy_panel.index).all()
         assert (res_panel.columns == dummy_panel.columns).all()
 
+    @pytest.mark.parametrize("shuffled", [False, True])
     @pytest.mark.parametrize("method", METHODS_SCALAR, ids=METHODS_SCALAR)
-    def test_methods_scalar(self, estimator_instance, method):
+    def test_methods_scalar(self, estimator_instance, method, shuffled):
         """Test expected return of scalar methods."""
         if not _has_capability(estimator_instance, method):
             return None
 
         d = estimator_instance
-        res = getattr(estimator_instance, method)()
+        if shuffled:
+            d = _shuffle_distr(d)
+
+        res = getattr(d, method)()
 
         _check_output_format(res, d, method)
 
+    @pytest.mark.parametrize("shuffled", [False, True])
     @pytest.mark.parametrize("method", METHODS_X, ids=METHODS_X)
-    def test_methods_x(self, estimator_instance, method):
+    def test_methods_x(self, estimator_instance, method, shuffled):
         """Test expected return of methods that take sample-like argument."""
         if not _has_capability(estimator_instance, method):
             return None
 
         d = estimator_instance
+
+        if shuffled:
+            d = _shuffle_distr(d)
+
         x = d.sample()
-        res = getattr(estimator_instance, method)(x)
+        res = getattr(d, method)(x)
 
         _check_output_format(res, d, method)
 
+    @pytest.mark.parametrize("shuffled", [False, True])
     @pytest.mark.parametrize("method", METHODS_P, ids=METHODS_P)
-    def test_methods_p(self, estimator_instance, method):
+    def test_methods_p(self, estimator_instance, method, shuffled):
         """Test expected return of methods that take percentage-like argument."""
         if not _has_capability(estimator_instance, method):
             return None
 
         d = estimator_instance
+
+        if shuffled:
+            d = _shuffle_distr(d)
+
         np_unif = np.random.uniform(size=d.shape)
         p = pd.DataFrame(np_unif, index=d.index, columns=d.columns)
         res = getattr(estimator_instance, method)(p)
@@ -130,6 +149,63 @@ class TestAllDistributions(DistributionFixtureGenerator, QuickTester):
         res = d.quantile(q)
         _check_quantile_output(res, q)
 
+    @pytest.mark.parametrize("subset_row", [True, False])
+    @pytest.mark.parametrize("subset_col", [True, False])
+    def test_subsetting(self, estimator_instance, subset_row, subset_col):
+        """Test subsetting of distribution."""
+        d = estimator_instance
+
+        if subset_row:
+            ix_loc = random_ss_ix(d.index, 3)
+            ix_iloc = d.index.get_indexer(ix_loc)
+        else:
+            ix_loc = d.index
+            ix_iloc = pd.RangeIndex(len(d.index))
+
+        if subset_col:
+            iy_loc = random_ss_ix(d.columns, 1)
+            iy_iloc = d.columns.get_indexer(iy_loc)
+        else:
+            iy_loc = d.columns
+            iy_iloc = pd.RangeIndex(len(d.columns))
+
+        res_loc = d.loc[ix_loc, iy_loc]
+
+        assert isinstance(res_loc, type(d))
+        assert res_loc.shape == (len(ix_loc), len(iy_loc))
+        assert (res_loc.index == ix_loc).all()
+        assert (res_loc.columns == iy_loc).all()
+
+        res_iloc = d.iloc[ix_iloc, iy_iloc]
+
+        assert isinstance(res_iloc, type(d))
+        assert res_iloc.shape == (len(ix_iloc), len(iy_iloc))
+        assert (res_iloc.index == ix_loc).all()
+        assert (res_iloc.columns == iy_loc).all()
+
+    def test_log_pdf_and_pdf(self, estimator_instance):
+        """Test that the log of the pdf and log_pdf function are similar."""
+        d = estimator_instance
+        capabilities_exact = d.get_tags()["capabilities:exact"]
+
+        if "log_pdf" not in capabilities_exact or "pdf" not in capabilities_exact:
+            return
+        x = d.sample()
+        pdf = d.pdf(x)
+        log_pdf = d.log_pdf(x)
+        assert np.allclose(np.log(pdf), log_pdf)
+
+    def test_ppf_and_cdf(self, estimator_instance):
+        """Test that the ppf is the inverse of the cdf."""
+        d = estimator_instance
+        capabilities_exact = d.get_tags()["capabilities:exact"]
+
+        if "ppf" not in capabilities_exact or "cdf" not in capabilities_exact:
+            return
+        x = d.sample()
+        x_approx = d.ppf(d.cdf(x))
+        assert np.allclose(x.values, x_approx.values)
+
 
 def _check_output_format(res, dist, method):
     """Check output format expectations for BaseDistribution tests."""
@@ -144,3 +220,16 @@ def _check_output_format(res, dist, method):
 
     if method in METHODS_SCALAR_POS or method in METHODS_X_POS:
         assert (res >= 0).all().all()
+
+    if isinstance(res, pd.DataFrame):
+        assert res.apply(pd.api.types.is_numeric_dtype).all()
+    elif isinstance(res, pd.Series):
+        assert pd.api.types.is_numeric_dtype(res)
+    else:
+        raise TypeError("res must be a pandas DataFrame or Series.")
+
+
+def _shuffle_distr(d):
+    """Shuffle distribution row index."""
+    shuffled_index = pd.DataFrame(d.index).sample(frac=1).index
+    return d.loc[shuffled_index]
diff --git a/sktime/transformations/tests/test_base.py b/sktime/transformations/tests/test_base.py
index b18b1e918..be3b7f85b 100644
--- a/sktime/transformations/tests/test_base.py
+++ b/sktime/transformations/tests/test_base.py
@@ -35,15 +35,14 @@ from sktime.utils._testing.scenarios_transformers import (
     TransformerFitTransformSeriesUnivariate,
 )
 from sktime.utils._testing.series import _make_series
+from sktime.utils.parallel import _get_parallel_test_fixtures
 from sktime.utils.validation._dependencies import _check_soft_dependencies
 
 # other scenarios that might be needed later in development:
 # TransformerFitTransformPanelUnivariateWithClassY,
 
 # list of parallelization backends to test
-BACKENDS = [None, "multiprocessing", "loky", "threading"]
-if _check_soft_dependencies("dask", severity="none"):
-    BACKENDS.append("dask")
+BACKENDS = _get_parallel_test_fixtures("config")
 
 
 def inner_X_scitypes(est):
@@ -204,7 +203,7 @@ def test_panel_in_panel_out_not_supported_but_series(backend):
     # one example for a transformer which supports Series internally but not Panel
     cls = BoxCoxTransformer
     est = cls.create_test_instance()
-    est.set_config(**{"backend:parallel": backend})
+    est.set_config(**backend.copy())
     # ensure cls is a good example, if this fails, choose another example
     #   (if this changes, it may be due to implementing more scitypes)
     #   (then this is not a failure of cls, but we need to choose another example)
@@ -274,7 +273,7 @@ def test_panel_in_primitives_out_not_supported_fit_in_transform(backend):
     # one example for a transformer which supports Series internally but not Panel
     cls = SummaryTransformer
     est = cls.create_test_instance()
-    est.set_config(**{"backend:parallel": backend})
+    est.set_config(**backend.copy())
     # ensure cls is a good example, if this fails, choose another example
     #   (if this changes, it may be due to implementing more scitypes)
     #   (then this is not a failure of cls, but we need to choose another example)
@@ -391,7 +390,7 @@ def test_hierarchical_in_hierarchical_out_not_supported_but_series(backend):
     # one example for a transformer which supports Series internally
     cls = BoxCoxTransformer
     est = cls.create_test_instance()
-    est.set_config(**{"backend:parallel": backend})
+    est.set_config(**backend.copy())
     # ensure cls is a good example, if this fails, choose another example
     #   (if this changes, it may be due to implementing more scitypes)
     #   (then this is not a failure of cls, but we need to choose another example)
@@ -468,7 +467,7 @@ def test_vectorization_multivariate_no_row_vectorization(backend):
     # one example for a transformer which supports Series internally
     cls = BoxCoxTransformer
     est = cls.create_test_instance()
-    est.set_config(**{"backend:parallel": backend})
+    est.set_config(**backend.copy())
     # ensure cls is a good example, if this fails, choose another example
     #   (if this changes, it may be due to implementing multivariate functionality)
     #   (then this is not a failure of cls, but we need to choose another example)
@@ -509,7 +508,7 @@ def test_vectorization_multivariate_and_hierarchical(backend):
     # one example for a transformer which supports Series internally
     cls = BoxCoxTransformer
     est = cls.create_test_instance()
-    est.set_config(**{"backend:parallel": backend})
+    est.set_config(**backend.copy())
     # ensure cls is a good example, if this fails, choose another example
     #   (if this changes, it may be due to implementing more scitypes)
     #   (then this is not a failure of cls, but we need to choose another example)
@@ -552,7 +551,7 @@ def test_vectorization_multivariate_no_row_vectorization_empty_fit(backend):
     # one example for a transformer which supports Series internally
     cls = BoxCoxTransformer
     est = FitInTransform(cls.create_test_instance())
-    est.set_config(**{"backend:parallel": backend})
+    est.set_config(**backend.copy())
     # ensure cls is a good example, if this fails, choose another example
     #   (if this changes, it may be due to implementing multivariate functionality)
     #   (then this is not a failure of cls, but we need to choose another example)
@@ -593,7 +592,7 @@ def test_vectorization_multivariate_and_hierarchical_empty_fit(backend):
     # one example for a transformer which supports Series internally
     cls = BoxCoxTransformer
     est = FitInTransform(cls.create_test_instance())
-    est.set_config(**{"backend:parallel": backend})
+    est.set_config(**backend.copy())
     # ensure cls is a good example, if this fails, choose another example
     #   (if this changes, it may be due to implementing more scitypes)
     #   (then this is not a failure of cls, but we need to choose another example)
diff --git a/sktime/utils/_testing/deep_equals.py b/sktime/utils/_testing/deep_equals.py
index 0616cc81a..c114c5d19 100644
--- a/sktime/utils/_testing/deep_equals.py
+++ b/sktime/utils/_testing/deep_equals.py
@@ -180,7 +180,10 @@ def deep_equals(x, y, return_msg=False):
     elif isinstance(x, np.ndarray):
         if x.dtype != y.dtype:
             return ret(False, f".dtype, x.dtype = {x.dtype} != y.dtype = {y.dtype}")
-        return ret(np.array_equal(x, y, equal_nan=True), ".values")
+        if x.dtype in ["object", "str"]:
+            return ret(np.array_equal(x, y), ".values")
+        else:
+            return ret(np.array_equal(x, y, equal_nan=True), ".values")
     # recursion through lists, tuples and dicts
     elif isinstance(x, (list, tuple)):
         return ret(*_tuple_equals(x, y, return_msg=True))
diff --git a/sktime/utils/_testing/tests/test_deep_equals.py b/sktime/utils/_testing/tests/test_deep_equals.py
index 9d16330eb..16be1e9c2 100644
--- a/sktime/utils/_testing/tests/test_deep_equals.py
+++ b/sktime/utils/_testing/tests/test_deep_equals.py
@@ -26,6 +26,10 @@ EXAMPLES = [
     ForecastingHorizon([1, 2, 3], is_relative=False),
     {"foo": [42], "bar": pd.Series([1, 2])},
     {"bar": [42], "foo": pd.Series([1, 2])},
+    pd.Index([1, 2, 3]),
+    pd.Index([2, 3, 4]),
+    np.array([0.1, 1], dtype="object"),
+    np.array([0.2, 1], dtype="object"),
 ]