# MLArrayFeature

This is a multidimensional array feature, a.k.a a tensor. Most models which accept tensors will accept an array feature in NatML.

{% hint style="info" %}
The array data type `T` is always [`unmanaged`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/unmanaged-types).
{% endhint %}

{% hint style="success" %}
Array features are always views of a pre-allocated array or buffer. As such, creating an array feature will never allocate tensor memory.
{% endhint %}

## Creating the Feature

The array feature can be created from any numeric array or buffer representation:

### From a Managed Array

```csharp
/// <summary>
/// Create an array feature.
/// </summary>
/// <param name="data">Feature data.</param>
/// <param name="shape">Feature shape.</param>
MLArrayFeature (T[] data, int[] shape = null);
```

An array feature can be created from a managed array. In rare cases where it is useful to fully specify the feature type, there is an overload which accepts the array type:

```csharp
/// <summary>
/// Create an array feature.
/// </summary>
/// <param name="data">Feature data.</param>
/// <param name="type">Feature type.</param>
MLArrayFeature (T[] data, MLArrayType type);
```

### From a Native Array

The array feature provides variants of the managed array constructors where the `data` argument is a [`NativeArray<T>`](https://docs.unity3d.com/ScriptReference/Unity.Collections.NativeArray_1.html). This can be useful for working with certain performance-critical Unity API's like Burst:

```csharp
/// <summary>
/// Create an array feature.
/// </summary>
/// <param name="data">Feature data.</param>
/// <param name="shape">Feature shape.</param>
MLArrayFeature (NativeArray<T> data, int[] shape = null);
```

Similarly, in cases where it is necessary to explicitly specify the array feature type, there is a corresponding overload:

```csharp
/// <summary>
/// Create an array feature.
/// </summary>
/// <param name="data">Feature data.</param>
/// <param name="type">Feature type.</param>
MLArrayFeature (NativeArray<T> data, MLArrayType type);
```

### From a Native Buffer

The array feature provides variants of the managed array constructors where the `data` argument is a typed native buffer. These can be useful for making predictions on arrays from native code or external libraries like OpenCV:

```csharp
/// <summary>
/// Create an array feature.
/// </summary>
/// <param name="data">Feature data.</param>
/// <param name="shape">Feature shape.</param>
MLArrayFeature (T* data, int[] shape = null);
```

There is a corresponding constructor for specifying the feature type:

```csharp
/// <summary>
/// Create an array feature.
/// </summary>
/// <param name="data">Feature data.</param>
/// <param name="type">Feature type.</param>
MLArrayFeature (T* data, MLArrayType type);
```

{% hint style="warning" %}
The `data` buffer MUST remain valid for the lifetime of the array feature.
{% endhint %}

### From an Edge Feature

```csharp
/// <summary>
/// Create an array feature from an Edge ML feature.
/// Note that this does NOT take ownership of the edge feature.
/// As such the edge feature must be explicitly disposed by the client.
/// </summary>
/// <param name="feature">Edge ML feature. This MUST be an array feature.</param>
MLArrayFeature (MLEdgeFeature feature);
```

An array feature can be created from an `MLEdgeFeature`. This is useful for making predictions with an [`MLEdgeModel`](/unity/api/mlmodel/mledgemodel.md) .

{% hint style="warning" %}
The `feature` MUST have a numeric data type.
{% endhint %}

### From a Cloud Feature

```csharp
/// <summary>
/// Create an array feature from a cloud feature.
/// </summary>
/// <param name="feature">Cloud feature.</param>
MLArrayFeature (MLCloudFeature feature);
```

The array feature can be created from an `MLCloudFeature`. This is useful for making predictions with an [`MLCloudModel`](/unity/api/mlmodel/mlcloudmodel.md) .

{% hint style="warning" %}
The `feature` MUST have a numeric data type.
{% endhint %}

## Inspecting the Feature

The array feature provides information about its shape.

### Feature Type

```csharp
/// <summary>
/// Feature type.
/// </summary>
MLFeatureType type { get; }
```

Refer to the [Inspecting the Feature](/unity/api/mlfeature.md#inspecting-the-feature) section of the `MLFeature` class for more information.

{% hint style="info" %}
The `type` is always an [`MLArrayType`](/unity/api/mlfeaturetype/mlarraytype.md).
{% endhint %}

### Feature Shape

```csharp
/// <summary>
/// Feature shape.
/// </summary>
int[] shape { get; }
```

The feature shape is a convenience property which provides the shape from the feature `type`.

{% hint style="warning" %}
The `shape` can be `null` if the feature was created with no shape.
{% endhint %}

### Element Count

```csharp
/// <summary>
/// Feature element count.
/// </summary>
int elementCount { get; }
```

The element count is a convenience property which provides the element count from the feature `type`.

{% hint style="warning" %}
The `elementCount` will be zero when the feature does not have a `shape`.
{% endhint %}

## Accessing Feature Data

The array feature provides accessors for reading and writing feature data.

### Multi-Indexing

```csharp
/// <summary>
/// Get or set a value at a specified multi-index.
/// </summary>
/// <param name="idx">Multi-index.</param>
T this [params int[] idx] { get; set; }
```

The array feature provides support for multi-indexing. This is a common pattern for working with tensors in machine learning:

```csharp
// With an array feature
var feature = new MLArrayFeature<float>(...);
// You can index across multiple dimensions
var logit = feature[0,12,29,1];
```

{% hint style="info" %}
Multiple indexing requires the array feature to have a valid `shape`, but linear indexing (i.e. indexing with a single number) does not.
{% endhint %}

{% hint style="warning" %}
The array feature does not perform bounds checking for performance, so make sure to always index correctly.
{% endhint %}

The array feature also supports linear indexing, in which case it accesses the elements of the feature assuming a flat shape:

```csharp
// You can also index linearly, disregarding the shape
var logit = feature[392];
```

### Copying

```csharp
/// <summary>
/// Copy the array feature into another feature.
/// This copies `destination.elementCount * sizeof(U)` elements.
/// </summary>
/// <param name="destination">Feature to copy data into.</destination>
void CopyTo<U> (MLArrayFeature<U> destination) where U : unmanaged;
```

The array feature can copy it data into another array feature.

{% hint style="info" %}
This method copies `destination.elementCount * sizeof(U)` bytes into the `destination` feature.
{% endhint %}

{% hint style="warning" %}
This method does not respect any permutations that have been applied to the array feature.
{% endhint %}

{% hint style="success" %}
To copy data into a managed array, native buffer, or other destination, first create an `MLArrayFeature` to wrap the destination, then use the `CopyTo` method.
{% endhint %}

### Converting to Array

```csharp
/// <summary>
/// Convert the array feature to a flattened array.
/// </summary>
/// <returns>Result array.</returns>
 T[] ToArray ();
```

The array feature can copy its data into an array and return the array. The destination array type can also be specified:

```csharp
/// <summary>
/// Convert the array feature to a flattened array.
/// This method always returns a copy of the array feature data.
/// </summary>
/// <returns>Result array.</returns>
U[] ToArray<U> () where U : unmanaged;
```

{% hint style="warning" %}
This method does not respect any permutations that have been applied to the array feature.
{% endhint %}

### Pinning

```csharp
/// <summary>
/// Pin the array feature.
/// </summary>
ref T GetPinnableReference ();
```

The array feature supports pinning, allowing direct access to the underlying feature data while bypassing all checks. This can be used in `unsafe` context with the `fixed` statement:

```csharp
// Given an array feature
MLArrayFeature<float> feature = ...;
// Manually set the 12th element in the feature by pinning
fixed (float* featureData = feature)
    featureData[11] = 420.69;
```

{% hint style="success" %}
Pinning is mostly used for bulk read or write operations. Use multi-indexing for individual element access.
{% endhint %}

{% hint style="danger" %}
Do not use pinning unless you know exactly what you are doing. Mistakes are almost guaranteed to result in segmentation faults and hard crashes.
{% endhint %}

## Viewing Operations

The array feature supports viewing operations. Each of these operations do not allocate any memory; they simply return a shallow feature that has the proper shape.

### Permute

```csharp
/// <summary>
/// Permute the dimensions of this array feature.
/// This operation is a generalization of the transpose operation.
/// </summary>
/// <param name="dims">Permuted dimensions.</param>
/// <returns>Array feature with permuted dimensions.</returns>
MLArrayFeature<T> Permute (params int[] dims);
```

The array feature's dimensions can be permuted, allowing different dimensions to be swapped (like transposing):

```csharp
// Create an array feature with shape (3,5)
var feature = new MLArrayFeature<float>(..., new [] { 3, 5 });
Debug.Log(feature.shape);              // (3,5)
// Transpose it by permuting dimensions
var transposedFeature = feature.Permute(1, 0);
Debug.Log(transposedFeature.shape);    // (5,3)
```

### View

```csharp
/// <summary>
/// Create a view of this array feature with a different shape.
/// The element count of the new shape MUST match that of the feature.
/// </summary>
/// <param name="shape">New shape.</param>
/// <returns>Array feature with new shape.</returns>
MLArrayFeature<T> View (params int[] shape);
```

The array feature supports creating a view of the feature data with a different shape:

```csharp
// Create an array feature
var feature = new MLArrayFeature<float>(..., new [] { 5, 30 });
Debug.Log(feature.shape);          // (5,30)
// View the feature with a different shape
var viewedFeature = feature.View(5, 10, 3); 
Debug.Log(viewedFeature.shape);    // (5,10,3)
```

{% hint style="warning" %}
The element count of the view shape **must** match the element count of the feature.
{% endhint %}

## Creating an Edge Feature

```csharp
/// <summary>
/// Create an edge feature that is ready for prediction with edge models.
/// </summary>
/// <param name="type">Feature type used to create the edge feature.</param>
/// <returns>Edge feature.</returns>
MLEdgeFeature IMLEdgeFeature.Create (MLFeatureType type);
```

INCOMPLETE.

## Creating a Cloud Feature

<pre class="language-csharp"><code class="lang-csharp">/// &#x3C;summary>
/// Create a cloud feature that is ready for prediction with cloud models.
/// &#x3C;/summary>
/// &#x3C;param name="type">Feature type used to create the cloud feature.&#x3C;/param>
/// &#x3C;returns>Cloud feature.&#x3C;/returns>
<strong>MLCloudFeature IMLCloudFeature.Create (MLFeatureType type)
</strong></code></pre>

INCOMPLETE.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.natml.ai/unity/api/mlfeature/mlarrayfeature.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
