Skip to content

Commit ecacd93

Browse files
hrzndennisbader
andauthored
make prophet, lightgbm and catboost optional (#1589)
* make prophet optional again, adapt install readme * adapt u8darts setup as well * remove prophet, lightgbm, catboost for core requirements * simplify the module importing * update tests with new optional dependencies * update gradle for including optional dependencies in unittest_all * update checkExamples to show all installed dependencies before test * apply suggestions from PR review * update install guide * update shap unit tests * apply suggestions from PR review * update changelog --------- Co-authored-by: dennisbader <[email protected]>
1 parent 137cf8c commit ecacd93

18 files changed

+396
-341
lines changed

CHANGELOG.md

+7-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ but cannot always guarantee backwards compatibility. Changes that may **break co
1010

1111
### For users of the library:
1212

13+
**Installation**
14+
- 🔴 Removed Prophet, LightGBM, and CatBoost dependencies from PyPI packages (`darts`, `u8darts`, `u8darts[torch]`), and conda-forge packages (`u8darts`, `u8darts-torch`) to avoid installation issues that some users were facing (installation on Apple M1/M2 devices, ...). [#1589](https://github.com/unit8co/darts/pull/1589) by [Julien Herzen](https://github.com/hrzn) and [Dennis Bader](https://github.com/dennisbader).
15+
- The models are still supported by installing the required packages as described in our [installation guide](https://github.com/unit8co/darts/blob/master/INSTALL.md#enabling-optional-dependencies).
16+
- PyPi package `u8darts[all]` and conda-forge package `u8darts-all` are now equivalent to the old `darts` package (all dependencies).
17+
- Added new PyPI flavor `u8darts[notorch]`, and conda-forge flavor `u8darts-notorch` which are equivalent to the old `u8darts` installation.
18+
- 🔴 Removed support for Python 3.7 [#1864](https://github.com/unit8co/darts/pull/#1864) by [Dennis Bader](https://github.com/dennisbader).
19+
1320
**Improved**
1421
- General model improvements:
1522
- Added support for `PathLike` to the `save()` and `load()` functions of all non-deep learning based models. [#1754](https://github.com/unit8co/darts/pull/1754) by [Simon Sudrich](https://github.com/sudrich).
@@ -42,9 +49,6 @@ but cannot always guarantee backwards compatibility. Changes that may **break co
4249
- Fixed an issue when calling `ARIMA.predict()` and `num_samples > 1` (probabilistic forecasting), where the start point of the simulation was not anchored to the end of the target series. [#1893](https://github.com/unit8co/darts/pull/1893) by [Dennis Bader](https://github.com/dennisbader).
4350
- Fixed an issue when using `TFTModel.predict()` with `full_attention=True` where the attention mask was not applied properly. [#1392](https://github.com/unit8co/darts/issues/1392) by [Dennis Bader](https://github.com/dennisbader).
4451

45-
**Removed**
46-
- Removed support for Python 3.7 [#1864](https://github.com/unit8co/darts/pull/#1864) by [Dennis Bader](https://github.com/dennisbader).
47-
4852
### For developers of the library:
4953

5054
**Improvements**

INSTALL.md

+50-68
Original file line numberDiff line numberDiff line change
@@ -2,111 +2,93 @@
22

33
Below, we detail how to install Darts using either `conda` or `pip`.
44

5+
## From PyPI
6+
Install darts with all models expect the ones from optional dependencies (Prophet, LightGBM, CatBoost, see more on that [here](#enabling-optional-dependencies)): `pip install darts`.
7+
8+
If this fails on your platform, please follow the official installation
9+
guide for [PyTorch](https://pytorch.org/get-started/locally/), then try installing Darts again.
10+
11+
As some dependencies are relatively big or involve non-Python dependencies,
12+
we also maintain the `u8darts` package, which provides the following alternate lighter install options:
13+
14+
* Install darts with all available models: `pip install u8darts[all]`
15+
* Install core only (without neural networks, Prophet, LightGBM and Catboost): `pip install u8darts`
16+
* Install core + Prophet + LightGBM + CatBoost: `pip install "u8darts[notorch]"`
17+
* Install core + neural networks (PyTorch): `pip install "u8darts[torch]"` (equivalent to `pip install darts`)
18+
519
## From conda-forge
620
Currently only the x86_64 architecture with Python 3.8-3.10
721
is fully supported with conda; consider using PyPI if you are running into troubles.
822

9-
To create a conda environment for Python 3.9
23+
Create a conda environment (e.g., for Python 3.10):
1024
(after installing [conda](https://docs.conda.io/en/latest/miniconda.html)):
1125

12-
conda create --name <env-name> python=3.9
26+
conda create --name <env-name> python=3.10
1327

14-
Don't forget to activate your virtual environment
28+
Activate the environment
1529

1630
conda activate <env-name>
1731

18-
As some models have relatively heavy dependencies, we provide two conda-forge packages:
32+
As some models have relatively heavy dependencies, we provide four conda-forge packages:
1933

20-
* Install darts with all available models (recommended): `conda install -c conda-forge -c pytorch u8darts-all`.
34+
* Install darts with all available models: `conda install -c conda-forge -c pytorch u8darts-all`
35+
* Install core only (without neural networks, Prophet, LightGBM and Catboost): `conda install -c conda-forge u8darts`
36+
* Install core + Prophet + LightGBM + CatBoost: `pip install "u8darts-notorch"`
2137
* Install core + neural networks (PyTorch): `conda install -c conda-forge -c pytorch u8darts-torch`
22-
* Install core only (without neural networks or AutoARIMA): `conda install -c conda-forge u8darts`
2338

24-
For GPU support, please follow the instructions to install CUDA in the [PyTorch installation guide](https://pytorch.org/get-started/locally/).
2539

40+
## Other Information
2641

27-
## From PyPI
28-
Install darts with all available models: `pip install darts`.
42+
### Enabling Optional Dependencies
43+
By default, as of 0.25.0, `darts` does not have Prophet, CatBoost, and LightGBM as dependencies anymore, because their
44+
build processes were too often causing issues. If you want to use any of Darts' `Prophet`, `CatBoostModel`, and
45+
`LightGBMModel`, you will need to manually install the corresponding packages.
2946

30-
If this fails on your platform, please follow the official installation
31-
guide for [PyTorch](https://pytorch.org/get-started/locally/), then try installing Darts again.
47+
#### Prophet
48+
Install the `prophet` package (version 1.1.1 or more recent) using the [Prophet install guide](https://facebook.github.io/prophet/docs/installation.html#python)
3249

33-
As some dependencies are relatively big or involve non-Python dependencies,
34-
we also maintain the `u8darts` package, which provides the following alternate lighter install options:
50+
#### CatBoostModel
51+
Install the `catboost` package (version 1.0.6 or more recent) using the [CatBoost install guide](https://catboost.ai/en/docs/concepts/python-installation)
3552

36-
* Install core only (without neural networks, Prophet or AutoARIMA): `pip install u8darts`
37-
* Install core + neural networks (PyTorch): `pip install "u8darts[torch]"`
38-
* Install core + AutoARIMA: `pip install "u8darts[pmdarima]"`
53+
#### LightGBMModel
54+
Install the `lightgbm` package (version 3.2.0 or more recent) using the [LightGBM install guide](https://lightgbm.readthedocs.io/en/latest/Installation-Guide.html)
3955

40-
### Enabling Support for LightGBM
41-
42-
To enable support for LightGBM in Darts, please follow the
43-
[installation instructions](https://lightgbm.readthedocs.io/en/latest/Installation-Guide.html) for your OS.
44-
45-
#### MacOS Issues with LightGBM
46-
At the time of writing, there is an issue with ``libomp`` 12.0.1 that results in
47-
[segmentation fault on Mac OS Big Sur](https://github.com/microsoft/LightGBM/issues/4229).
48-
Here's the procedure to downgrade the ``libomp`` library (from the
49-
[original Github issue](https://github.com/microsoft/LightGBM/issues/4229#issue-867528353)):
50-
* [Install brew](https://brew.sh/) if you don't already have it.
51-
* Install `wget` if you don't already have it : `brew install wget`.
52-
* Run the commands below:
53-
```
54-
wget https://raw.githubusercontent.com/Homebrew/homebrew-core/fb8323f2b170bd4ae97e1bac9bf3e2983af3fdb0/Formula/libomp.rb
55-
brew unlink libomp
56-
brew install libomp.rb
57-
```
56+
### Enabling GPU support
57+
Darts relies on PyTorch for the neural network models.
58+
For GPU support, please follow the instructions to install CUDA in the [PyTorch installation guide](https://pytorch.org/get-started/locally/).
5859

59-
#### Test environment Apple M1 processor
60+
### Using an emulated x64 environment on Apple Silicon.
61+
The installation of `darts` has been tested to work on Apple silicon (M1) (Python 3.10, OSX Ventura 13.2.1).
6062

61-
We currently recommend to run Darts in an x_64 emulated environment on Mac computers with the Silicon M1 processor,
62-
instead of trying to install directly with native arm64 packages, many of the dependent packages still have compatibility
63-
issues. The following is a proposed procedure, if you tested other procedures on similar hardware and they worked,
64-
please let us know about them by opening an issue or by updating this file and opening a PR.
63+
If you run into issues, you can always use rosetta to run in an (intel) emulated x64 environment:
6564

6665
Before you start make sure that you have rosetta2 installed by running:
67-
```
66+
67+
```bash
6868
pgrep oahd
6969
```
70-
If you see some process id you are ready to go, as internally rosetta is known as oah.
70+
71+
If you see a process id you are ready to go, as internally rosetta is known as oah.
7172

7273
If pgrep doesn't return any id then install rosetta2:
73-
```
74+
75+
```bash
7476
softwareupdate --install-rosetta
7577
```
7678

7779
Below are the necessary instructions to create and configure the environment:
78-
- Start by installing conda (e.g., with miniforge : `brew install miniforge`).
79-
- Create the x_64 environment : `CONDA_SUBDIR=osx-64 conda create -n env_name python=3.9 pip`
80-
- Activate the created environment: `conda activate env_name`
80+
- Install conda if you haven't done so (e.g., with miniforge : `brew install miniforge`).
81+
- Create the x_64 environment : `CONDA_SUBDIR=osx-64 conda create -n env_name python=3.10 pip`
82+
- Activate the environment: `conda activate env_name`
8183
- Configure the environment : `conda env config vars set CONDA_SUBDIR=osx-64`
8284
- Deactivate and reactivate the environment:
83-
```
85+
```bash
8486
conda deactivate
8587
conda activate env_name
8688
```
8789
- Install darts: `pip install darts`
88-
- With this method of installation, lightgbm might still have issues finding the libomp library.
89-
The following procedure is to guarantee that the correct libomp (11.1.0) library is linked.
90-
- Unlink the existing libomp, from terminal : `brew unlink libomp`
91-
- Setup a homebrew installer that is compatible with x_64 packages (follow this [blog](https://medium.com/mkdir-awesome/how-to-install-x86-64-homebrew-packages-on-apple-m1-macbook-54ba295230f)
92-
post):
93-
```
94-
cd ~/Downloads
95-
mkdir homebrew
96-
curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew
97-
sudo mv homebrew /usr/local/homebrew
98-
export PATH=$HOME/bin:/usr/local/bin:$PATH
99-
```
100-
- At this point, we have a new brew command located at /usr/local/homebrew/bin/brew
101-
- In the following code bits we download version 11.1.0 of libomp, install it as a x_64 compatible package and link to it so that lightgbm can find it:
102-
```
103-
wget https://raw.githubusercontent.com/Homebrew/homebrew-core/fb8323f2b170bd4ae97e1bac9bf3e2983af3fdb0/Formula/libomp.rb
104-
arch -x86_64 /usr/local/homebrew/bin/brew install libomp.rb
105-
sudo ln -s /usr/local/homebrew/Cellar/libomp/11.1.0/lib /usr/local/opt/libomp/lib
106-
```
107-
- Verify that your lightgbm works by importing lightgbm from your python env. It should not give library loading errors.
108-
109-
## Running the examples only, without installing:
90+
91+
### Running the examples only, without installing:
11092

11193
If the conda setup is causing too many problems, we also provide a Docker image with everything set up for you and ready-to-use Python notebooks with demo examples.
11294
To run the example notebooks without installing our libraries natively on your machine, you can use our Docker image:

build.gradle

+11-3
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ task installPipLatest {
6464
commandLine "pip", "install", "pip-tools"
6565
}
6666
exec {
67-
commandLine "pip-compile", "-o", "requirements-latest.txt"
67+
commandLine "pip-compile", "requirements/core.txt", "requirements/notorch.txt", "requirements/torch.txt", "-o", "requirements-latest.txt"
6868
}
6969
exec {
7070
commandLine "pip", "install", "-r", "requirements-latest.txt"
@@ -80,7 +80,7 @@ void createPipInstallTask(String flavour) {
8080
}
8181
}
8282

83-
String[] flavours = ["core", "dev", "torch", "release"];
83+
String[] flavours = ["core", "dev", "notorch", "torch", "release"];
8484

8585
for(String flavour : flavours) {
8686
createPipInstallTask(flavour);
@@ -94,7 +94,7 @@ task pipInstall() {
9494
doFirst {
9595
setupPip
9696
}
97-
dependsOn pip_core, pip_dev, pip_torch, pip_release
97+
dependsOn pip_core, pip_dev, pip_notorch, pip_torch, pip_release
9898
}
9999

100100
task lint_black(type: Exec) {
@@ -158,6 +158,14 @@ def exampleName=project.properties["exampleName"] ?: ""
158158
task checkExample(type: Exec) {
159159
dependsOn pipInstall, installLocally
160160
workingDir "./examples"
161+
doFirst {
162+
exec {
163+
commandLine "echo", "Installed packages"
164+
}
165+
exec {
166+
commandLine "pip", "list"
167+
}
168+
}
161169
// exampleName must be passed with -PexampleName=FFT-examples.ipynb
162170
commandLine "papermill", exampleName, exampleName
163171
}

darts/models/__init__.py

+11-59
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from darts.models.forecasting.tbats_model import BATS, TBATS
2727
from darts.models.forecasting.theta import FourTheta, Theta
2828
from darts.models.forecasting.varima import VARIMA
29+
from darts.models.utils import NotImportedModule
2930

3031
try:
3132
from darts.models.forecasting.block_rnn_model import BlockRNNModel
@@ -50,48 +51,17 @@
5051
try:
5152
from darts.models.forecasting.lgbm import LightGBMModel
5253
except ModuleNotFoundError:
53-
logger.warning(
54-
"Support for LightGBM not available. "
55-
"To enable LightGBM support in Darts, follow the detailed "
56-
"install instructions for LightGBM in the README: "
57-
"https://github.com/unit8co/darts/blob/master/INSTALL.md"
58-
)
59-
# TODO: simpler option would be to write LightGBMModel=None
60-
# Prevent a second ImportError that would interrupt the import
61-
class NotImportedLightGBM:
62-
usable = False
63-
64-
LightGBMModel = NotImportedLightGBM()
54+
LightGBMModel = NotImportedModule(module_name="LightGBM")
6555

6656
try:
6757
from darts.models.forecasting.prophet_model import Prophet
6858
except ImportError:
69-
logger.warning(
70-
"The prophet module could not be imported. "
71-
"To enable support for Prophet model, follow "
72-
"the instruction in the README: "
73-
"https://github.com/unit8co/darts/blob/master/INSTALL.md"
74-
)
75-
76-
class NotImportedProphet:
77-
usable = False
78-
79-
Prophet = NotImportedProphet()
59+
Prophet = NotImportedModule(module_name="Prophet")
8060

8161
try:
8262
from darts.models.forecasting.catboost_model import CatBoostModel
8363
except ModuleNotFoundError:
84-
logger.warning(
85-
"The catboost module could not be imported. "
86-
"To enable support for CatBoostModel model, "
87-
"follow the instruction in the README: "
88-
"https://github.com/unit8co/darts/blob/master/INSTALL.md"
89-
)
90-
91-
class NotImportedCatBoostModel:
92-
usable = False
93-
94-
CatBoostModel = NotImportedCatBoostModel()
64+
CatBoostModel = NotImportedModule(module_name="CatBoost")
9565

9666
try:
9767
from darts.models.forecasting.croston import Croston
@@ -102,39 +72,21 @@ class NotImportedCatBoostModel:
10272

10373
except ImportError:
10474
logger.warning(
105-
"The statsforecast module could not be imported. "
75+
"The StatsForecast module could not be imported. "
10676
"To enable support for the StatsForecastAutoARIMA, "
10777
"StatsForecastAutoETS and Croston models, please consider "
10878
"installing it."
10979
)
110-
111-
class NotImportedStatsForecastAutoARIMA:
112-
usable = False
113-
114-
StatsForecastAutoARIMA = NotImportedStatsForecastAutoARIMA()
115-
116-
class NotImportedStatsForecastAutoETS:
117-
usable = False
118-
119-
StatsForecastAutoETS = NotImportedStatsForecastAutoETS()
120-
121-
class NotImportedCroston:
122-
usable = False
123-
124-
Croston = NotImportedCroston()
80+
Croston = NotImportedModule(module_name="StatsForecast", warn=False)
81+
StatsForecastAutoARIMA = NotImportedModule(module_name="StatsForecast", warn=False)
82+
StatsForecastAutoCES = NotImportedModule(module_name="StatsForecast", warn=False)
83+
StatsForecastAutoETS = NotImportedModule(module_name="StatsForecast", warn=False)
84+
StatsForecastAutoTheta = NotImportedModule(module_name="StatsForecast", warn=False)
12585

12686
try:
12787
from darts.models.forecasting.xgboost import XGBModel
12888
except ImportError:
129-
logger.warning(
130-
"The xgboost module could not be imported. "
131-
"To enable support for XGBoost model, install the xgboost package."
132-
)
133-
134-
class NotImportedXGBModel:
135-
usable = False
136-
137-
XGBModel = NotImportedXGBModel()
89+
XGBModel = NotImportedModule(module_name="XGBoost")
13890

13991
from darts.models.filtering.gaussian_process_filter import GaussianProcessFilter
14092
from darts.models.filtering.kalman_filter import KalmanFilter

darts/models/forecasting/regression_model.py

+1-11
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,6 @@
5555

5656
logger = get_logger(__name__)
5757

58-
try:
59-
from catboost import CatBoostRegressor
60-
except ModuleNotFoundError:
61-
logger.warning(
62-
"The catboost module could not be imported. "
63-
"To enable support for CatBoostRegressor, "
64-
"follow the instruction in the README: "
65-
"https://github.com/unit8co/darts/blob/master/INSTALL.md"
66-
)
67-
6858

6959
class RegressionModel(GlobalForecastingModel):
7060
def __init__(
@@ -533,7 +523,7 @@ def fit(
533523
self.model = MultiOutputRegressor(
534524
self.model, n_jobs=n_jobs_multioutput_wrapper
535525
)
536-
elif isinstance(self.model, CatBoostRegressor):
526+
elif self.model.__class__.__name__ == "CatBoostRegressor":
537527
if (
538528
self.model.get_params()["loss_function"]
539529
== "RMSEWithUncertainty"

darts/models/utils.py

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from darts.logging import get_logger, raise_log
2+
3+
logger = get_logger(__name__)
4+
5+
6+
class NotImportedModule:
7+
"""Helper class for handling import errors of optional dependencies."""
8+
9+
usable = False
10+
11+
def __init__(self, module_name: str, warn: bool = True):
12+
self.error_message = (
13+
f"The `{module_name}` module could not be imported. "
14+
f"To enable {module_name} support in Darts, follow the detailed "
15+
f"instructions in the installation guide: "
16+
f"https://github.com/unit8co/darts/blob/master/INSTALL.md"
17+
)
18+
if warn:
19+
logger.warning(self.error_message)
20+
21+
def __call__(self, *args, **kwargs):
22+
raise_log(ImportError(self.error_message), logger=logger)

0 commit comments

Comments
 (0)