diff --git a/.github/workflows/macos-tests-3.12.yml b/.github/workflows/macos-tests-3.12.yml new file mode 100644 index 0000000..aebcadf --- /dev/null +++ b/.github/workflows/macos-tests-3.12.yml @@ -0,0 +1,24 @@ +name: macos build + +# workflow dispatch has been added for testing purposes +on: [push, pull_request, workflow_dispatch] + +jobs: + build: + runs-on: ["macos-13"] + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + - name: Install spare scores + run: | + python -m pip cache purge + pip install -r requirements.txt + pip install setuptools twine wheel + python -m pip install . + - name: Run unit tests + run: | + pip install pytest pytest-cov + cd tests/unit && pytest --cov=../../ diff --git a/.github/workflows/macos_test_cases_p3-8.yml b/.github/workflows/macos-tests-3.8.yml similarity index 95% rename from .github/workflows/macos_test_cases_p3-8.yml rename to .github/workflows/macos-tests-3.8.yml index 7c91627..08c3735 100644 --- a/.github/workflows/macos_test_cases_p3-8.yml +++ b/.github/workflows/macos-tests-3.8.yml @@ -1,4 +1,4 @@ -name: spare_scores test cases on macos for python 3.8 +name: macos tests python=3.8 # workflow dispatch has been added for testing purposes on: [push, pull_request, workflow_dispatch] diff --git a/.github/workflows/macos_test_cases_p3-12.yml b/.github/workflows/ubuntu-tests-3.12.yml similarity index 52% rename from .github/workflows/macos_test_cases_p3-12.yml rename to .github/workflows/ubuntu-tests-3.12.yml index b9c42d4..04f78ea 100644 --- a/.github/workflows/macos_test_cases_p3-12.yml +++ b/.github/workflows/ubuntu-tests-3.12.yml @@ -1,29 +1,21 @@ -name: spare_scores test cases on macos for python 3.12 +name: ubuntu build # workflow dispatch has been added for testing purposes on: [push, pull_request, workflow_dispatch] jobs: build: - runs-on: ["macos-13"] + runs-on: ["ubuntu-latest"] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - - name: Set-up miniconda for macos and ubuntu - uses: conda-incubator/setup-miniconda@v2 - with: - auto-update-conda: true - python-version: 3.12 - miniconda-version: "latest" - - name: Create conda env - run: conda create -n spare python=3.12 - - name: Install pip - run: conda run -n spare conda install pip - name: Install spare scores run: | + python -m pip cache purge + pip install -r requirements.txt pip install setuptools twine wheel python -m pip install . - name: Run unit tests diff --git a/.github/workflows/ubuntu_test_cases_p3-8.yml b/.github/workflows/ubuntu-tests-3.8.yml similarity index 54% rename from .github/workflows/ubuntu_test_cases_p3-8.yml rename to .github/workflows/ubuntu-tests-3.8.yml index 552323c..0c6b9ba 100644 --- a/.github/workflows/ubuntu_test_cases_p3-8.yml +++ b/.github/workflows/ubuntu-tests-3.8.yml @@ -1,4 +1,4 @@ -name: spare_scores test cases on ubuntu for python 3.8 +name: ubuntu build python=3.8 # workflow dispatch has been added for testing purposes on: [push, pull_request, workflow_dispatch] @@ -12,25 +12,15 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.8" - - name: Set-up miniconda for macos and ubuntu - uses: conda-incubator/setup-miniconda@v2 - with: - auto-update-conda: true - python-version: 3.8 - miniconda-version: "latest" - - name: Create conda env - run: conda create -n spare python=3.8 - - name: Install pip - run: conda run -n spare conda install pip - name: Install spare scores run: | + python -m pip cache purge + pip install -r requirements.txt pip install setuptools twine wheel python setup.py bdist_wheel cd dist WHEEL_FILE=$(ls spare_scores*) pip install "$WHEEL_FILE" - - name: Download dependencies - run: pip install setuptools && pip install . - name: Run unit tests run: | cd tests/unit && python -m unittest discover -s . -p "*.py" diff --git a/.github/workflows/ubuntu_test_cases_p3-12.yml b/.github/workflows/ubuntu_test_cases_p3-12.yml deleted file mode 100644 index 8d71e56..0000000 --- a/.github/workflows/ubuntu_test_cases_p3-12.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: spare_scores test cases on ubuntu for python 3.12 - -# workflow dispatch has been added for testing purposes -on: [push, pull_request, workflow_dispatch] - -jobs: - build: - runs-on: ["ubuntu-latest"] - - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - name: Set-up miniconda for macos and ubuntu - uses: conda-incubator/setup-miniconda@v2 - with: - auto-update-conda: true - python-version: 3.12 - miniconda-version: "latest" - - name: Create conda env - run: conda create -n spare python=3.12 - - name: Install pip - run: conda run -n spare conda install pip - - name: Install spare scores - run: | - pip install setuptools twine wheel - python -m pip install . - - name: Download dependencies - run: pip install setuptools && pip install . - - name: Run unit tests - run: | - cd tests/unit && python -m unittest discover -s . -p "*.py" diff --git a/README.md b/README.md index 1f5dd37..1111a3a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ [![codecov](https://codecov.io/gh/CBICA/spare_score/graph/badge.svg?token=7yk7pkydHE)](https://codecov.io/gh/CBICA/spare_score) +![macos tests](https://github.com/CBICA/spare_score/actions/workflows/macos-tests-3.12.yml/badge.svg) +![ubuntu tests](https://github.com/CBICA/spare_score/actions/workflows/ubuntu-tests-3.12.yml/badge.svg) # Compute SPARE Scores for Your Case @@ -38,9 +40,9 @@ Please open an issue if you find any bugs for the newer versions of spare_score # for python 3.12 git clone https://github.com/CBICA/spare_score.git cd spare_score - python -m pip install . + python -m pip install . - # for python 3.8... + # for python 3.8 python setup.py bdist_wheel cd dist && pip install ... diff --git a/dev-dependencies.txt b/requirements.txt similarity index 86% rename from dev-dependencies.txt rename to requirements.txt index d12df9f..6eaf6a5 100644 --- a/dev-dependencies.txt +++ b/requirements.txt @@ -16,11 +16,11 @@ iniconfig==2.0.0 joblib==1.3.1 jsonschema==4.17.3 kiwisolver==1.4.4 -matplotlib==3.9.0 +matplotlib==3.7.5 msgpack==1.0.5 -numpy==1.22.0 +numpy packaging==23.1 -pandas==2.2.0 +pandas==2.0.3 Pillow==9.5.0 pkgutil_resolve_name==1.3.10 pluggy==1.5.0 @@ -31,14 +31,13 @@ pytest==8.2.2 python-dateutil==2.8.2 pytz==2023.3 PyYAML==6.0.2 -ray==2.34.0 requests==2.31.0 -scikit-learn==1.0.1 -scipy==1.14.0 +scikit-learn==1.3.2 +scipy six==1.16.0 threadpoolctl==3.1.0 tomli==2.0.1 -torch==2.2.0 +torch==2.2.1 torchvision==0.17.1 typing_extensions==4.8.0 tzdata==2023.3 diff --git a/setup.cfg b/setup.cfg index aae17b1..d7ecc64 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,7 +17,7 @@ per-file-ignores = __init__.py: F401, F403 [mypy] -exclude= tests +exclude = tests # Import discovery namespace_packages = False ignore_missing_imports = True diff --git a/spare_scores/mlp.py b/spare_scores/mlp.py index afb233a..27a6b0a 100644 --- a/spare_scores/mlp.py +++ b/spare_scores/mlp.py @@ -100,7 +100,7 @@ def __init__( "mlp__alpha": [0.001, 0.01, 0.05, 0.1], "mlp__learning_rate": ["constant", "adaptive"], "mlp__early_stopping": [True], - "mlp__max_iter": [500], + "mlp__max_iter": [1000], } def set_parameters(self, **parameters: Any) -> None: @@ -113,11 +113,11 @@ def _fit(self, df: pd.DataFrame) -> None: y = df[self.to_predict].astype("float64") if self.task == "Regression": - mlp = MLPRegressor(early_stopping=True, max_iter=500) + mlp = MLPRegressor(early_stopping=True, max_iter=1000) scoring = "neg_mean_absolute_error" metrics = ["MAE", "RMSE", "R2"] else: - mlp = MLPClassifier(early_stopping=True, max_iter=500) + mlp = MLPClassifier(early_stopping=True, max_iter=1000) scoring = "balanced_accuracy" metrics = [ "AUC", diff --git a/spare_scores/mlp_torch.py b/spare_scores/mlp_torch.py index b37a0ab..138ed33 100644 --- a/spare_scores/mlp_torch.py +++ b/spare_scores/mlp_torch.py @@ -49,7 +49,7 @@ class MLPDataset(Dataset): """ - def __init__(self, X: list, y: list): + def __init__(self, X: list, y: list) -> None: self.X = np.array(X, dtype=np.float32) self.y = np.array(y, dtype=np.float32) @@ -59,13 +59,15 @@ def __len__(self) -> int: """ return len(self.y) - def __getitem__(self, idx: int) -> Tuple[np.float32, np.float32]: + def __getitem__(self, idx: int) -> Tuple[torch.Tensor, torch.Tensor]: """ (getter)returns the index of both X and y at index: idx(X[idx], y[idx]) :param idx: the index :type idx: int """ - return self.X[idx], self.y[idx] + return torch.tensor(self.X[idx], dtype=torch.float32), torch.tensor( + self.y[idx], dtype=torch.float32 + ) class SimpleMLP(nn.Module): @@ -213,12 +215,12 @@ def __init__( # Model settings self.classification = True if self.task == "Classification" else False - self.mdl: Any - self.scaler: Any - self.stats: Any - self.param: Any - self.train_dl: Any - self.val_dl: Any + self.mdl: SimpleMLP + self.scaler: StandardScaler + self.stats: dict + self.param: dict + self.train_dl: DataLoader + self.val_dl: DataLoader def find_best_threshold(self, y_hat: list, y: list) -> Any: """ @@ -230,7 +232,7 @@ def find_best_threshold(self, y_hat: list, y: list) -> Any: :type y: list :return: the best threshold value - :rtype: Any + :rtype: List """ diff --git a/spare_scores/svm.py b/spare_scores/svm.py index a3a7b30..2dd3dac 100644 --- a/spare_scores/svm.py +++ b/spare_scores/svm.py @@ -249,7 +249,7 @@ def train_initialize(self, df: pd.DataFrame, to_predict: str) -> None: ) self.to_predict, self.classify = to_predict, list(df[to_predict].unique()) self.mdl = ( - [LinearSVC(max_iter=100000, dual="auto")] + [LinearSVC(max_iter=100000, dual=False)] if self.kernel == "linear" else [SVC(max_iter=100000, kernel=self.kernel)] ) * len(self.folds) @@ -260,7 +260,11 @@ def train_initialize(self, df: pd.DataFrame, to_predict: str) -> None: ["MAE", "RMSE", "R2"], ) self.to_predict, self.classify = to_predict, None - self.mdl = [LinearSVR(max_iter=100000, dual="auto")] * len(self.folds) + self.mdl = [ + LinearSVR( + max_iter=100000, loss="squared_epsilon_insensitive", dual=False + ) + ] * len(self.folds) self.bias_correct = { "slope": np.zeros((len(self.folds),)), "int": np.zeros((len(self.folds),)), @@ -320,6 +324,7 @@ def param_search( scoring=scoring, cv=self.k, return_train_score=True, + error_score=0.0, verbose=0, ) gs.fit(X_train, y_train) diff --git a/test_data_prep.py b/test_data_prep.py deleted file mode 100644 index e69de29..0000000