{
  "source_file": "0930",
  "source_platform": "Dev.to",
  "author": "Wesam Khallaf",
  "title_listed": "Reshape vs View in PyTorch: What's the Difference (and When `view()` Breaks)",
  "keywords": "",
  "domain": "机器学习",
  "content_type": "技术教程",
  "is_paid_flag": "否",
  "url": "https://dev.to/pytorchfromgroundup/reshape-vs-view-in-pytorch-whats-the-difference-and-when-view-breaks-4a9o",
  "publish_date": "2026-07-17",
  "corpus_stage": "",
  "notes": "",
  "id": "e042757a931d",
  "collected_at": "2026-10-02T13:54:04",
  "title": "Reshape vs View in PyTorch: What's the Difference (and When `view()` Breaks) - DEV Community",
  "body_markdown": "You called\n.view()\non a tensor, got a\nRuntimeError: view size is not compatible with input tensor's size and stride\n, switched to\n.reshape()\n, and it just... worked. So what's actually going on — and which one should you use?\nThe short answer\nreshape\nand\nview\nboth give you the same numbers under a new shape. The difference is one word:\ncontiguity\n.\nview()\nreturns a zero-copy view but\nrequires the tensor to be contiguous\n— if it isn't, it errors.\nreshape()\nreturns a view when it can and silently makes a copy when it can't, so it never errors on contiguity.\nUse\nreshape()\nby default;\nreach for\nview()\nonly when you specifically need to guarantee shared memory.\nWhy reshape vs view exists at all\nA tensor's data and its shape are two separate things. The data is a flat row of numbers sitting in memory; the shape is just the lens you look at it through. Reshaping changes the lens without touching the numbers — twelve elements can be seen as a 3×4 matrix, a 4×3, a 2×6, or a flat row of 12.\nimport\ntorch\nt\n=\ntorch\n.\narange\n(\n1\n,\n13\n)\n# 12 elements: 1..12\nprint\n(\nt\n.\nreshape\n(\n3\n,\n4\n))\nprint\n(\nt\n.\nreshape\n(\n2\n,\n6\n))\nprint\n(\nt\n.\nreshape\n(\n12\n))\nEnter fullscreen mode\nExit fullscreen mode\nThe only constraint is that the product of the new shape must equal the total number of elements (\nnumel()\n). Twelve elements can become\n(3, 4)\nbecause 3 × 4 = 12, but not\n(3, 5)\nbecause 3 × 5 = 15.\nWhen the tensor is contiguous — which it almost always is right after you create it —\nview\nand\nreshape\ndo exactly the same thing: return a zero-cost view of the same memory.\nt\n=\ntorch\n.\narange\n(\n12\n)\na\n=\nt\n.\nview\n(\n3\n,\n4\n)\n# view — always free\nb\n=\nt\n.\nreshape\n(\n3\n,\n4\n)\n# reshape — also free here\nprint\n(\na\n.\ndata_ptr\n()\n==\nt\n.\ndata_ptr\n())\n# True\nprint\n(\nb\n.\ndata_ptr\n()\n==\nt\n.\ndata_ptr\n())\n# True\nEnter fullscreen mode\nExit fullscreen mode\nSame data pointer means no copy happened. So far, no difference.\nWhat does \"contiguous\" mean in PyTorch?\nA tensor is\ncontiguous\nwhen its elements — read left-to-right along the last dimension, then the next dimension out, and so on — sit in that same order in memory. Most tensors are contiguous from birth. The operations that break contiguity are\ntranspose\n,\npermute\n, and\nexpand\n: they change the\nstrides\nwithout moving the data.\nt\n=\ntorch\n.\narange\n(\n6\n).\nreshape\n(\n2\n,\n3\n)\nprint\n(\nt\n.\nis_contiguous\n())\n# True\nprint\n(\nt\n.\nstride\n())\n# (3, 1)\ntt\n=\nt\n.\nT\n# transpose\nprint\n(\ntt\n.\nis_contiguous\n())\n# False\nprint\n(\ntt\n.\nstride\n())\n# (1, 3)\nEnter fullscreen mode\nExit fullscreen mode\nAfter the transpose the strides are reversed. The numbers are still in the same flat row\n0 1 2 3 4 5\n, but reading them in the new dimension order no longer walks through memory in order. That is non-contiguous — and it's exactly the situation where\nview()\nbreaks.\nWhen\nview()\nbreaks (the error you googled)\ntt\n=\nt\n.\nT\n# non-contiguous\ntt\n.\nview\n(\n6\n)\n# RuntimeError!\nEnter fullscreen mode\nExit fullscreen mode\nYou'll see something like:\nRuntimeError: view size is not compatible with input tensor's size and stride\n(at least one dimension spans across two contiguous subspaces). Use .reshape(...) instead.\nEnter fullscreen mode\nExit fullscreen mode\nPyTorch is telling you the operation isn't safe as a zero-copy view. You have two fixes:\nprint\n(\ntt\n.\nreshape\n(\n6\n))\n# works — quietly copies\nprint\n(\ntt\n.\ncontiguous\n().\nview\n(\n6\n))\n# also works — rearranges memory first, then views\nEnter fullscreen mode\nExit fullscreen mode\nreshape\nis almost always the right default. Call\n.contiguous().view(...)\nonly when you have a reason to force the copy explicitly.\nWatch out: reshape doesn't guarantee a view\nBecause\nreshape\nreturns a view\nsometimes\nand a copy\nother times\n, you cannot rely on it to share memory. If you need in-place edits to propagate back to the original, use\nview\n— and if it errors, that's PyTorch telling you the operation genuinely can't be done without copying.\nThe\n-1\nshortcut\nYou can pass\n-1\nfor exactly one dimension and PyTorch infers its size from the total element count:\nt\n=\ntorch\n.\narange\n(\n24\n)\nprint\n(\nt\n.\nreshape\n(\n4\n,\n-\n1\n).\nshape\n)\n# (4, 6)\nprint\n(\nt\n.\nreshape\n(\n-\n1\n,\n3\n).\nshape\n)\n# (8, 3)\nprint\n(\nt\n.\nreshape\n(\n2\n,\n3\n,\n-\n1\n).\nshape\n)\n# (2, 3, 4)\nEnter fullscreen mode\nExit fullscreen mode\nAt most one\n-1\nper call. This is everywhere in real code — you know some dimensions and let PyTorch solve for the last.\nA worked example: flatten before a linear layer\nThe single most common reshape in practice is collapsing spatial dimensions before a fully-connected layer, while keeping the batch dimension intact:\nbatch\n=\ntorch\n.\nrandn\n(\n32\n,\n3\n,\n28\n,\n28\n)\n# N, C, H, W\nflat\n=\nbatch\n.\nflatten\n(\n1\n)\n# flatten from dim 1 onward\nprint\n(\nflat\n.\nshape\n)\n# torch.Size([32, 2352])\nEnter fullscreen mode\nExit fullscreen mode\nflatten(1)\nkeeps dimension 0 (the batch) and merges the rest into one. Note the trap:\nflatten()\nwith\nno argument\ncollapses\neverything\n, batch included — inside a model's forward pass, always use\nflatten(1)\n.\nCommon mistakes and gotchas\nCalling\nview()\nafter\ntranspose\n/\npermute\n.\nThat's the classic\nRuntimeError\n. Use\nreshape()\nor\n.contiguous().view()\n.\nAssuming\nreshape\nshares memory.\nSometimes it copies. If you need a guaranteed view, use\nview()\n.\nUsing bare\nflatten()\nin a forward pass.\nIt eats the batch dimension. Use\nflatten(1)\n.\nWrong element count.\nreshape(3, 5)\non 12 elements raises\nRuntimeError: shape '[3, 5]' is invalid for input of size 12\n. The product must equal\nnumel()\n.\nRecap\nview\nand\nreshape\nboth reinterpret the same flat memory under a new shape.\nview\nrequires contiguity and always returns a true view;\nreshape\nreturns a view when it can and copies when it must, so it never errors on contiguity. Default to\nreshape\n; use\nview\nwhen you specifically need shared memory.\nThis is one idea from my book\nPyTorch From Ground Up\n, which builds everything from tensors upward so nothing stays vague. If it helped, you can grab the\nfree PyTorch tensor cheat-sheet here\n, run every example from the book in the\ncompanion notebooks on GitHub\n, or find the\nfull paperback on Amazon here\nor find a\ndigital copy of the book on leanpup here",
  "metadata": {
    "title": "Reshape vs View in PyTorch: What's the Difference (and When `view()` Breaks) - DEV Community",
    "description": "You called .view() on a tensor, got a RuntimeError: view size is not compatible with input tensor's... Tagged with deeplearning, machinelearning, python, tutorial.",
    "keywords": "deeplearning, machinelearning, python, tutorial, software, coding, development, engineering, inclusive, community",
    "author": null,
    "og:type": "article",
    "og:url": "https://dev.to/pytorchfromgroundup/reshape-vs-view-in-pytorch-whats-the-difference-and-when-view-breaks-4a9o",
    "og:title": "Reshape vs View in PyTorch: What's the Difference (and When `view()` Breaks)",
    "og:description": "You called .view() on a tensor, got a RuntimeError: view size is not compatible with input tensor's...",
    "og:site_name": "DEV Community",
    "og:image": "https://media2.dev.to/dynamic/image/width=1200,height=627,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F54txmntr5qcmoa48vy0u.png",
    "twitter:site": "@thepracticaldev",
    "twitter:creator": "@wesamkhallaf",
    "twitter:title": "Reshape vs View in PyTorch: What's the Difference (and When `view()` Breaks)",
    "twitter:description": "You called .view() on a tensor, got a RuntimeError: view size is not compatible with input tensor's...",
    "twitter:card": "summary_large_image",
    "twitter:widgets:new-embed-design": "on",
    "twitter:image:src": "https://media2.dev.to/dynamic/image/width=1200,height=627,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F54txmntr5qcmoa48vy0u.png"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/e042757a931d/code/body-000.txt",
      "chars": 130,
      "language": "text"
    },
    {
      "file": "attachments/e042757a931d/code/body-001.txt",
      "chars": 203,
      "language": "text"
    },
    {
      "file": "attachments/e042757a931d/code/body-002.txt",
      "chars": 215,
      "language": "text"
    },
    {
      "file": "attachments/e042757a931d/code/body-003.txt",
      "chars": 95,
      "language": "text"
    },
    {
      "file": "attachments/e042757a931d/code/body-004.txt",
      "chars": 169,
      "language": "text"
    },
    {
      "file": "attachments/e042757a931d/code/body-005.txt",
      "chars": 146,
      "language": "text"
    },
    {
      "file": "attachments/e042757a931d/code/body-006.txt",
      "chars": 153,
      "language": "text"
    },
    {
      "file": "attachments/e042757a931d/code/body-007.txt",
      "chars": 177,
      "language": "text"
    }
  ],
  "images": [],
  "audio": [],
  "videos": [],
  "links": [
    {
      "href": "https://payhip.com/b/7ukxh",
      "label": "free PyTorch tensor cheat-sheet here",
      "type": "a"
    },
    {
      "href": "https://github.com/pytorch-from-ground-up/book_code",
      "label": "companion notebooks on GitHub",
      "type": "a"
    },
    {
      "href": "https://www.amazon.com/dp/B0H8WMCV33",
      "label": "full paperback on Amazon here",
      "type": "a"
    },
    {
      "href": "https://leanpub.com/pytorchfromgroundup",
      "label": "digital copy of the book on leanpup here",
      "type": "a"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:48:54Z",
  "source_url": "https://dev.to/pytorchfromgroundup/reshape-vs-view-in-pytorch-whats-the-difference-and-when-view-breaks-4a9o",
  "papers": [],
  "actual_video_files": [],
  "body_chars": 6109,
  "expected_body_images": 0,
  "discovery_status": "ok",
  "delivery_status": "ok",
  "missing_reason": "",
  "raw_html": "attachments/e042757a931d/pages/source.html",
  "local_html": "attachments/e042757a931d/pages/article.html",
  "body_base_path": "attachments/e042757a931d/pages/",
  "body_markdown_path": "attachments/e042757a931d/pages/article.md"
}