Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
El paquete System.Numerics.Tensors proporciona Tensor<T>, TensorSpan<T>y ReadOnlyTensorSpan<T> para datos multidimensionales. Las formas de los tensores describen las dimensiones lógicas; los strides describen la distancia, en elementos, entre posiciones sucesivas a lo largo de cada dimensión.
El comportamiento aquí descrito se incluye en el paquete en todos sus marcos de destino compatibles. La actualización del paquete puede afectar a las aplicaciones que tienen como destino versiones anteriores de .NET.
Estos tipos comparten muchas convenciones con NumPy, pero no son intercambiables. Tenga en cuenta las siguientes diferencias al portar un algoritmo.
Formas vacías y resultados escalares
Cuando se crea un tensor a partir de una forma vacía ([]) sin datos de respaldo, el tensor tiene forma [0] y ningún elemento. En NumPy, la shape () tiene rango cero y contiene un elemento escalar. En concreto, np.empty(()) asigna un escalar con un valor no inicializado; "vacío" no significa que no tenga elementos.
Por el contrario, cuando se omiten longitudes de un constructor de tensor-span sobre los datos existentes, el constructor deduce una forma unidimensional del array o span proporcionados.
Al comprimir un tensor con forma [1, 1], el resultado tiene la forma [1], no la forma de rango cero de NumPy (). Ambos resultados contienen un elemento y pueden difundirse como un escalar, pero el código que examina el rango, selecciona ejes o indiza el resultado debe tener en cuenta la dimensión conservada.
Cuando se omiten los pasos, cualquier forma que contenga una dimensión de longitud cero tiene cero pasos en cada dimensión. Su recuento de elementos y el almacenamiento necesario son cero, independientemente de las otras longitudes de dimensión. Las longitudes negativas no son válidas. Las strides explícitas aún deben cumplir la validación del diseño.
Strides y datos invertidos
Los pasos deben ser no negativos. NumPy puede representar una vista invertida con un paso negativo, por ejemplo array[::-1].
Para invertir el primer eje, llame a Tensor.ReverseDimension con la dimensión 0:
using System.Numerics.Tensors;
Tensor<int> source = Tensor.Create(new[] { 1, 2, 3, 4 }, new nint[] { 2, 2 });
Tensor<int> reversed = Tensor.ReverseDimension<int>(source.AsReadOnlyTensorSpan(), 0);
Los elementos lógicos de reversed son [3, 4, 1, 2]. La sobrecarga de asignación genera un nuevo tensor; no es una vista de paso negativo sobre el almacenamiento original.
Cambiar el tamaño de un tensor
Tensor.Resize y Tensor.ResizeTo rellenan los elementos lógicos agregados con default(T). Por ejemplo, si crece [1, 2] hasta cinco elementos int, el resultado contiene [1, 2, 0, 0, 0]. En su lugar, np.resize de NumPy repite la entrada y produce [1, 2, 1, 2, 1].
Si el destino es más pequeño, la operación descarta los elementos después del recuento de elementos lógicos del destino. Si es mayor, la operación inicializa los elementos de destino lógicos restantes incluso cuando el destino tiene huecos entre elementos. El almacenamiento fuera del destino lógico no forma parte de la operación de cambio de tamaño.
Tensor.ResizeTo y la concatenación en un destino existente rechazan una dimensión de paso cero que contiene más de un elemento lógico. Esta dimensión hace que varias posiciones de salida hagan referencia al mismo almacenamiento y no puede contener valores de salida distintos. Los pasos cero en las dimensiones singleton y los destinos vacíos no crean este conflicto.
Orígenes y destinos superpuestos
Los objetos tensor independientes y los segmentos pueden hacer referencia a regiones superpuestas del mismo array. Los casos admitidos dependen de la operación y de la disposición:
| Operation | Superposición admitida |
|---|---|
CopyTo y TryCopyTo |
Origen y destino densos con recuentos de elementos iguales o con vistas exactamente idénticas. Las copias densas utilizan copia de span segura ante superposición. |
FlattenTo y TryFlattenTo |
Un origen denso y el span de destino. |
| Operaciones elementwise con un destino | Una entrada y una salida con la misma referencia inicial, longitudes y strides, siempre que la vista no tenga ubicaciones de almacenamiento lógicas repetidas. Cada entrada se comprueba de forma independiente. |
Tensor.ResizeTo |
Origen y destino densos. Se rechaza la superposición con stride no admitida. |
| Reversión en la misma vista | Se puede invertir una vista densa sin crear una copia. También se admiten reversiones no-op. |
Otros diseños superpuestos no admitidos generan ArgumentException antes de que la operación escriba la salida. Un tensor denso por sí solo no garantiza la compatibilidad con cada operación: por ejemplo, se admite un destino denso desplazado para una copia, pero no para una operación elementwise.
Los métodos TryCopyTo y TryFlattenTo devuelven false sin copiar cuando el destino es demasiado corto.
TryCopyTo también devuelve false para las formas de origen y destino incompatibles. Para formas compatibles con capacidad de destino suficiente, estos métodos aún pueden producir excepciones ante superposiciones no admitidas; Try no suprime las excepciones de diseño no válido.
Por ejemplo, el siguiente origen de stride y destino denso se superponen:
int[] storage = { 1, 2, 3, 4, 5, 6 };
ReadOnlyTensorSpan<int> source = new(storage, new nint[] { 2, 2 }, new nint[] { 3, 1 });
TensorSpan<int> destination = new(storage, new nint[] { 2, 2 });
Para copiar desde este diseño superpuesto no admitido, primero tome una instantánea en almacenamiento independiente:
int[] snapshot = new int[checked((int)source.FlattenedLength)];
source.FlattenTo(snapshot);
ReadOnlyTensorSpan<int> independentSource = new(snapshot, source.Lengths);
independentSource.CopyTo(destination);
La instantánea contiene [1, 2, 4, 5]. La copia escribe esos elementos en el destino sin cambiar los valores originales antes de que se lean.
Para una operación elemento a elemento con destino, asigne un tensor de resultado independiente o una instantánea de cada entrada superpuesta antes de escribir la salida. Para un destino de difusión con ubicaciones de almacenamiento repetidas, use almacenamiento de salida independiente en su lugar; Una instantánea de entrada no hace que ese destino sea capaz de contener valores distintos.
La biblioteca no asigna implícitamente una instantánea de tensor completa para admitir diseños superpuestos arbitrarios. Las copias no superpuestas con stride no requieren ese almacenamiento temporal.