Metadata-Version: 2.4
Name: fasttransform
Version: 0.0.5
Summary: Transform is the main building block of data pipelines in fastai. And elsewhere if you want.
Author-email: Jeremy Howard and Rens Dimmendaal and Alexis Gallagher <info@fast.ai>
License: Apache-2.0
Project-URL: Repository, https://github.com/AnswerDotAI/fasttransform
Project-URL: Documentation, https://AnswerDotAI.github.io/fasttransform
Keywords: nbdev,jupyter,notebook,python
Classifier: Natural Language :: English
Classifier: Intended Audience :: Developers
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastcore>=2.2.22
Requires-Dist: plum-dispatch<2.10
Provides-Extra: dev
Requires-Dist: matplotlib; extra == "dev"
Requires-Dist: numpy; extra == "dev"
Requires-Dist: pandas; extra == "dev"
Dynamic: license-file

# Welcome to fasttransform


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

`fasttransform` provides reusable data transformations and pipelines. It is the main building block of fastai’s data pipelines and can also be used independently. A [`Transform`](https://AnswerDotAI.github.io/fasttransform/transform.html#transform) combines a function with optional inverse, setup, and type-handling behaviour. A [`Pipeline`](https://AnswerDotAI.github.io/fasttransform/transform.html#pipeline) composes transforms.

## Installation

Install latest from the GitHub [repository](https://github.com/AnswerDotAI/fasttransform):

``` sh
$ pip install git+https://github.com/AnswerDotAI/fasttransform.git
```

or from [pypi](https://pypi.org/project/fasttransform/):

``` sh
$ pip install fasttransform
```

## Quick start

### Transform

Create a [`Transform`](https://AnswerDotAI.github.io/fasttransform/transform.html#transform) by passing a function to its constructor or using it as a decorator. The function becomes the transform’s `encodes` method.

A transform supports:

- Reversibility: keep a function and its inverse in one object.
- Setup: configure a transform instance using the dataset.
- Type-based multiple dispatch: select a function based on argument types.
- Type conversion and preservation: control the result’s type, including subclasses.

To create a transform with a decorator:

``` python
from fasttransform import Transform, Pipeline
```

``` python
@Transform
def add_one(x): 
    return x + 1

# Usage
add_one(2)
```

    3

### Reversibility

Pass a function and its inverse to make a transform reversible. Use this to normalize and de-normalize numerical values, or to encode categories as indices and decode them again:

``` python
def enc(x): return x*2
def dec(x): return x//2

t = Transform(enc,dec)

t(2), t.decode(2), t.decode(t(2))
```

    (4, 1, 2)

### Setup

A transform’s `setups` method can calculate properties from a dataset. This z-score normalization transform stores the mean and standard deviation. Its `encodes` and `decodes` methods use those values:

``` python
import statistics

class NormalizeMean(Transform):
    def setups(self, items): 
        self.mean = statistics.mean(items)
        self.std  = statistics.stdev(items)
    
    def encodes(self, x): 
        return (x - self.mean) / self.std
    
    def decodes(self, x): 
        return x * self.std + self.mean

normalize = NormalizeMean()
normalize.setup([1, 2, 3, 4, 5])
normalize.mean
```

    3

### Type-based multiple dispatch

Pass multiple functions with different parameter annotations to select behaviour by input type. This is useful for handling different image formats or numerical types in one transform.

This transform selects a function for an `int` or a `str`:

``` python
def inc1(x:int): return x+1
def inc2(x:str): return x+"a"

t = Transform(enc=(inc1,inc2))

t(5), t('b')
```

    (6, 'ba')

When no type annotation matches an input, the transform returns that input unchanged.

``` python
add_one(2.0)
```

    3.0

``` python
normalize(3.0)
```

    0.0

### Type conversion and preservation

[`Transform`](https://AnswerDotAI.github.io/fasttransform/transform.html#transform) uses the wrapped function’s return type to control conversion in `encodes` and `decodes`. The return type can be explicit or implicit. The rules are:

1.  The result has the function’s return type, with conversion when needed.
2.  When the input’s runtime type is a subtype of that return type, the result preserves the input’s type.
3.  A return annotation of `None` disables type conversion and preservation.

#### Return type

`FS` is a subclass of `float`. Normal Python multiplication of an `FS` and a `float` returns a `float`:

``` python
class FS(float):
    def __repr__(self): return f'FS({float(self)})'
 

f1 = float(1)
FS2 = FS(2)

val = f1 * FS2
type(val) # => float
```

    float

With [`Transform`](https://AnswerDotAI.github.io/fasttransform/transform.html#transform), an `FS` return annotation makes the multiplication return an `FS`:

``` python
def double_FS(x)->FS: return FS(2)*x
t = Transform(double_FS)
val = t(1) 
assert isinstance(val,FS)
val
```

    FS(2.0)

#### Type preservation

Without a return annotation, this multiplication transform preserves the input’s runtime type. Passing an `FS` returns an `FS`. The wrapped function alone would return a `float`:

``` python
def double(x): return x*2.0  # no type annotation
t = Transform(double)
fs1 = FS(1)
val = t(fs1)
assert isinstance(val,FS)
val # => FS(2), an FS value of 2
```

    FS(2.0)

#### Disabling conversion

Use a return annotation of `None` to disable type conversion and preservation:

``` python
def double_none(x) -> None: return x*2.0  # "None" returnt type means "no conversion"
t = Transform(double_none)
fs1 = FS(1)
val = t(fs1)
assert isinstance(val,float)
val # => 2.0, a float of 2, because of fallback to standard Python type logic
```

    2.0

### Pipelines

A [`Pipeline`](https://AnswerDotAI.github.io/fasttransform/transform.html#pipeline) applies transforms in sequence. This pipeline doubles a value and then normalizes it. `decode` reverses the transformations:

``` python
def double(x): return x*2.0 
def halve(x): return x/2.0
dt = Transform(double,halve)

class NormalizeMean(Transform):
    def setups(self, items): 
        self.mean = statistics.mean(items)
        self.std  = statistics.stdev(items)
    
    def encodes(self, x):
        return (x - self.mean) / self.std
    
    def decodes(self, x):
        return x * self.std + self.mean

normalize = NormalizeMean()
normalize.setup([1, 2, 3, 4, 5])

p = Pipeline((dt, normalize))

v = p(5)
v
```

    4.427188724235731

``` python
p.decode(v)
```

    5.0

### Documentation

See the [documentation](https://answerdotai.github.io/fasttransform/) for the full API.
