easytorch


Nameeasytorch JSON
Version 3.8.5 PyPI version JSON
download
home_pagehttps://github.com/sraashis/easytorch
SummaryEasy Neural Network Experiments with pytorch
upload_time2023-12-06 00:18:36
maintainer
docs_urlNone
authorAashis Khana1
requires_python
licenseMIT
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ## A very lightweight framework on top of PyTorch with full functionality.

#### **Just one way of doing things means no learning curve.**  ✅

![Logo](assets/easytorchlogo.png)

![PyPi version](https://img.shields.io/pypi/v/easytorch)
[![YourActionName Actions Status](https://github.com/sraashis/easytorch/workflows/build/badge.svg)](https://github.com/sraashis/easytorch/actions)
![Python versions](https://img.shields.io/pypi/pyversions/pybadges.svg)

<hr />

#### Installation

1. `pip install --upgrade pip`
2. `Install latest pytorch and torchvision from` [Pytorch](https://pytorch.org/)
3. `pip install easytorch`

* [MNIST](./examples/MNIST_easytorch_CNN.ipynb) [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github//sraashis/easytorch/blob/master/examples/MNIST_easytorch_CNN.ipynb)
* [Retinal fundus image transfer learning tasks.](https://github.com/sraashis/retinal-fundus-transfer)
* [Covid-19 chest x-ray classification.](https://github.com/sraashis/covidxfactory)
* [DCGAN.](https://github.com/sraashis/gan-easytorch-celeb-faces)

#### Let's start with something simple like MNIST digit classification:

```python
from easytorch import EasyTorch, ETRunner, ConfusionMatrix, ETMeter
from torchvision import datasets, transforms
import torch.nn.functional as F
import torch
from examples.models import MNISTNet

transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
])


class MNISTTrainer(ETRunner):
    def _init_nn_model(self):
        self.nn['model'] = MNISTNet()

    def iteration(self, batch):
        inputs, labels = batch[0].to(self.device['gpu']).float(), batch[1].to(self.device['gpu']).long()

        out = self.nn['model'](inputs)
        loss = F.nll_loss(out, labels)
        _, pred = torch.max(out, 1)

        meter = self.new_meter()
        meter.averages.add(loss.item(), len(inputs))
        meter.metrics['cfm'].add(pred, labels.float())

        return {'loss': loss, 'meter': meter, 'predictions': pred}

    def init_experiment_cache(self):
        self.cache['log_header'] = 'Loss|Accuracy,F1,Precision,Recall'
        self.cache.update(monitor_metric='f1', metric_direction='maximize')

    def new_meter(self):
        return ETMeter(
            cfm=ConfusionMatrix(num_classes=10),
            device=self.device['gpu']
        )


if __name__ == "__main__":
    train_dataset = datasets.MNIST('../data', train=True, download=True, transform=transform)
    val_dataset = datasets.MNIST('../data', train=False, transform=transform)

    dataloader_args = {'train': {'dataset': train_dataset}, 'validation': {'dataset': val_dataset}}
    runner = EasyTorch(phase='train', batch_size=512,
                       epochs=10, gpus=[0], dataloader_args=dataloader_args)
    runner.run(MNISTTrainer)
```

### Run as:

`python script.py -ph train -b 512 -e 10 -gpus 0`

### ... with **20+** useful options. Check [here](./easytorch/config/) for full list.

<hr />

## General use case:

#### 1. Define your trainer

```python
from easytorch import ETRunner, Prf1a, ETMeter, AUCROCMetrics


class MyTrainer(ETRunner):

    def _init_nn_model(self):
        self.nn['model'] = NeuralNetModel(out_size=self.conf['num_class'])

    def iteration(self, batch):
        """Handle a single batch"""
        """Must have loss and meter"""
        meter = self.new_meter()
        ...
        return {'loss': ..., 'meter': ..., 'predictions': ...}

    def new_meter(self):
        return ETMeter(
            num_averages=1,
            prf1a=Prf1a(),
            auc=AUCROCMetrics(),
            device=self.device['gpu']
        )

    def init_cache(self):
        """Will plot Loss in one plot, and Accuracy,F1_score in another."""
        self.cache['log_header'] = 'Loss|Accuracy,F1_score'

        """Model selection using validation set if present"""
        self.cache.update(monitor_metric='f1', metric_direction='maximize')

````

* Method new_meter() returns ETMeter that takes any implementation of easytorch.meter.ETMetrics. Provided ones:
    * easytorch.metrics.Prf1a() for binary classification that computes accuracy,f1,precision,recall, overlap/IOU.
    * easytorch.metrics.ConfusionMatrix(num_classes=...) for multiclass classification that also computes global
      accuracy,f1,precision,recall.
    * easytorch.metrics.AUCROCMetrics for binary ROC-AUC score.

#### 2. Define specification for your datasets:

* EasyTorch automatically splits the training data in _**data_source**_ as specified by
  _**split_ratio(-spl or --split-ratio 0.7, 0.15, 0.15, for train validation and test portion)**_ OR Custom splits in
    1. Text files:
        * data_source = "/some/path/*.txt", where it looks for 'train.txt', 'validation.txt', and 'test.txt' if phase is
          _train_, and only 'test.txt' if phase is _test_
    2. Json files:
        * data_source = "some/path/split.json", where each split key has list of files as {'train': [], '
          validation' :[], 'test':[]}
    3. Just glob as data_source = "some/path/**/*.txt", must also provide split_ratio if phase = _train_

```python
from easytorch import ETDataset


class MyDataset(ETDataset):
    def load_index(self, file):
        """(Optional) Load/Process something and add to diskcache as:
                self.diskcahe.add(file, value)"""
        """This method runs in multiple processes by default"""

        self.indices.append([file, 'something_extra'])

    def __getitem__(self, index):
        file = self.indices[index]
        """(Optional) Retrieve from diskcache as self.diskcache.get(file)"""

        image =  # Todo # Load file/Image. 
        label =  # Todo # Load corresponding label.

        # Extra preprocessing, if needed.
        # Apply transforms, if needed.

        return image, label
```

#### 3. Entry point (say main.py)
### Run as:

`python main.py -ph train -b 512 -e 10 -gpus 0`

One can also directly pass arguments as below which overrides all.
```python
from easytorch import EasyTorch

runner = EasyTorch(phase="train", batch_size=4, epochs=10,
                   gpus=[0], num_channel=1, 
                   num_class=2, data_source="<some_data>/data_split.json")
runner.run(MyTrainer, MyDataset)
```

### All the best! Cheers! 🎉

#### Cite the following papers if you use this library:

```
@article{deepdyn_10.3389/fcomp.2020.00035,
	title        = {Dynamic Deep Networks for Retinal Vessel Segmentation},
	author       = {Khanal, Aashis and Estrada, Rolando},
	year         = 2020,
	journal      = {Frontiers in Computer Science},
	volume       = 2,
	pages        = 35,
	doi          = {10.3389/fcomp.2020.00035},
	issn         = {2624-9898}
}

@misc{2202.02382,
        Author       = {Aashis Khanal and Saeid Motevali and Rolando Estrada},
        Title        = {Fully Automated Tree Topology Estimation and Artery-Vein Classification},
        Year         = {2022},
        Eprint       = {arXiv:2202.02382},
}
```

### Feature Higlights:

* DataHandle that is always available, and decoupled from other modules enabling easy
  customization ([ETDataHandle](easytorch/data/data.py)).
    * Use custom & complex data handling mechanism.
* Simple lightweight logger/plotter.
    * **Plot:** set log_header = 'Loss,F1,Accuracy' to plot in same plot or set log_header = 'Loss|F1,Accuracy' to plot
      Loss in one plot, and F1,Accuracy in another plot.
    * **Logs:** all arguments/generated data will be saved in logs.json file after the experiment finishes.
* Gradient accumulation, automatic logging/plotting, model checkpointing, save everything.
* Multiple metrics implementation at easytorch.metrics: Precision, Recall, Accuracy, Overlap, F1, ROC-AUC, Confusion
  matrix
* **For advanced training with multiple networks, and complex training steps,
  click [here](assets/AdvancedTraining.md):**
* **Implement custom metrics as [here](assets/CustomMetrics.md).**


            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/sraashis/easytorch",
    "name": "easytorch",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "",
    "author": "Aashis Khana1",
    "author_email": "sraashis@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/5d/db/0b29bbd3da4ad3e7898a8f296389a00e1936f7f16317f5bccc41cca3347e/easytorch-3.8.5.tar.gz",
    "platform": null,
    "description": "## A very lightweight framework on top of PyTorch with full functionality.\n\n#### **Just one way of doing things means no learning curve.**  \u2705\n\n![Logo](assets/easytorchlogo.png)\n\n![PyPi version](https://img.shields.io/pypi/v/easytorch)\n[![YourActionName Actions Status](https://github.com/sraashis/easytorch/workflows/build/badge.svg)](https://github.com/sraashis/easytorch/actions)\n![Python versions](https://img.shields.io/pypi/pyversions/pybadges.svg)\n\n<hr />\n\n#### Installation\n\n1. `pip install --upgrade pip`\n2. `Install latest pytorch and torchvision from` [Pytorch](https://pytorch.org/)\n3. `pip install easytorch`\n\n* [MNIST](./examples/MNIST_easytorch_CNN.ipynb) [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github//sraashis/easytorch/blob/master/examples/MNIST_easytorch_CNN.ipynb)\n* [Retinal fundus image transfer learning tasks.](https://github.com/sraashis/retinal-fundus-transfer)\n* [Covid-19 chest x-ray classification.](https://github.com/sraashis/covidxfactory)\n* [DCGAN.](https://github.com/sraashis/gan-easytorch-celeb-faces)\n\n#### Let's start with something simple like MNIST digit classification:\n\n```python\nfrom easytorch import EasyTorch, ETRunner, ConfusionMatrix, ETMeter\nfrom torchvision import datasets, transforms\nimport torch.nn.functional as F\nimport torch\nfrom examples.models import MNISTNet\n\ntransform = transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Normalize((0.1307,), (0.3081,))\n])\n\n\nclass MNISTTrainer(ETRunner):\n    def _init_nn_model(self):\n        self.nn['model'] = MNISTNet()\n\n    def iteration(self, batch):\n        inputs, labels = batch[0].to(self.device['gpu']).float(), batch[1].to(self.device['gpu']).long()\n\n        out = self.nn['model'](inputs)\n        loss = F.nll_loss(out, labels)\n        _, pred = torch.max(out, 1)\n\n        meter = self.new_meter()\n        meter.averages.add(loss.item(), len(inputs))\n        meter.metrics['cfm'].add(pred, labels.float())\n\n        return {'loss': loss, 'meter': meter, 'predictions': pred}\n\n    def init_experiment_cache(self):\n        self.cache['log_header'] = 'Loss|Accuracy,F1,Precision,Recall'\n        self.cache.update(monitor_metric='f1', metric_direction='maximize')\n\n    def new_meter(self):\n        return ETMeter(\n            cfm=ConfusionMatrix(num_classes=10),\n            device=self.device['gpu']\n        )\n\n\nif __name__ == \"__main__\":\n    train_dataset = datasets.MNIST('../data', train=True, download=True, transform=transform)\n    val_dataset = datasets.MNIST('../data', train=False, transform=transform)\n\n    dataloader_args = {'train': {'dataset': train_dataset}, 'validation': {'dataset': val_dataset}}\n    runner = EasyTorch(phase='train', batch_size=512,\n                       epochs=10, gpus=[0], dataloader_args=dataloader_args)\n    runner.run(MNISTTrainer)\n```\n\n### Run as:\n\n`python script.py -ph train -b 512 -e 10 -gpus 0`\n\n### ... with **20+** useful options. Check [here](./easytorch/config/) for full list.\n\n<hr />\n\n## General use case:\n\n#### 1. Define your trainer\n\n```python\nfrom easytorch import ETRunner, Prf1a, ETMeter, AUCROCMetrics\n\n\nclass MyTrainer(ETRunner):\n\n    def _init_nn_model(self):\n        self.nn['model'] = NeuralNetModel(out_size=self.conf['num_class'])\n\n    def iteration(self, batch):\n        \"\"\"Handle a single batch\"\"\"\n        \"\"\"Must have loss and meter\"\"\"\n        meter = self.new_meter()\n        ...\n        return {'loss': ..., 'meter': ..., 'predictions': ...}\n\n    def new_meter(self):\n        return ETMeter(\n            num_averages=1,\n            prf1a=Prf1a(),\n            auc=AUCROCMetrics(),\n            device=self.device['gpu']\n        )\n\n    def init_cache(self):\n        \"\"\"Will plot Loss in one plot, and Accuracy,F1_score in another.\"\"\"\n        self.cache['log_header'] = 'Loss|Accuracy,F1_score'\n\n        \"\"\"Model selection using validation set if present\"\"\"\n        self.cache.update(monitor_metric='f1', metric_direction='maximize')\n\n````\n\n* Method new_meter() returns ETMeter that takes any implementation of easytorch.meter.ETMetrics. Provided ones:\n    * easytorch.metrics.Prf1a() for binary classification that computes accuracy,f1,precision,recall, overlap/IOU.\n    * easytorch.metrics.ConfusionMatrix(num_classes=...) for multiclass classification that also computes global\n      accuracy,f1,precision,recall.\n    * easytorch.metrics.AUCROCMetrics for binary ROC-AUC score.\n\n#### 2. Define specification for your datasets:\n\n* EasyTorch automatically splits the training data in _**data_source**_ as specified by\n  _**split_ratio(-spl or --split-ratio 0.7, 0.15, 0.15, for train validation and test portion)**_ OR Custom splits in\n    1. Text files:\n        * data_source = \"/some/path/*.txt\", where it looks for 'train.txt', 'validation.txt', and 'test.txt' if phase is\n          _train_, and only 'test.txt' if phase is _test_\n    2. Json files:\n        * data_source = \"some/path/split.json\", where each split key has list of files as {'train': [], '\n          validation' :[], 'test':[]}\n    3. Just glob as data_source = \"some/path/**/*.txt\", must also provide split_ratio if phase = _train_\n\n```python\nfrom easytorch import ETDataset\n\n\nclass MyDataset(ETDataset):\n    def load_index(self, file):\n        \"\"\"(Optional) Load/Process something and add to diskcache as:\n                self.diskcahe.add(file, value)\"\"\"\n        \"\"\"This method runs in multiple processes by default\"\"\"\n\n        self.indices.append([file, 'something_extra'])\n\n    def __getitem__(self, index):\n        file = self.indices[index]\n        \"\"\"(Optional) Retrieve from diskcache as self.diskcache.get(file)\"\"\"\n\n        image =  # Todo # Load file/Image. \n        label =  # Todo # Load corresponding label.\n\n        # Extra preprocessing, if needed.\n        # Apply transforms, if needed.\n\n        return image, label\n```\n\n#### 3. Entry point (say main.py)\n### Run as:\n\n`python main.py -ph train -b 512 -e 10 -gpus 0`\n\nOne can also directly pass arguments as below which overrides all.\n```python\nfrom easytorch import EasyTorch\n\nrunner = EasyTorch(phase=\"train\", batch_size=4, epochs=10,\n                   gpus=[0], num_channel=1, \n                   num_class=2, data_source=\"<some_data>/data_split.json\")\nrunner.run(MyTrainer, MyDataset)\n```\n\n### All the best! Cheers! \ud83c\udf89\n\n#### Cite the following papers if you use this library:\n\n```\n@article{deepdyn_10.3389/fcomp.2020.00035,\n\ttitle        = {Dynamic Deep Networks for Retinal Vessel Segmentation},\n\tauthor       = {Khanal, Aashis and Estrada, Rolando},\n\tyear         = 2020,\n\tjournal      = {Frontiers in Computer Science},\n\tvolume       = 2,\n\tpages        = 35,\n\tdoi          = {10.3389/fcomp.2020.00035},\n\tissn         = {2624-9898}\n}\n\n@misc{2202.02382,\n        Author       = {Aashis Khanal and Saeid Motevali and Rolando Estrada},\n        Title        = {Fully Automated Tree Topology Estimation and Artery-Vein Classification},\n        Year         = {2022},\n        Eprint       = {arXiv:2202.02382},\n}\n```\n\n### Feature Higlights:\n\n* DataHandle that is always available, and decoupled from other modules enabling easy\n  customization ([ETDataHandle](easytorch/data/data.py)).\n    * Use custom & complex data handling mechanism.\n* Simple lightweight logger/plotter.\n    * **Plot:** set log_header = 'Loss,F1,Accuracy' to plot in same plot or set log_header = 'Loss|F1,Accuracy' to plot\n      Loss in one plot, and F1,Accuracy in another plot.\n    * **Logs:** all arguments/generated data will be saved in logs.json file after the experiment finishes.\n* Gradient accumulation, automatic logging/plotting, model checkpointing, save everything.\n* Multiple metrics implementation at easytorch.metrics: Precision, Recall, Accuracy, Overlap, F1, ROC-AUC, Confusion\n  matrix\n* **For advanced training with multiple networks, and complex training steps,\n  click [here](assets/AdvancedTraining.md):**\n* **Implement custom metrics as [here](assets/CustomMetrics.md).**\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Easy Neural Network Experiments with pytorch",
    "version": "3.8.5",
    "project_urls": {
        "Homepage": "https://github.com/sraashis/easytorch"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "5ddb0b29bbd3da4ad3e7898a8f296389a00e1936f7f16317f5bccc41cca3347e",
                "md5": "f55045e710b7ade2f486716083447429",
                "sha256": "dc4110a15a702282d86f3788ea8fad7544c9c5fc4478a7eddb1869a5ca0cdfe9"
            },
            "downloads": -1,
            "filename": "easytorch-3.8.5.tar.gz",
            "has_sig": false,
            "md5_digest": "f55045e710b7ade2f486716083447429",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 34655,
            "upload_time": "2023-12-06T00:18:36",
            "upload_time_iso_8601": "2023-12-06T00:18:36.317803Z",
            "url": "https://files.pythonhosted.org/packages/5d/db/0b29bbd3da4ad3e7898a8f296389a00e1936f7f16317f5bccc41cca3347e/easytorch-3.8.5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-12-06 00:18:36",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "sraashis",
    "github_project": "easytorch",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "easytorch"
}
        
Elapsed time: 0.15584s