numpy type 和 tensor type 二元运算类型转换问题
问题来源:
https://github.com/Oneflow-Inc/OneCloud/issues/141#issuecomment-1203781305 https://github.com/Oneflow-Inc/OneCloud/issues/141#issuecomment-1203912725
最小复现代码:
import oneflow as flow
import numpy as np
a=np.array([1,2]).astype(np.double)[0]
b=flow.randn(10)
c= a + b
print(type(c))
import torch
a=np.array([1,2]).astype(np.double)[0]
b=torch.randn(10)
c= a + b
print(type(c))
上面代码的输出结果:

从上面来看,在 oneflow 里, numpy.float64 和 tensor 做二元运算,类型会被强转为 numpy.ndarray,而 torch 转为 tensor。
np.array([1,2]).astype(np.double)[0] 是 numpy.float64 类型,所以没有调用 ScalarAdd2Functor。
是的,其他numpy类型是可以被转换为Tensor
是的,其他numpy类型是可以被转换为Tensor
也不是这样的,总结了下:
oneflow 当前与 torch 没对齐的地方有下面两点:
- 我们以
c = a + b为例,假设 a 为 numpy.xx 类型(实际上必须一个 “scalar”,如果一个 numpy 数组和 tensor 二元运算,在 torch 上是不支持的,oneflow 支持),b 为 oneflow.tensor,那么在 oneflow 上,计算结果的 type 是 numpy.ndarray,在 torch 上则是一个 tensor。 - 当
c = b + a的情况,b 还是 oneflow.tensor,a 还是 numpy.xx 类型,在常规情况下(这里调用 scalaradd 算子,上面那种情况调用 ScalarAdd2)。这种情况下 torch 支持 a 为各种类型,比如 numpy.int,而 oneflow 则会报下面的已知问题:
。因为 oneflow 只能把 numpy.float64 、long 和 bool 转换为 scalar。
好的学到了
这里分 case 详细讨论一下这个问题:
- 第一种:a 是 numpy.xx type,b 是 tensor,做 b+a。
import oneflow as flow
import numpy as np
a=np.array([1]).astype(np.double)[0]
print(type(a))
b=flow.randn(1)
c= b + a
print(type(c))
import torch
import numpy as np
a=np.array([1]).astype(np.double)[0]
print(type(a))
b=torch.randn(1)
c= b + a
print(type(c))
这时 oneflow 和 torch 是对齐的。
- 第二种:a 是 numpy.float64 type,b 是 tensor,做 a+b。
import oneflow as flow
import numpy as np
a=np.array([1]).astype(np.double)[0]
print(type(a))
b=flow.randn(1)
c= a + b
print(type(c))
import torch
import numpy as np
a=np.array([1]).astype(np.double)[0]
print(type(a))
b=torch.randn(1)
c= a + b
print(type(c))
这时 print(type(c)),oneflow 的输出为 numpy.ndarray,而 torch 是个 tensor,也就是这个 issue 的来源。
- 第三种:a 是 numpy.int type,b 是 tensor,做 b+a。
import oneflow as flow
import numpy as np
a=np.array([1]).astype(np.int)[0]
print(type(a))
b=flow.randn(1)
c= b + a
print(type(c))
import torch
import numpy as np
a=np.array([1]).astype(np.int)[0]
print(type(a))
b=torch.randn(1)
c= b + a
print(type(c))
这时,oneflow 不支持这种情况,torch 输出还为 tensor。
- 第四种:a 是 scalar,b 是 tensor,做 a+b。
import oneflow as flow
import numpy as np
a=1.0
print(type(a))
b=flow.randn(1)
c= a + b
print(type(c))
import torch
import numpy as np
a=1.0
print(type(a))
b=torch.randn(1)
c= a + b
print(type(c))
这种情况两者是对齐的。
- 第五种:a 是
numpy.ndarraytype,b 是 tensor,做 a+b 运算。
import oneflow as flow
import numpy as np
a=np.array([1]).astype(np.double)
print(type(a))
b=flow.randn(1)
c= a + b
print(type(c))
import torch
import numpy as np
a=np.array([1]).astype(np.double)
print(type(a))
b=torch.randn(1)
c= a + b
print(type(c))
这时,oneflow 是支持这种运算的,输出为 numpy type,而 torch 则不支持,既:TypeError: unsupported operand type(s) for +: 'numpy.ndarray' and 'Tensor'。