Sự khác biệt giữa định hình lại và chế độ xem trong pytorch là gì?


83

Trong numpy, chúng tôi sử dụng ndarray.reshape()để định hình lại một mảng.

Tôi nhận thấy rằng trong pytorch, mọi người sử dụng torch.view(...)cho cùng một mục đích, nhưng đồng thời, cũng có một torch.reshape(...)tồn tại.

Vì vậy, tôi tự hỏi sự khác biệt giữa chúng là gì và khi nào tôi nên sử dụng một trong hai?

Câu trả lời:


88

torch.viewđã có từ rất lâu đời. Nó sẽ trả về một tensor với hình dạng mới. Tensor trả về sẽ chia sẻ dữ liệu cơ bản với tensor ban đầu. Xem tài liệu tại đây .

Mặt khác, có vẻ như nó torch.reshape đã được giới thiệu gần đây trong phiên bản 0.4 . Theo tài liệu , phương pháp này sẽ

Trả về một tensor có cùng dữ liệu và số phần tử như đầu vào, nhưng có hình dạng được chỉ định. Khi có thể, tensor trả về sẽ là một khung nhìn của đầu vào. Nếu không, nó sẽ là một bản sao. Các đầu vào và đầu vào liền kề với các bước tương thích có thể được định hình lại mà không cần sao chép, nhưng bạn không nên phụ thuộc vào hành vi sao chép so với xem.

Nó có nghĩa là nó torch.reshapecó thể trả về một bản sao hoặc một khung nhìn của tensor gốc. Bạn không thể dựa vào đó để trả lại một lượt xem hoặc một bản sao. Theo nhà phát triển:

nếu bạn cần một bản sao, hãy sử dụng clone () nếu bạn cần cùng một chế độ xem sử dụng bộ nhớ (). Ngữ nghĩa của reshape () là nó có thể chia sẻ hoặc không chia sẻ bộ nhớ mà bạn không biết trước.

Một điểm khác biệt nữa là reshape()có thể hoạt động trên tensor liền kề và không liền kề trong khi view()chỉ có thể hoạt động trên tensor liền kề. Cũng xem ở đây về ý nghĩa của contiguous.


28
Có thể nhấn mạnh rằng torch.view chỉ có thể hoạt động trên các tensors liền kề, trong khi torch.reshape có thể hoạt động trên cả hai cũng có thể hữu ích.
p13rr0m

6
@pierrom contiguous ở đây đề cập đến tensors được lưu trữ trong bộ nhớ liền kề hay thứ gì khác?
gokul_uf

3
@gokul_uf Có, bạn có thể xem câu trả lời được viết ở đây: stackoverflow.com/questions/48915810/pytorch-contiguous
MBT

cụm từ "một khung nhìn của tensor" có nghĩa là trong pytorch?
Charlie Parker

42

Mặc dù cả hai torch.viewtorch.reshapeđều được sử dụng để định hình lại các tenxơ, nhưng đây là sự khác biệt giữa chúng.

  1. Như tên cho thấy, torch.viewchỉ đơn thuần tạo ra một khung nhìn của tensor ban đầu. Tensor mới sẽ luôn chia sẻ dữ liệu của nó với tensor ban đầu. Điều này có nghĩa là nếu bạn thay đổi tensor ban đầu, tensor định hình lại sẽ thay đổi và ngược lại.
>>> z = torch.zeros(3, 2)
>>> x = z.view(2, 3)
>>> z.fill_(1)
>>> x
tensor([[1., 1., 1.],
        [1., 1., 1.]])
  1. Để đảm bảo rằng tenxơ mới luôn chia sẻ dữ liệu của nó với dữ liệu ban đầu, hãy torch.viewáp đặt một số ràng buộc về mặt tiếp giáp đối với hình dạng của hai tenxơ [ docs ]. Thông thường, điều này không đáng lo ngại, nhưng đôi khi gây torch.viewra lỗi ngay cả khi hình dạng của hai bộ căng dây tương thích. Đây là một ví dụ phản bác nổi tiếng.
>>> z = torch.zeros(3, 2)
>>> y = z.t()
>>> y.size()
torch.Size([2, 3])
>>> y.view(6)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: invalid argument 2: view size is not compatible with input tensor's
size and stride (at least one dimension spans across two contiguous subspaces).
Call .contiguous() before .view().
  1. torch.reshapekhông áp đặt bất kỳ ràng buộc tiếp giáp nào, nhưng cũng không đảm bảo chia sẻ dữ liệu. Teo mới có thể là một hình chiếu của tensor ban đầu, hoặc nó có thể là một tensor mới hoàn toàn.
>>> z = torch.zeros(3, 2)
>>> y = z.reshape(6)
>>> x = z.t().reshape(6)
>>> z.fill_(1)
tensor([[1., 1.],
        [1., 1.],
        [1., 1.]])
>>> y
tensor([1., 1., 1., 1., 1., 1.])
>>> x
tensor([0., 0., 0., 0., 0., 0.])

TL; DR:
Nếu bạn chỉ muốn định hình lại các tensor, hãy sử dụng torch.reshape. Nếu bạn cũng lo lắng về việc sử dụng bộ nhớ và muốn đảm bảo rằng hai bộ căng chia sẻ cùng một dữ liệu, hãy sử dụng torch.view.


Có thể đó chỉ là tôi, nhưng tôi đã bối rối khi nghĩ rằng sự tiếp giáp là yếu tố quyết định giữa thời điểm định hình lại và không chia sẻ dữ liệu. Từ các thí nghiệm của riêng tôi, có vẻ như đây không phải là trường hợp. (Của bạn xyở trên đều tiếp giáp). Có lẽ điều này có thể được làm rõ? Có lẽ một nhận xét về việc định hình lại khi nào và không sao chép sẽ hữu ích?
RMurphy

6

Tensor.reshape()mạnh mẽ hơn. Nó sẽ hoạt động trên mọi tensor, trong khi Tensor.view()chỉ hoạt động trên tensor tđâu t.is_contiguous()==True.

Để giải thích về không liền kề và liền kề là một câu chuyện thời gian khác, nhưng bạn luôn có thể làm cho tensor tliền kề là bạn gọi t.contiguous()và sau đó bạn có thể gọi view()mà không bị lỗi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.