私はPyTorch Tensorメモリモデルがどのように機能するかについて深く理解しようとしています。
_# input numpy array
In [91]: arr = np.arange(10, dtype=float32).reshape(5, 2)
# input tensors in two different ways
In [92]: t1, t2 = torch.Tensor(arr), torch.from_numpy(arr)
# their types
In [93]: type(arr), type(t1), type(t2)
Out[93]: (numpy.ndarray, torch.FloatTensor, torch.FloatTensor)
# ndarray
In [94]: arr
Out[94]:
array([[ 0., 1.],
[ 2., 3.],
[ 4., 5.],
[ 6., 7.],
[ 8., 9.]], dtype=float32)
_
PyTorchテンソルはNumPy ndarraysのメモリバッファを共有することを知っています。したがって、一方を変更すると他方に反映されます。だから、ここで私はTensor _t2
_のいくつかの値をスライスして更新しています
_In [98]: t2[:, 1] = 23.0
_
そして予想どおり、同じメモリバッファを共有しているため、_t2
_およびarr
で更新されます。
_In [99]: t2
Out[99]:
0 23
2 23
4 23
6 23
8 23
[torch.FloatTensor of size 5x2]
In [101]: arr
Out[101]:
array([[ 0., 23.],
[ 2., 23.],
[ 4., 23.],
[ 6., 23.],
[ 8., 23.]], dtype=float32)
_
ただし、_t1
_も更新されます。 _t1
_はtorch.Tensor()
を使用して構築されたのに対し、_t2
_はtorch.from_numpy()
を使用して構築されたことを思い出してください
_In [100]: t1
Out[100]:
0 23
2 23
4 23
6 23
8 23
[torch.FloatTensor of size 5x2]
_
したがって、 torch.from_numpy()
または torch.Tensor()
を使用してndarrayからテンソルを構築しても、allそのようなテンソルとndarrayは同じメモリバッファを共有します。
この理解に基づいて、私の質問は、単に torch.from_numpy()
ができるのに、なぜ専用の関数 torch.Tensor()
が存在するのかということです。
PyTorchのドキュメントを見ましたが、これについては何も言及されていませんか?アイデア/提案はありますか?
from_numpy()
は、入力配列dtype
を自動的に継承します。一方、torch.Tensor
はtorch.FloatTensor
のエイリアスです。
したがって、int64
配列をtorch.Tensor
に渡すと、出力テンソルは浮動小数点テンソルになり、ストレージを共有しません。 torch.from_numpy
は、期待どおりtorch.LongTensor
を提供します。
a = np.arange(10)
ft = torch.Tensor(a) # same as torch.FloatTensor
it = torch.from_numpy(a)
a.dtype # == dtype('int64')
ft.dtype # == torch.float32
it.dtype # == torch.int64
これは_torch_docs.py
;また、「why」 here に関する議論もあります。
def from_numpy(ndarray): # real signature unknown; restored from __doc__
"""
from_numpy(ndarray) -> Tensor
Creates a :class:`Tensor` from a :class:`numpy.ndarray`.
The returned tensor and `ndarray` share the same memory.
Modifications to the tensor will be reflected in the `ndarray`
and vice versa. The returned tensor is not resizable.
Example::
>>> a = numpy.array([1, 2, 3])
>>> t = torch.from_numpy(a)
>>> t
torch.LongTensor([1, 2, 3])
>>> t[0] = -1
>>> a
array([-1, 2, 3])
"""
pass
numpy
ドキュメントから取得:
異なる
ndarrays
は同じデータを共有できるため、1つのndarrayで行われた変更が別のndarrayで見えるようになります。つまり、ndarray
は別のndarray
の「ビュー」になることができ、それが参照しているデータは「ベース」ndarray
によって処理されます。
Pytorch docs
:
もし
numpy.ndarray
、torch.Tensor
、 またはtorch.Storage
が指定された場合、同じデータを共有する新しいテンソルが返されます。 Pythonシーケンスが指定された場合、シーケンスのコピーから新しいテンソルが作成されます。
Pytorchでテンソルを構築する推奨方法は、次の2つのファクトリ関数を使用することです:_torch.tensor
_および_torch.as_tensor
_。
_torch.tensor
_ alwaysはデータをコピーします。たとえば、torch.tensor(x)
はx.clone().detach()
と同等です。
_torch.as_tensor
_ 常に試行データのコピーを回避します。 _as_tensor
_がデータのコピーを回避するケースの1つは、元のデータがnumpy配列である場合です。