Sémantique de diffusion
De nombreuses opérations PyTorch prennent en charge la sémantique de diffusion de NumPy.
En résumé, si une opération PyTorch prend en charge la diffusion, ses paramètres Tensor peuvent être automatiquement étendus pour atteindre des tailles égales (sans copier les données).
Sémantique générale
Deux tenseurs sont «diffusables» si les règles suivantes sont respectées :
- Chaque tenseur possède au moins une dimension.
- Lors de l'itération sur les tailles de dimension, en commençant par la dimension finale, les tailles de dimension doivent être égales, l'une d'elles doit être égale à 1 ou l'une d'elles doit être inexistante.
Par exemple :
|
>>> x=torch.empty(5,7,3) >>> y=torch.empty(5,7,3) # les mêmes formes sont toujours diffusables (c'est-à-dire que les règles ci-dessus s'appliquent toujours) >>> x=torch.empty((0,)) >>> y=torch.empty(2,2) # x et y ne sont pas diffusables, car x n'a pas au moins 1 dimension # peut aligner les dimensions de fuite >>> x=torch.empty(5,3,4,1) >>> y=torch.empty( 3,1,1) # x et y sont diffusables. # 1re dimension finale : les deux ont une taille de 1 # 2e dimension finale : y a une taille de 1 # 3e dimension finale : la taille de x est égale à la taille de y # 4e dimension finale : la dimension y n'existe pas # mais: >>> x=torch.empty(5,2,4,1) >>> y=torch.empty( 3,1,1) # x et y ne sont pas diffusables, car dans la 3ème dimension de fuite 2 != 3 |
Si deux tenseurs x et y sont «diffusables», la taille du tenseur résultant est calculée comme suit :
- Si le nombre de dimensions de x et y n'est pas égal, ajoutez 1 au début des dimensions du tenseur ayant le moins de dimensions pour les rendre de même longueur.
- Ensuite, pour chaque taille de dimension, la taille résultante est la valeur maximale des tailles de x et y le long de cette dimension.
Par exemple :
|
# peut aligner les dimensions de fuite pour faciliter la lecture >>> x=torch.empty(5,1,4,1) >>> y=torch.empty( 3,1,1) >>> (x+y).size() torch.Size([5, 3, 4, 1]) # mais pas nécessaire : >>> x=torch.empty(1) >>> y=torch.empty(3,1,7) >>> (x+y).size() torch.Size([3, 1, 7]) >>> x=torch.empty(5,2,4,1) >>> y=torch.empty(3,1,1) >>> (x+y).size() RuntimeError: The size of tensor a (2) must match the size of tensor b (3) at non-singleton dimension 1 |
Sémantique in-situ
Une complication réside dans le fait que les opérations in-situ empêchent le tenseur in-situ de changer de forme suite à la diffusion.
Par exemple :
|
>>> x=torch.empty(5,3,4,1) >>> y=torch.empty(3,1,1) >>> (x.add_(y)).size() torch.Size([5, 3, 4, 1]) # mais : >>> x=torch.empty(1,3,1) >>> y=torch.empty(3,1,7) >>> (x.add_(y)).size() RuntimeError: The expanded size of the tensor (1) must match the existing size (7) at non-singleton dimension 2. |
Rétrocompatibilité
Les versions précédentes de PyTorch permettaient l'exécution de certaines fonctions ponctuelles sur des tenseurs de formes différentes, à condition que le nombre d'éléments de chaque tenseur soit égal. L'opération ponctuelle était alors réalisée en considérant chaque tenseur comme unidimensionnel. PyTorch prend désormais en charge la diffusion (diffusion) et le comportement ponctuel unidimensionnel est considéré comme obsolète et génère un avertissement Python si les tenseurs ne sont pas diffusables, mais ont le même nombre d'éléments.
Notez que l'introduction de la diffusion peut entraîner des modifications rétrocompatibles lorsque deux tenseurs n'ont pas la même forme, mais sont diffusables et ont le même nombre d'éléments. Par exemple :
| >>> torch.add(torch.ones(4,1), torch.randn(4)) |
Auparavant, un Tensor de taille torch.Size([4,1]) était généré, mais il en produit désormais un autre de taille torch.Size([4,4]). Afin d'identifier les cas dans votre code où des incompatibilités rétroactives introduites par la diffusion pourraient exister, vous pouvez définir torch.utils.backcompat.broadcast_warning.enabled sur True, ce qui générera un avertissement Python dans ces cas.
Par exemple :
|
>>> torch.utils.backcompat.broadcast_warning.enabled=True >>> torch.add(torch.ones(4,1), torch.ones(4)) __main__:1: UserWarning: self and other do not have the same shape, but are broadcastable, and have the same number of elements. Changing behavior in a backwards incompatible manner to broadcasting rather than viewing as 1-dimensional. |