Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix to scipy.minimize changes #124

Merged
merged 3 commits into from
Jul 7, 2023
Merged

Fix to scipy.minimize changes #124

merged 3 commits into from
Jul 7, 2023

Conversation

ikeuchi-screen
Copy link
Collaborator

Motivation

Fix for changes in scipy-1.11.0

The scipy.optimize.minimize function was changed in scipy-1.11.0.

SciPy 1.11.0 Release Notes
https://scipy.github.io/devdocs/release/1.11.0-notes.html#expired-deprecations

The scipy.optimize.minimize function now raises an error for x0 with x0.ndim > 1.

How to reproduce the error

Executing the following code will result in an error.

Confirmatory factor analysis example.

import pandas as pd
from factor_analyzer import (ConfirmatoryFactorAnalyzer, ModelSpecificationParser)

df_features = pd.read_csv('tests/data/test11.csv')
model_dict = {"F1": ["V1", "V2", "V3", "V4"], "F2": ["V5", "V6", "V7", "V8"]}
model_spec = ModelSpecificationParser.parse_model_specification_from_dict(df_features, model_dict)
cfa = ConfirmatoryFactorAnalyzer(model_spec, disp=False)
cfa.fit(df_features.values)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In [1], line 8
      6 model_spec = ModelSpecificationParser.parse_model_specification_from_dict(df_features, model_dict)
      7 cfa = ConfirmatoryFactorAnalyzer(model_spec, disp=False)
----> 8 cfa.fit(df_features.values)

File ~\factor_analyzer\confirmatory_factor_analyzer.py:742, in ConfirmatoryFactorAnalyzer.fit(self, X, y)
    737     assert len(self.bounds) == len(x0), error_msg
    739 # fit the actual model using L-BFGS algorithm;
    740 # the constraints are set inside the objective function,
    741 # so that we can avoid using linear programming methods (e.g. SLSQP)
--> 742 res = minimize(
    743     self._objective,
    744     x0,
    745     method="L-BFGS-B",
    746     options={"maxiter": self.max_iter, "disp": self.disp},
    747     bounds=self.bounds,
    748     args=(cov_mtx, self.model.loadings),
    749 )
    751 # if the optimizer failed to converge, print the message
    752 if not res.success:

File ~\AppData\Roaming\Python\Python39\site-packages\scipy\optimize\_minimize.py:533, in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)
    530 x0 = np.atleast_1d(np.asarray(x0))
    532 if x0.ndim != 1:
--> 533     raise ValueError("'x0' must only have one dimension.")
    535 if x0.dtype.kind in np.typecodes["AllInteger"]:
    536     x0 = np.asarray(x0, dtype=float)

ValueError: 'x0' must only have one dimension.

Expected Behavior

https://github.com/EducationalTestingService/factor_analyzer#examples

Description of the changes

The error can be avoided by setting x0 in the minimize function to 1d-vector.

res = minimize(
    self._objective,
    x0.flatten(),
    method="L-BFGS-B",
    options={"maxiter": self.max_iter, "disp": self.disp},
    bounds=self.bounds,
    args=(cov_mtx, self.model.loadings),
)

@desilinguist
Copy link
Member

@ikeuchi-screen I think I know why the code coverage is not being computed. I am going to use this PR to also fix the coverage issue in a bit. Thanks for your patience!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants