Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions chainladder/core/tests/test_triangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,7 @@ def test_printer(raa):
def test_value_order(clrd):
a = clrd[["CumPaidLoss", "BulkLoss"]]
b = clrd[["BulkLoss", "CumPaidLoss"]]
xp = a.get_array_module()
xp.testing.assert_array_equal(a.values[:, -1], b.values[:, 0])
assert a.iloc[:, -1] == b.iloc[:, 0]


def test_trend(raa, atol):
Expand Down Expand Up @@ -436,7 +435,7 @@ def test_groupby_agg_auto_sparse(prism: Triangle) -> None:
assert result_default == result_no_sparse


def test_auto_sparse_disabled_returns_self(prism: Triangle) -> None:
def test_auto_sparse_disabled_returns_self(prism_convert: Triangle) -> None:
"""
When cl.options.AUTO_SPARSE is False, _auto_sparse() returns the triangle
unchanged without switching backends.
Expand All @@ -450,7 +449,7 @@ def test_auto_sparse_disabled_returns_self(prism: Triangle) -> None:
-------
None
"""
dense = prism.set_backend("numpy")
dense = prism_convert.set_backend("numpy")
cl.options.set_option("AUTO_SPARSE", False)
try:
result = dense._auto_sparse()
Expand Down
9 changes: 6 additions & 3 deletions chainladder/development/learning.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,14 @@ def _prep_X_ml(self, X):
return df

def _prep_w_ml(self,X,sample_weight=None):
weight_base = (~np.isnan(X.values)).astype(float)
#scikit-learn requires a dense sample_weight
backend = "cupy" if X.array_backend == "cupy" else "numpy"
obj = X.set_backend(backend)
weight_base = (~np.isnan(obj.values)).astype(float)
weight = weight_base.copy()
weight = weight * TriangleWeight(drop=self.drop,drop_valuation=self.drop_valuation).fit(X).w_.fillzero().values
weight = weight * TriangleWeight(drop=self.drop,drop_valuation=self.drop_valuation).fit(obj).w_.fillzero().values
if sample_weight is not None:
weight = weight * sample_weight.values
weight = weight * sample_weight.set_backend(backend).values
return weight.flatten()[weight_base.flatten()>0]

def fit(self, X, y=None, sample_weight=None):
Expand Down
19 changes: 11 additions & 8 deletions chainladder/development/tests/test_development.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,23 @@ def __init__(self,dev):

def fit(self, X, y: None = None, sample_weight: None = None):
if hasattr(X,'age_to_age'):
super().fit(X.incr_to_cum().age_to_age)
xp = X.get_array_module()
indices = X.values.shape[0]
columns = X.values.shape[1]
origins = X.age_to_age.values.shape[2]
reg_x = X.incr_to_cum().values[...,:origins,:-1]
reg_y = X.incr_to_cum().values[...,:origins,1:]
#following precedent _set_fit_groups() from DevelopmentBase
backend = "numpy" if X.array_backend in ["sparse", "numpy"] else "cupy"
obj = X.set_backend(backend)
super().fit(obj.incr_to_cum().age_to_age)
xp = obj.get_array_module()
indices = obj.values.shape[0]
columns = obj.values.shape[1]
origins = obj.age_to_age.values.shape[2]
reg_x = obj.incr_to_cum().values[...,:origins,:-1]
reg_y = obj.incr_to_cum().values[...,:origins,1:]
dev_len = reg_x.shape[3]
average_param = self._cascade_param(dev_len, self.average, "volume")
average_param = np.tile(average_param,(indices,columns,1,1))
params = cl.WeightedRegression(axis=2, thru_orig=True, xp=xp).fit(
reg_x, reg_y, self.w_.values, average_param
)
self.ldf_ = self.dev._param_property(X, params.slope_.swapaxes(2, 3), 0)
self.ldf_ = self.dev._param_property(obj, params.slope_.swapaxes(2, 3), 0)
return self

def test_full_slice(genins):
Expand Down
19 changes: 12 additions & 7 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@ def pytest_generate_tests(metafunc):
metafunc.parametrize("clrd", ["normal_run", "sparse_only_run"], indirect=True)
if "genins" in metafunc.fixturenames:
metafunc.parametrize("genins", ["normal_run", "sparse_only_run"], indirect=True)
if "prism_convert" in metafunc.fixturenames:
metafunc.parametrize(
"prism_convert", ["normal_run", "sparse_only_run"], indirect=True
)
if "prism_dense" in metafunc.fixturenames:
metafunc.parametrize(
"prism_dense", ["normal_run", "sparse_only_run"], indirect=True
)
if "prism" in metafunc.fixturenames:
metafunc.parametrize("prism", ["normal_run"], indirect=True)
metafunc.parametrize("prism", ["sparse_only_run"], indirect=True)
if "xyz" in metafunc.fixturenames:
metafunc.parametrize("xyz", ["normal_run", "sparse_only_run"], indirect=True)

Expand Down Expand Up @@ -56,14 +60,12 @@ def _sample_fixture(

"""

# Set the backend to sparse for a sparse-only-run.
cl.options.set_option("ARRAY_BACKEND", "sparse" if request.param == "sparse_only_run" else "numpy")
# Load the sample data.
tri = cl.load_sample(sample)
# Apply a transformation if supplied, then yield the triangle to the test.
yield transform(tri) if transform else tri
# After the test, reset the backend to default numpy.
cl.options.set_option("ARRAY_BACKEND", "numpy")
# Apply a transformation if supplied
tri = transform(tri) if transform else tri
# Set the backend to sparse for a sparse-only-run, then yield the triangle to the test.
yield tri.set_backend("sparse" if request.param == "sparse_only_run" else "numpy")


@pytest.fixture
Expand All @@ -90,6 +92,9 @@ def genins(request):
def prism(request):
yield from _sample_fixture(request, "prism")

@pytest.fixture
def prism_convert(request):
yield from _sample_fixture(request, "prism", transform=lambda t: t.iloc[:5000])

@pytest.fixture
def prism_dense(request):
Expand Down
Loading