torbi


Nametorbi JSON
Version 1.3.3 PyPI version JSON
download
home_pageNone
SummaryOptimized Viterbi decoding and fast approximations
upload_time2025-09-01 19:25:09
maintainerNone
docs_urlNone
authorNone
requires_python>=3.9
licenseMIT License
keywords decode sequence torch viterbi
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <h1 align="center">Viterbi decoding in PyTorch</h1>
<div align="center">

[![PyPI](https://img.shields.io/pypi/v/torbi.svg)](https://pypi.python.org/pypi/torbi)
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![Downloads](https://pepy.tech/badge/torbi)](https://pepy.tech/project/torbi)

</div>


Highly parallelizable Viterbi decoding for CPU or GPU compute. Below are time benchmarks of our method relative to `librosa.sequence.viterbi`. We use 1440 states and ~20 million timesteps over ~40k files for benchmarking.

| Method  | Timesteps decoded per second |
| ------------- | ------------- |
| Librosa (1x cpu)| 208 |
| Librosa (16x cpu)| 1,382* |
| Proposed (1x cpu)| 171 |
| Proposed (16x cpu)| **2,240** |
| Proposed (1x a40 gpu, batch size 1)| **3,944,452** |
| Proposed (1x a40 gpu, batch size 512)| **692,160,422** |

*By default, `librosa.sequence.viterbi` uses one CPU thread. We use a Multiprocessing pool to parallelize.


## Table of contents

- [Installation](#installation)
- [Decoding](#decoding)
    * [Application programming interface](#application-programming-interface)
        * [`torbi.from_probabilities`](#torbifrom_probabilities)
        * [`torbi.from_file`](#torbifrom_file)
        * [`torbi.from_file_to_file`](#torbifrom_file_to_file)
        * [`torbi.from_files_to_files`](#torbifrom_files_to_files)
    * [Command-line interface](#command-line-interface)
- [Evaluation](#evaluation)
    * [Download](#download)
    * [Preprocess](#preprocess)
    * [Partition](#partition)
    * [Evaluate](#evaluate)
- [Citation](#citation)


## Installation

```bash
git clone git@github.com:maxrmorrison/torbi
pip install torbi/
```

If you receive an error message regarding mismatched CUDA versions, change the torch version in `pyproject.toml` to your currently installed version of `torch`.

To perform evaluation of the accuracy and speed of decoding methods, install `torbi` with the additional evaluation dependencies.

`pip install torbi[evaluate]`


## Decoding

### Application programming interface

```python
import torbi
import torch

# Time-varying categorical distribution to decode
observation = torch.tensor([
    [0.25, 0.5, 0.25],
    [0.25, 0.25, 0.5],
    [0.33, 0.33, 0.33]
]).unsqueeze(dim=0)

# Transition probabilities bewteen categories
transition = torch.tensor([
    [0.5, 0.25, 0.25],
    [0.33, 0.34, 0.33],
    [0.25, 0.25, 0.5]
])

# Initial category probabilities
initial = torch.tensor([0.4, 0.35, 0.25])

# Find optimal path using CPU compute
torbi.from_probabilities(
   observation,
   transition=transition,
   initial=initial,
   log_probs=False)

# Find optimal path using GPU compute
torbi.from_probabilities(
   observation,
   transition=transition,
   initial=initial,
   log_probs=False,
   gpu=0)
```


#### `torbi.from_probabilities`

```python
def from_probabilities(
    observation: torch.Tensor,
    batch_frames: Optional[torch.Tensor] = None,
    transition: Optional[torch.Tensor] = None,
    initial: Optional[torch.Tensor] = None,
    log_probs: bool = False,
    gpu: Optional[int] = None,
    num_threads: Optional[int] = 1
) -> torch.Tensor:
    """Decode a time-varying categorical distribution

    Arguments
        observation
            Time-varying categorical distribution
            shape=(batch, frames, states)
        batch_frames
            Number of frames in each batch item; defaults to all
            shape=(batch,)
        transition
            Categorical transition matrix; defaults to uniform
            shape=(states, states)
        initial
            Categorical initial distribution; defaults to uniform
            shape=(states,)
        log_probs
            Whether inputs are in (natural) log space
        gpu
            GPU index to use for decoding. Defaults to CPU.
        num_threads
            The number of threads to use for parallelized decoding

    Returns
        indices
            The decoded bin indices
            shape=(batch, frames)
    """
```


#### `torbi.from_file`

```python
def from_file(
    input_file: Union[str, os.PathLike],
    transition_file: Optional[Union[str, os.PathLike]] = None,
    initial_file: Optional[Union[str, os.PathLike]] = None,
    log_probs: bool = False,
    gpu: Optional[int] = None,
    num_threads: Optional[int] = 1
) -> torch.Tensor:
    """Decode a time-varying categorical distribution file

    Arguments
        input_file
            Time-varying categorical distribution file
            shape=(frames, states)
        transition_file
            Categorical transition matrix file; defaults to uniform
            shape=(states, states)
        initial_file
            Categorical initial distribution file; defaults to uniform
            shape=(states,)
        log_probs
            Whether inputs are in (natural) log space
        gpu
            GPU index to use for decoding. Defaults to CPU.
        num_threads
            The number of threads to use for parallelized decoding

    Returns
        indices
            The decoded bin indices
            shape=(frames,)
    """
```


#### `torbi.from_file_to_file`

```python
def from_file_to_file(
    input_file: Union[str, os.PathLike],
    output_file: Union[str, os.PathLike],
    transition_file: Optional[Union[str, os.PathLike]] = None,
    initial_file: Optional[Union[str, os.PathLike]] = None,
    log_probs: bool = False,
    gpu: Optional[int] = None,
    num_threads: Optional[int] = None
) -> None:
    """Decode a time-varying categorical distribution file and save

    Arguments
        input_file
            Time-varying categorical distribution file
            shape=(frames, states)
        output_file
            File to save decoded indices
        transition_file
            Categorical transition matrix file; defaults to uniform
            shape=(states, states)
        initial_file
            Categorical initial distribution file; defaults to uniform
            shape=(states,)
        log_probs
            Whether inputs are in (natural) log space
        gpu
            GPU index to use for decoding. Defaults to CPU.
        num_threads
            The number of threads to use for parallelized decoding
    """
```


#### `torbi.from_files_to_files`

```python
def from_files_to_files(
    input_files: List[Union[str, os.PathLike]],
    output_files: List[Union[str, os.PathLike]],
    transition_file: Optional[Union[str, os.PathLike]] = None,
    initial_file: Optional[Union[str, os.PathLike]] = None,
    log_probs: bool = False,
    gpu: Optional[int] = None,
    num_threads: Optional[int] = None
) -> None:
    """Decode time-varying categorical distribution files and save

    Arguments
        input_files
            Time-varying categorical distribution files
            shape=(frames, states)
        output_files
            Files to save decoded indices
        transition_file
            Categorical transition matrix file; defaults to uniform
            shape=(states, states)
        initial_file
            Categorical initial distribution file; defaults to uniform
            shape=(states,)
        log_probs
            Whether inputs are in (natural) log space
        gpu
            GPU index to use for decoding. Defaults to CPU.
        num_threads
            The number of threads to use for parallelized decoding
    """
```


### Command-line interface

```
usage: python -m torbi
    [-h]
    --input_files INPUT_FILES [INPUT_FILES ...]
    --output_files OUTPUT_FILES [OUTPUT_FILES ...]
    [--transition_file TRANSITION_FILE]
    [--initial_file INITIAL_FILE]
    [--log_probs]
    [--gpu GPU]
    [--num_threads NUM_THREADS]

arguments:
  --input_files INPUT_FILES [INPUT_FILES ...]
    Time-varying categorical distribution files
  --output_files OUTPUT_FILES [OUTPUT_FILES ...]
    Files to save decoded indices

optional arguments:
  -h, --help
    show this help message and exit
  --transition_file TRANSITION_FILE
    Categorical transition matrix file; defaults to uniform
  --initial_file INITIAL_FILE
    Categorical initial distribution file; defaults to uniform
  --log_probs
    Whether inputs are in (natural) log space
  --gpu GPU
    GPU index to use for decoding. Defaults to CPU.
  --num_threads NUM_THREADS
    The number of threads to use for parellelized CPU decoding
```


## Evaluation

### Download

`python -m torbi.data.download`

Downloads and decompresses the `daps` and `vctk` datasets used for evaluation.


### Preprocess

`python -m torbi.data.preprocess --gpu 0`

Preprocess the dataset to prepare time-varying categorical distributions for
evaluation. The distributions are pitch posteriorgrams produced by the `penn`
pitch estimator.


### Partition

`python -m torbi.partition`

Select all examples in dataset for evaluation.


### Evaluate

```
python -m torbi.evaluate --config <config> --gpu <gpu>
```

Evaluates the accuracy and speed of decoding methods. `<gpu>` is the GPU index.


## Citation

### IEEE
M. Morrison, C. Churchwell, N. Pruyne, and B. Pardo, "Fine-Grained and Interpretable Neural Speech Editing," Interspeech, September 2024.


### BibTex

```
@inproceedings{morrison2024fine,
    title={Fine-Grained and Interpretable Neural Speech Editing},
    author={Morrison, Max and Churchwell, Cameron and Pruyne, Nathan and Pardo, Bryan},
    booktitle={Interspeech},
    month={September},
    year={2024}
}

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "torbi",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "decode, sequence, torch, Viterbi",
    "author": null,
    "author_email": "Cameron Churchwell <cameronchurchwell2024@u.northwestern.edu>, Max Morrison <maxrmorrison@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/c5/90/65f290474e499bd3c2fd61a7162cb229603f2fd41c77c2e08cc8cc376e06/torbi-1.3.3.tar.gz",
    "platform": null,
    "description": "<h1 align=\"center\">Viterbi decoding in PyTorch</h1>\n<div align=\"center\">\n\n[![PyPI](https://img.shields.io/pypi/v/torbi.svg)](https://pypi.python.org/pypi/torbi)\n[![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n[![Downloads](https://pepy.tech/badge/torbi)](https://pepy.tech/project/torbi)\n\n</div>\n\n\nHighly parallelizable Viterbi decoding for CPU or GPU compute. Below are time benchmarks of our method relative to `librosa.sequence.viterbi`. We use 1440 states and ~20 million timesteps over ~40k files for benchmarking.\n\n| Method  | Timesteps decoded per second |\n| ------------- | ------------- |\n| Librosa (1x cpu)| 208 |\n| Librosa (16x cpu)| 1,382* |\n| Proposed (1x cpu)| 171 |\n| Proposed (16x cpu)| **2,240** |\n| Proposed (1x a40 gpu, batch size 1)| **3,944,452** |\n| Proposed (1x a40 gpu, batch size 512)| **692,160,422** |\n\n*By default, `librosa.sequence.viterbi` uses one CPU thread. We use a Multiprocessing pool to parallelize.\n\n\n## Table of contents\n\n- [Installation](#installation)\n- [Decoding](#decoding)\n    * [Application programming interface](#application-programming-interface)\n        * [`torbi.from_probabilities`](#torbifrom_probabilities)\n        * [`torbi.from_file`](#torbifrom_file)\n        * [`torbi.from_file_to_file`](#torbifrom_file_to_file)\n        * [`torbi.from_files_to_files`](#torbifrom_files_to_files)\n    * [Command-line interface](#command-line-interface)\n- [Evaluation](#evaluation)\n    * [Download](#download)\n    * [Preprocess](#preprocess)\n    * [Partition](#partition)\n    * [Evaluate](#evaluate)\n- [Citation](#citation)\n\n\n## Installation\n\n```bash\ngit clone git@github.com:maxrmorrison/torbi\npip install torbi/\n```\n\nIf you receive an error message regarding mismatched CUDA versions, change the torch version in `pyproject.toml` to your currently installed version of `torch`.\n\nTo perform evaluation of the accuracy and speed of decoding methods, install `torbi` with the additional evaluation dependencies.\n\n`pip install torbi[evaluate]`\n\n\n## Decoding\n\n### Application programming interface\n\n```python\nimport torbi\nimport torch\n\n# Time-varying categorical distribution to decode\nobservation = torch.tensor([\n    [0.25, 0.5, 0.25],\n    [0.25, 0.25, 0.5],\n    [0.33, 0.33, 0.33]\n]).unsqueeze(dim=0)\n\n# Transition probabilities bewteen categories\ntransition = torch.tensor([\n    [0.5, 0.25, 0.25],\n    [0.33, 0.34, 0.33],\n    [0.25, 0.25, 0.5]\n])\n\n# Initial category probabilities\ninitial = torch.tensor([0.4, 0.35, 0.25])\n\n# Find optimal path using CPU compute\ntorbi.from_probabilities(\n   observation,\n   transition=transition,\n   initial=initial,\n   log_probs=False)\n\n# Find optimal path using GPU compute\ntorbi.from_probabilities(\n   observation,\n   transition=transition,\n   initial=initial,\n   log_probs=False,\n   gpu=0)\n```\n\n\n#### `torbi.from_probabilities`\n\n```python\ndef from_probabilities(\n    observation: torch.Tensor,\n    batch_frames: Optional[torch.Tensor] = None,\n    transition: Optional[torch.Tensor] = None,\n    initial: Optional[torch.Tensor] = None,\n    log_probs: bool = False,\n    gpu: Optional[int] = None,\n    num_threads: Optional[int] = 1\n) -> torch.Tensor:\n    \"\"\"Decode a time-varying categorical distribution\n\n    Arguments\n        observation\n            Time-varying categorical distribution\n            shape=(batch, frames, states)\n        batch_frames\n            Number of frames in each batch item; defaults to all\n            shape=(batch,)\n        transition\n            Categorical transition matrix; defaults to uniform\n            shape=(states, states)\n        initial\n            Categorical initial distribution; defaults to uniform\n            shape=(states,)\n        log_probs\n            Whether inputs are in (natural) log space\n        gpu\n            GPU index to use for decoding. Defaults to CPU.\n        num_threads\n            The number of threads to use for parallelized decoding\n\n    Returns\n        indices\n            The decoded bin indices\n            shape=(batch, frames)\n    \"\"\"\n```\n\n\n#### `torbi.from_file`\n\n```python\ndef from_file(\n    input_file: Union[str, os.PathLike],\n    transition_file: Optional[Union[str, os.PathLike]] = None,\n    initial_file: Optional[Union[str, os.PathLike]] = None,\n    log_probs: bool = False,\n    gpu: Optional[int] = None,\n    num_threads: Optional[int] = 1\n) -> torch.Tensor:\n    \"\"\"Decode a time-varying categorical distribution file\n\n    Arguments\n        input_file\n            Time-varying categorical distribution file\n            shape=(frames, states)\n        transition_file\n            Categorical transition matrix file; defaults to uniform\n            shape=(states, states)\n        initial_file\n            Categorical initial distribution file; defaults to uniform\n            shape=(states,)\n        log_probs\n            Whether inputs are in (natural) log space\n        gpu\n            GPU index to use for decoding. Defaults to CPU.\n        num_threads\n            The number of threads to use for parallelized decoding\n\n    Returns\n        indices\n            The decoded bin indices\n            shape=(frames,)\n    \"\"\"\n```\n\n\n#### `torbi.from_file_to_file`\n\n```python\ndef from_file_to_file(\n    input_file: Union[str, os.PathLike],\n    output_file: Union[str, os.PathLike],\n    transition_file: Optional[Union[str, os.PathLike]] = None,\n    initial_file: Optional[Union[str, os.PathLike]] = None,\n    log_probs: bool = False,\n    gpu: Optional[int] = None,\n    num_threads: Optional[int] = None\n) -> None:\n    \"\"\"Decode a time-varying categorical distribution file and save\n\n    Arguments\n        input_file\n            Time-varying categorical distribution file\n            shape=(frames, states)\n        output_file\n            File to save decoded indices\n        transition_file\n            Categorical transition matrix file; defaults to uniform\n            shape=(states, states)\n        initial_file\n            Categorical initial distribution file; defaults to uniform\n            shape=(states,)\n        log_probs\n            Whether inputs are in (natural) log space\n        gpu\n            GPU index to use for decoding. Defaults to CPU.\n        num_threads\n            The number of threads to use for parallelized decoding\n    \"\"\"\n```\n\n\n#### `torbi.from_files_to_files`\n\n```python\ndef from_files_to_files(\n    input_files: List[Union[str, os.PathLike]],\n    output_files: List[Union[str, os.PathLike]],\n    transition_file: Optional[Union[str, os.PathLike]] = None,\n    initial_file: Optional[Union[str, os.PathLike]] = None,\n    log_probs: bool = False,\n    gpu: Optional[int] = None,\n    num_threads: Optional[int] = None\n) -> None:\n    \"\"\"Decode time-varying categorical distribution files and save\n\n    Arguments\n        input_files\n            Time-varying categorical distribution files\n            shape=(frames, states)\n        output_files\n            Files to save decoded indices\n        transition_file\n            Categorical transition matrix file; defaults to uniform\n            shape=(states, states)\n        initial_file\n            Categorical initial distribution file; defaults to uniform\n            shape=(states,)\n        log_probs\n            Whether inputs are in (natural) log space\n        gpu\n            GPU index to use for decoding. Defaults to CPU.\n        num_threads\n            The number of threads to use for parallelized decoding\n    \"\"\"\n```\n\n\n### Command-line interface\n\n```\nusage: python -m torbi\n    [-h]\n    --input_files INPUT_FILES [INPUT_FILES ...]\n    --output_files OUTPUT_FILES [OUTPUT_FILES ...]\n    [--transition_file TRANSITION_FILE]\n    [--initial_file INITIAL_FILE]\n    [--log_probs]\n    [--gpu GPU]\n    [--num_threads NUM_THREADS]\n\narguments:\n  --input_files INPUT_FILES [INPUT_FILES ...]\n    Time-varying categorical distribution files\n  --output_files OUTPUT_FILES [OUTPUT_FILES ...]\n    Files to save decoded indices\n\noptional arguments:\n  -h, --help\n    show this help message and exit\n  --transition_file TRANSITION_FILE\n    Categorical transition matrix file; defaults to uniform\n  --initial_file INITIAL_FILE\n    Categorical initial distribution file; defaults to uniform\n  --log_probs\n    Whether inputs are in (natural) log space\n  --gpu GPU\n    GPU index to use for decoding. Defaults to CPU.\n  --num_threads NUM_THREADS\n    The number of threads to use for parellelized CPU decoding\n```\n\n\n## Evaluation\n\n### Download\n\n`python -m torbi.data.download`\n\nDownloads and decompresses the `daps` and `vctk` datasets used for evaluation.\n\n\n### Preprocess\n\n`python -m torbi.data.preprocess --gpu 0`\n\nPreprocess the dataset to prepare time-varying categorical distributions for\nevaluation. The distributions are pitch posteriorgrams produced by the `penn`\npitch estimator.\n\n\n### Partition\n\n`python -m torbi.partition`\n\nSelect all examples in dataset for evaluation.\n\n\n### Evaluate\n\n```\npython -m torbi.evaluate --config <config> --gpu <gpu>\n```\n\nEvaluates the accuracy and speed of decoding methods. `<gpu>` is the GPU index.\n\n\n## Citation\n\n### IEEE\nM. Morrison, C. Churchwell, N. Pruyne, and B. Pardo, \"Fine-Grained and Interpretable Neural Speech Editing,\" Interspeech, September 2024.\n\n\n### BibTex\n\n```\n@inproceedings{morrison2024fine,\n    title={Fine-Grained and Interpretable Neural Speech Editing},\n    author={Morrison, Max and Churchwell, Cameron and Pruyne, Nathan and Pardo, Bryan},\n    booktitle={Interspeech},\n    month={September},\n    year={2024}\n}\n",
    "bugtrack_url": null,
    "license": "MIT License",
    "summary": "Optimized Viterbi decoding and fast approximations",
    "version": "1.3.3",
    "project_urls": {
        "Homepage": "https://github.com/maxrmorrison/torbi",
        "Issues": "https://github.com/maxrmorrison/torbi/issues"
    },
    "split_keywords": [
        "decode",
        " sequence",
        " torch",
        " viterbi"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "c59065f290474e499bd3c2fd61a7162cb229603f2fd41c77c2e08cc8cc376e06",
                "md5": "fbb3594151d3913e387e893dd13c14a4",
                "sha256": "5873775dd1a43123f8b8b706eae0611bd30ac6924ba21b6dca5bf0bb70ba8e68"
            },
            "downloads": -1,
            "filename": "torbi-1.3.3.tar.gz",
            "has_sig": false,
            "md5_digest": "fbb3594151d3913e387e893dd13c14a4",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 95060,
            "upload_time": "2025-09-01T19:25:09",
            "upload_time_iso_8601": "2025-09-01T19:25:09.727149Z",
            "url": "https://files.pythonhosted.org/packages/c5/90/65f290474e499bd3c2fd61a7162cb229603f2fd41c77c2e08cc8cc376e06/torbi-1.3.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-01 19:25:09",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "maxrmorrison",
    "github_project": "torbi",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "torbi"
}
        
Elapsed time: 3.47068s