# Get started with the OPU¶

There are three ways to process data with an OPU: - `lightonml`

with `numpy.ndarray`

- `lightonml`

with `torch.Tensor`

- `lightonopu`

with `numpy.ndarray`

or `torch.Tensor`

```
[1]:
```

```
import numpy as np
import torch
```

## Lightonml with numpy arrays¶

There is an `OPUMap`

class in `lightonml.projections.sklearn`

that can process `numpy.ndarray`

s and is built to be scikit-learn compatible: it can be embedded in pipelines, cross-validated, etc.

```
[2]:
```

```
from lightonml.projections.sklearn import OPUMap
```

```
[3]:
```

```
numpy_data = np.random.randint(0, 2, size=(3000, 10000), dtype=np.uint8)
opumap_np = OPUMap(n_components=10000)
```

```
[4]:
```

```
output = opumap_np.transform(numpy_data)
output
```

```
[4]:
```

```
array([[ 29, 26, 5, ..., 21, 52, 98],
[ 37, 12, 30, ..., 90, 109, 86],
[ 10, 3, 9, ..., 36, 69, 71],
...,
[ 67, 21, 13, ..., 21, 65, 37],
[ 42, 10, 23, ..., 55, 110, 87],
[ 69, 26, 9, ..., 106, 89, 132]], dtype=uint8)
```

Since we are going to use a different object to “talk” with the OPU, we have to release the resource.

```
[5]:
```

```
opumap_np.opu.close()
```

## Lightonml with torch tensors¶

A second `OPUMap`

interface is available in `lightonml.projections.torch`

. In this case `OPUMap`

behaves as a `torch.nn.Module`

: the object can be called on data. Alternatively, it is still possible to call `.transform`

.

Note that the optical processing is not differentiable, so this operation will break the computational graph: gradients are not propagated through the `.transform`

method.

```
[6]:
```

```
from lightonml.projections.torch import OPUMap
```

```
[7]:
```

```
torch_data = torch.randint(0, 2, size=(3000, 10000), dtype=torch.uint8)
opumap_torch = OPUMap(n_components=10000)
```

```
OPU output is detached from the computational graph.
```

```
[8]:
```

```
output = opumap_torch.transform(torch_data)
output
```

```
[8]:
```

```
tensor([[ 6, 3, 5, ..., 10, 45, 79],
[ 28, 52, 17, ..., 22, 74, 170],
[ 10, 40, 38, ..., 27, 30, 52],
...,
[ 36, 12, 4, ..., 24, 54, 96],
[ 19, 37, 39, ..., 17, 130, 163],
[ 10, 5, 13, ..., 49, 94, 111]], dtype=torch.uint8)
```

```
[9]:
```

```
output = opumap_torch(torch_data)
output
```

```
[9]:
```

```
tensor([[ 5, 3, 6, ..., 9, 44, 78],
[ 27, 52, 18, ..., 23, 73, 168],
[ 13, 42, 37, ..., 25, 29, 51],
...,
[ 32, 12, 5, ..., 23, 56, 105],
[ 17, 34, 37, ..., 17, 137, 171],
[ 13, 4, 17, ..., 55, 104, 119]], dtype=torch.uint8)
```

```
[10]:
```

```
opumap_torch.opu.close()
```

## Lightonopu with numpy arrays or torch tensors¶

A lower-level class is `lightonopu.OPU`

, used internally in `OPUMap`

classes. This class does not offer fancy features for compatibility with third-party frameworks, but it is more versatile and can accept both `numpy.ndarray`

and `torch.Tensor`

.

In the case of `OPU`

, the user needs to call `.transform1d`

if the input data is a collection of vectors, or `.transform2d`

if it is a collection of matrices.

In `OPUMap`

classes, `.transform`

automatically dispatches to `.transform1d`

or `.transform2d`

.

```
[11]:
```

```
from lightonopu import OPU
```

```
[12]:
```

```
opu = OPU(n_components=10000)
```

```
[13]:
```

```
y_np = opu.transform1d(numpy_data)
y_np
```

```
[13]:
```

```
array([[ 26, 25, 5, ..., 19, 49, 98],
[ 37, 13, 27, ..., 90, 110, 83],
[ 13, 4, 9, ..., 35, 66, 71],
...,
[ 75, 23, 14, ..., 21, 60, 38],
[ 43, 10, 22, ..., 51, 107, 81],
[ 71, 27, 9, ..., 91, 86, 125]], dtype=uint8)
```

```
[14]:
```

```
y_torch = opu.transform1d(torch_data)
y_torch
```

```
[14]:
```

```
tensor([[ 6, 2, 5, ..., 9, 43, 77],
[ 27, 51, 18, ..., 25, 73, 164],
[ 11, 40, 39, ..., 25, 28, 49],
...,
[ 34, 12, 4, ..., 23, 56, 94],
[ 19, 35, 38, ..., 16, 129, 165],
[ 11, 5, 15, ..., 51, 97, 113]], dtype=torch.uint8)
```

```
[15]:
```

```
data_2d = np.random.randint(0, 2, size=(3000, 900, 900), dtype=np.uint8)
y = opu.transform2d(data_2d)
y
```

```
[15]:
```

```
array([[ 95, 59, 39, ..., 75, 95, 134],
[ 37, 13, 63, ..., 26, 90, 114],
[ 17, 7, 40, ..., 68, 179, 179],
...,
[ 64, 26, 37, ..., 47, 137, 67],
[ 86, 47, 42, ..., 31, 81, 97],
[ 18, 21, 30, ..., 51, 46, 46]], dtype=uint8)
```