{
  "id": 342794,
  "title": "Correct Implementation of PixelShuffle in Tensorflow?",
  "url": "/competitions/hubmap-organ-segmentation/discussion/342794",
  "author_name": "",
  "post_date": "2022-08-08T19:32:22.818308Z",
  "votes": 4,
  "comment_count": 1,
  "views": 0,
  "content": "<p>Many notebooks use <code>PixelShuffle</code> layers instead of <code>Conv2DTranspose</code> to upscale feature maps in the decoder of a UNet. The PixelShuffle layer is a native layer in Pytorch, however it has not been added to Tensorflow yet.</p>\n<p>Is the following implementation in Tensorflow correct?</p>\n<pre><code>def PixelShuffle(x, upscale_factor=2):\n    _, w, h, c = x.shape\n    n = -1\n\n    c_out = c // upscale_factor ** 2\n    w_out = w * upscale_factor\n    h_out = h * upscale_factor\n\n    x = tf.reshape(x, [-1, upscale_factor, upscale_factor, w, h, c_out])\n    x = tf.transpose(x, [0, 3, 1, 4, 2, 5])\n    x = tf.reshape(x, [-1, w_out, h_out, c_out])\n\n    return x\n</code></pre>",
  "messages": [
    {
      "id": "1890512",
      "postDate": "08/08/2022 19:32:22",
      "content": "<p>Many notebooks use <code>PixelShuffle</code> layers instead of <code>Conv2DTranspose</code> to upscale feature maps in the decoder of a UNet. The PixelShuffle layer is a native layer in Pytorch, however it has not been added to Tensorflow yet.</p>\n<p>Is the following implementation in Tensorflow correct?</p>\n<pre><code>def PixelShuffle(x, upscale_factor=2):\n    _, w, h, c = x.shape\n    n = -1\n\n    c_out = c // upscale_factor ** 2\n    w_out = w * upscale_factor\n    h_out = h * upscale_factor\n\n    x = tf.reshape(x, [-1, upscale_factor, upscale_factor, w, h, c_out])\n    x = tf.transpose(x, [0, 3, 1, 4, 2, 5])\n    x = tf.reshape(x, [-1, w_out, h_out, c_out])\n\n    return x\n</code></pre>",
      "rawMarkdown": "Many notebooks use `PixelShuffle` layers instead of `Conv2DTranspose` to upscale feature maps in the decoder of a UNet. The PixelShuffle layer is a native layer in Pytorch, however it has not been added to Tensorflow yet.\n\nIs the following implementation in Tensorflow correct?\n\n```\ndef PixelShuffle(x, upscale_factor=2):\n    _, w, h, c = x.shape\n    n = -1\n\n    c_out = c // upscale_factor ** 2\n    w_out = w * upscale_factor\n    h_out = h * upscale_factor\n\n    x = tf.reshape(x, [-1, upscale_factor, upscale_factor, w, h, c_out])\n    x = tf.transpose(x, [0, 3, 1, 4, 2, 5])\n    x = tf.reshape(x, [-1, w_out, h_out, c_out])\n\n    return x\n```",
      "votes": null
    },
    {
      "id": "1891310",
      "postDate": "08/09/2022 10:47:34",
      "content": "<p>maybe you can try this :)</p>\n<pre><code>import tensorflow as tf\nimport torch.nn.functional as F\nimport torch\n\n#tf version of pixel_shuffle\ndef pixel_shuffle(images, upscale_factor=2):\n    N, H, W, C = tf.unstack(tf.shape(images), num=4) #images.shape doesn't work inside model.\n    tf.debugging.assert_equal(C % upscale_factor**2,0,message='channel_size must be divisible by upscale_factor**2')\n\n    images = tf.reshape(images, (-1, H, W, C//upscale_factor**2, upscale_factor, upscale_factor))\n    images = tf.transpose(images, (0,1,4,2,5,3))\n    images = tf.reshape(images, (-1, H*upscale_factor, W*upscale_factor, C//upscale_factor**2))\n    return images\n</code></pre>\n<pre><code>images = np.random.uniform(size=(4,256,256,32))\nimages1 = pixel_shuffle(images, 2).numpy()\nimages1.shape\n(4, 512, 512, 8)\n</code></pre>\n<pre><code>images2 = F.pixel_shuffle(torch.Tensor(np.transpose(images, (0,3,1,2))), 2).numpy()\nimages2 = np.transpose(images2, (0,2,3,1))\nimages2.shape\n(4, 512, 512, 8)\n</code></pre>\n<pre><code>np.allclose(images1, images2)\nTrue\n</code></pre>",
      "rawMarkdown": "maybe you can try this :)\n```\nimport tensorflow as tf\nimport torch.nn.functional as F\nimport torch\n\n#tf version of pixel_shuffle\ndef pixel_shuffle(images, upscale_factor=2):\n    N, H, W, C = tf.unstack(tf.shape(images), num=4) #images.shape doesn't work inside model.\n    tf.debugging.assert_equal(C % upscale_factor**2,0,message='channel_size must be divisible by upscale_factor**2')\n\n    images = tf.reshape(images, (-1, H, W, C//upscale_factor**2, upscale_factor, upscale_factor))\n    images = tf.transpose(images, (0,1,4,2,5,3))\n    images = tf.reshape(images, (-1, H*upscale_factor, W*upscale_factor, C//upscale_factor**2))\n    return images\n```\n\n```\nimages = np.random.uniform(size=(4,256,256,32))\nimages1 = pixel_shuffle(images, 2).numpy()\nimages1.shape\n(4, 512, 512, 8)\n```\n\n```\nimages2 = F.pixel_shuffle(torch.Tensor(np.transpose(images, (0,3,1,2))), 2).numpy()\nimages2 = np.transpose(images2, (0,2,3,1))\nimages2.shape\n(4, 512, 512, 8)\n```\n\n```\nnp.allclose(images1, images2)\nTrue\n```",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 1891310,
      "author_name": "hoyso48",
      "author_url": "",
      "post_date": "08/09/2022 10:47:34",
      "content": "<p>maybe you can try this :)</p>\n<pre><code>import tensorflow as tf\nimport torch.nn.functional as F\nimport torch\n\n#tf version of pixel_shuffle\ndef pixel_shuffle(images, upscale_factor=2):\n    N, H, W, C = tf.unstack(tf.shape(images), num=4) #images.shape doesn't work inside model.\n    tf.debugging.assert_equal(C % upscale_factor**2,0,message='channel_size must be divisible by upscale_factor**2')\n\n    images = tf.reshape(images, (-1, H, W, C//upscale_factor**2, upscale_factor, upscale_factor))\n    images = tf.transpose(images, (0,1,4,2,5,3))\n    images = tf.reshape(images, (-1, H*upscale_factor, W*upscale_factor, C//upscale_factor**2))\n    return images\n</code></pre>\n<pre><code>images = np.random.uniform(size=(4,256,256,32))\nimages1 = pixel_shuffle(images, 2).numpy()\nimages1.shape\n(4, 512, 512, 8)\n</code></pre>\n<pre><code>images2 = F.pixel_shuffle(torch.Tensor(np.transpose(images, (0,3,1,2))), 2).numpy()\nimages2 = np.transpose(images2, (0,2,3,1))\nimages2.shape\n(4, 512, 512, 8)\n</code></pre>\n<pre><code>np.allclose(images1, images2)\nTrue\n</code></pre>",
      "votes": null,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "1890512": "Many notebooks use `PixelShuffle` layers instead of `Conv2DTranspose` to upscale feature maps in the decoder of a UNet. The PixelShuffle layer is a native layer in Pytorch, however it has not been added to Tensorflow yet.\n\nIs the following implementation in Tensorflow correct?\n\n```\ndef PixelShuffle(x, upscale_factor=2):\n    _, w, h, c = x.shape\n    n = -1\n\n    c_out = c // upscale_factor ** 2\n    w_out = w * upscale_factor\n    h_out = h * upscale_factor\n\n    x = tf.reshape(x, [-1, upscale_factor, upscale_factor, w, h, c_out])\n    x = tf.transpose(x, [0, 3, 1, 4, 2, 5])\n    x = tf.reshape(x, [-1, w_out, h_out, c_out])\n\n    return x\n```",
    "1891310": "maybe you can try this :)\n```\nimport tensorflow as tf\nimport torch.nn.functional as F\nimport torch\n\n#tf version of pixel_shuffle\ndef pixel_shuffle(images, upscale_factor=2):\n    N, H, W, C = tf.unstack(tf.shape(images), num=4) #images.shape doesn't work inside model.\n    tf.debugging.assert_equal(C % upscale_factor**2,0,message='channel_size must be divisible by upscale_factor**2')\n\n    images = tf.reshape(images, (-1, H, W, C//upscale_factor**2, upscale_factor, upscale_factor))\n    images = tf.transpose(images, (0,1,4,2,5,3))\n    images = tf.reshape(images, (-1, H*upscale_factor, W*upscale_factor, C//upscale_factor**2))\n    return images\n```\n\n```\nimages = np.random.uniform(size=(4,256,256,32))\nimages1 = pixel_shuffle(images, 2).numpy()\nimages1.shape\n(4, 512, 512, 8)\n```\n\n```\nimages2 = F.pixel_shuffle(torch.Tensor(np.transpose(images, (0,3,1,2))), 2).numpy()\nimages2 = np.transpose(images2, (0,2,3,1))\nimages2.shape\n(4, 512, 512, 8)\n```\n\n```\nnp.allclose(images1, images2)\nTrue\n```"
  },
  "source": "meta"
}