Skip to content

Commit a73a547

Browse files
authored
Merge pull request #1198 from mindsdb/staging
Release candidate
2 parents 9717e9e + be24227 commit a73a547

17 files changed

+282
-82
lines changed

.github/workflows/add_to_bugs_project.yml

-19
This file was deleted.
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: Add Pull Requests to PR review project
2+
3+
on:
4+
pull_request:
5+
types:
6+
- opened
7+
8+
jobs:
9+
add-to-project:
10+
name: Add issue to project
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/add-to-project@v0.5.0
14+
with:
15+
project-url: https://github.com/orgs/mindsdb/projects/65
16+
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
name: Add issue to roadmap project
2-
32
on:
43
issues:
54
types:
65
- opened
7-
86
jobs:
97
add-to-project:
108
name: Add issue to roadmap project
119
runs-on: ubuntu-latest
1210
steps:
1311
- uses: actions/add-to-project@v0.4.0
1412
with:
15-
# You can target a repository in a different organization
16-
# to the issue
17-
project-url: https://github.com/orgs/mindsdb/projects/54
13+
project-url: https://github.com/orgs/mindsdb/projects/53
1814
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
19-
labeled: enhancement
15+
labeled: bug, enhancement
16+
label-operator: OR

.github/workflows/doc_build.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
run: |
2525
sudo apt install pandoc
2626
python -m pip install --upgrade pip
27-
pip install install 'Sphinx==4.1.2' 'sphinx-autoapi==1.8.4' 'sphinx-autodoc-typehints==1.12.0' 'sphinx-code-include==1.1.1' 'sphinx-rtd-theme==0.5.2' 'sphinxcontrib-applehelp==1.0.2' 'sphinxcontrib-devhelp==1.0.2' 'sphinxcontrib-htmlhelp==2.0.0' 'sphinxcontrib-jsmath==1.0.1' 'sphinxcontrib-napoleon==0.7' 'sphinxcontrib-qthelp==1.0.3' 'sphinxcontrib-serializinghtml==1.1.5' autoapi nbsphinx myst_parser pandoc jupyter matplotlib imblearn fsspec
27+
pip install install 'Sphinx==6.2.1' 'sphinx-autoapi==3.0.0' 'sphinx-autodoc-typehints' 'sphinx-code-include' 'sphinx-rtd-theme' 'sphinxcontrib-applehelp' 'sphinxcontrib-devhelp' 'sphinxcontrib-htmlhelp' 'sphinxcontrib-jsmath' 'sphinxcontrib-napoleon' 'sphinxcontrib-qthelp' 'sphinxcontrib-serializinghtml' autoapi nbsphinx myst_parser pandoc jupyter matplotlib imblearn fsspec
2828
pip install --no-cache-dir -e .
2929
- name: Re-run notebooks
3030
run: |

docssrc/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ github:
2626
@cp -a build/html/. ../docs
2727
@rm -r build
2828
@touch ../docs/.nojekyll
29-
@echo lightwood.io > ../docs/CNAME
29+
@echo https://mindsdb.github.io/lightwood > ../docs/CNAME

lightwood/__about__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
__title__ = 'lightwood'
22
__package_name__ = 'lightwood'
3-
__version__ = '23.8.1.0'
3+
__version__ = '23.11.1.0'
44
__description__ = "Lightwood is a toolkit for automatic machine learning model building"
55
__email__ = "community@mindsdb.com"
66
__author__ = 'MindsDB Inc'

lightwood/api/json_ai.py

+13-29
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ def generate_json_ai(
203203
]
204204
)
205205
else:
206+
207+
# add neural model
206208
if not tss.is_timeseries:
207209
submodels.extend(
208210
[
@@ -226,10 +228,11 @@ def generate_json_ai(
226228
"stop_after": "$problem_definition.seconds_per_mixer",
227229
"search_hyperparameters": True,
228230
},
229-
}
231+
},
230232
]
231233
)
232234

235+
# add other models
233236
if (not tss.is_timeseries or tss.horizon == 1) and dtype_dict[target] not in (dtype.num_array, dtype.cat_array):
234237
submodels.extend(
235238
[
@@ -255,34 +258,15 @@ def generate_json_ai(
255258
},
256259
]
257260
)
258-
elif tss.is_timeseries and tss.horizon > 1 and tss.use_previous_target and \
259-
dtype_dict[target] in (dtype.integer, dtype.float, dtype.quantity):
260261

261-
submodels.extend(
262-
[
263-
{
264-
"module": "SkTime",
265-
"args": {
266-
"stop_after": "$problem_definition.seconds_per_mixer",
267-
"horizon": "$problem_definition.timeseries_settings.horizon",
268-
},
269-
},
270-
{
271-
"module": "ETSMixer",
272-
"args": {
273-
"stop_after": "$problem_definition.seconds_per_mixer",
274-
"horizon": "$problem_definition.timeseries_settings.horizon",
275-
},
276-
},
277-
{
278-
"module": "ARIMAMixer",
279-
"args": {
280-
"stop_after": "$problem_definition.seconds_per_mixer",
281-
"horizon": "$problem_definition.timeseries_settings.horizon",
282-
},
283-
}
284-
]
285-
)
262+
# special forecasting dispatch
263+
elif tss.is_timeseries:
264+
submodels.extend([
265+
{
266+
"module": "XGBoostArrayMixer",
267+
"args": {},
268+
},
269+
])
286270

287271
model = {
288272
"module": "BestOf",
@@ -571,7 +555,7 @@ def add_implicit_values(json_ai: JsonAI) -> JsonAI:
571555
"target_encoder", "$encoders[self.target]"
572556
)
573557

574-
elif mixers[i]["module"] == "LightGBMArray":
558+
elif mixers[i]["module"] in ("LightGBMArray", "XGBoostArrayMixer"):
575559
mixers[i]["args"]["input_cols"] = mixers[i]["args"].get(
576560
"input_cols", "$input_cols"
577561
)

lightwood/api/types.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ class JsonAI:
313313
analysis_blocks: Optional[List[Module]] = None
314314
timeseries_transformer: Optional[Module] = None
315315
timeseries_analyzer: Optional[Module] = None
316-
accuracy_functions: Optional[List[str]] = None
316+
accuracy_functions: Optional[List[Union[str, Module]]] = None
317317

318318
@staticmethod
319319
def from_dict(obj: Dict):

lightwood/helpers/device.py

+55-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,24 @@
55

66

77
def is_cuda_compatible():
8+
"""
9+
Check if the system has CUDA-compatible devices with the required architecture and
10+
compiled CUDA version.
11+
12+
This function checks the compatibility of CUDA devices available on the system by
13+
comparing their architectures and the compiled CUDA version. It iterates through
14+
the available devices and verifies if their architectures meet the minimum
15+
requirement specified by the function, and also checks if the compiled CUDA
16+
version is greater than a specific version.
17+
18+
Returns:
19+
bool: True if there are compatible CUDA devices, otherwise False.
20+
21+
Example:
22+
>>> is_compatible = is_cuda_compatible()
23+
>>> print(is_compatible)
24+
True
25+
"""
826
compatible_device_count = 0
927
if torch.version.cuda is not None:
1028
for d in range(device_count()):
@@ -23,6 +41,27 @@ def is_cuda_compatible():
2341

2442

2543
def get_devices():
44+
"""
45+
Get the appropriate Torch device(s) based on CUDA availability and compatibility.
46+
47+
This function determines the appropriate Torch device(s) to be used for
48+
computations based on the availability of CUDA and compatible devices. It checks
49+
if CUDA is available and if the available CUDA devices are compatible according to
50+
the 'is_cuda_compatible()' function. If compatible devices are found, the function
51+
selects either the first available CUDA device or a randomly selected one based on
52+
the 'RANDOM_GPU' environment variable. If CUDA is not available or no compatible
53+
devices are found, the function returns the CPU device.
54+
55+
Returns:
56+
Tuple: A tuple containing the selected Torch device and the number of available
57+
devices.
58+
Example:
59+
>>> device, num_devices = get_devices()
60+
>>> print(device)
61+
cuda:0
62+
>>> print(num_devices)
63+
1
64+
"""
2665
if torch.cuda.is_available() and is_cuda_compatible():
2766
device_str = "cuda"
2867
available_devices = torch.cuda.device_count()
@@ -40,10 +79,22 @@ def get_devices():
4079

4180
def get_device_from_name(device_name=''):
4281
"""
43-
Returns the device specified as an argument.
44-
If the argument is left empty it will returns the output of get_devices().
45-
46-
:param device_name: name of the device to use (default is an empty string), if is an empty string will use the output of get_devices() instead")
82+
Get a Torch device based on the specified device name or default behavior.
83+
84+
This function returns a Torch device based on the specified device name or the
85+
default behavior, which is to return the output of the 'get_devices()' function.
86+
87+
Args:
88+
device_name (str, optional): Name of the device to use. Default is an empty
89+
string.
90+
91+
Returns:
92+
torch.device: The selected Torch device.
93+
94+
Example:
95+
>>> device = get_device_from_name('cuda:1')
96+
>>> print(device)
97+
cuda:1
4798
""" # noqa E501
4899
if(device_name != ''):
49100
device = torch.device(device_name)

lightwood/helpers/torch.py

+54
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,32 @@
55

66

77
def concat_vectors_and_pad(vec_list, max_):
8+
"""
9+
Concatenates a list of input vectors and pads them to match a specified maximum
10+
length.
11+
12+
This function takes a list of input vectors, concatenates them along a specified
13+
dimension (dim=0), and then pads the concatenated vector to achieve a specified
14+
maximum length. The padding is done with zeros.
15+
16+
Args:
17+
vec_list (list of torch.Tensor): List of input vectors to concatenate and pad.
18+
max_ (int): The maximum length of the concatenated and padded vector.
19+
20+
Returns:
21+
torch.Tensor: The concatenated and padded vector.
22+
23+
Raises:
24+
AssertionError: If the length of 'vec_list' is not greater than 0, or if it
25+
exceeds 'max_len', or if 'max_len' is not greater than 0.
26+
27+
Example:
28+
>>> input_tensors = [torch.tensor([1, 2]), torch.tensor([3, 4, 5])]
29+
>>> max_length = 5
30+
>>> concatenated_padded = concat_vectors_and_pad(input_tensors, max_length)
31+
>>> print(concatenated_padded)
32+
tensor([1, 2, 3, 4, 5])
33+
"""
834
assert len(vec_list) > 0
935
assert len(vec_list) <= max_
1036
assert max_ > 0
@@ -27,10 +53,29 @@ class LightwoodAutocast:
2753
"""
2854
Equivalent to torch.cuda.amp.autocast, but checks device compute capability
2955
to activate the feature only when the GPU has tensor cores to leverage AMP.
56+
57+
**Attributes:**
58+
59+
* `active` (bool): Whether AMP is currently active. This attribute is at the class
60+
level
61+
62+
**Usage:**
63+
64+
```python
65+
>>> import lightwood.helpers.torch as lt
66+
>>> with lt.LightwoodAutocast():
67+
... # This code will be executed in AMP mode.
68+
... pass
3069
"""
3170
active = False
3271

3372
def __init__(self, enabled=True):
73+
"""
74+
Initializes the context manager for Automatic Mixed Precision (AMP) functionality.
75+
76+
Args:
77+
enabled (bool, optional): Whether to enable AMP. Defaults to True.
78+
"""
3479
self.major = 0 # GPU major version
3580
torch_version = [int(i) for i in torch.__version__.split('.')[:-1]]
3681

@@ -50,12 +95,18 @@ def __init__(self, enabled=True):
5095
LightwoodAutocast.active = self._enabled
5196

5297
def __enter__(self):
98+
"""
99+
* `__enter__()`: Enters the context manager and enables AMP if it is not already enabled.
100+
"""
53101
if self._enabled:
54102
self.prev = torch.is_autocast_enabled()
55103
torch.set_autocast_enabled(self._enabled)
56104
torch.autocast_increment_nesting()
57105

58106
def __exit__(self, *args):
107+
"""
108+
* `__exit__()`: Exits the context manager and disables AMP.
109+
"""
59110
if self._enabled:
60111
# Drop the cache when we exit to a nesting level that's outside any instance of autocast
61112
if torch.autocast_decrement_nesting() == 0:
@@ -64,6 +115,9 @@ def __exit__(self, *args):
64115
return False
65116

66117
def __call__(self, func):
118+
"""
119+
* `__call__(self, func)`: Returns a decorated function that enables AMP when it is called.
120+
"""
67121
@functools.wraps(func)
68122
def decorate_autocast(*args, **kwargs):
69123
with self:

lightwood/mixer/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from lightwood.mixer.neural import Neural
44
from lightwood.mixer.neural_ts import NeuralTs
55
from lightwood.mixer.xgboost import XGBoostMixer
6+
from lightwood.mixer.xgboost_array import XGBoostArrayMixer
67
from lightwood.mixer.random_forest import RandomForest
78
from lightwood.mixer.sktime import SkTime
89
from lightwood.mixer.arima import ARIMAMixer
@@ -43,4 +44,4 @@
4344

4445
__all__ = ['BaseMixer', 'Neural', 'NeuralTs', 'LightGBM', 'RandomForest', 'LightGBMArray', 'Unit', 'Regression',
4546
'SkTime', 'QClassic', 'ProphetMixer', 'ETSMixer', 'ARIMAMixer', 'NHitsMixer', 'GluonTSMixer', 'XGBoostMixer',
46-
'TabTransformerMixer']
47+
'TabTransformerMixer', 'XGBoostArrayMixer']

0 commit comments

Comments
 (0)