internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: open-mmlab/mmpose

Issue:
Seed in sampler
https://github.com/open-mmlab/mmdetection/pull/4665


Discussion:

Resolving patch:
diff --git a/mmpose/datasets/builder.py b/mmpose/datasets/builder.py
--- a/mmpose/datasets/builder.py
+++ b/mmpose/datasets/builder.py
@@ -77,7 +77,7 @@ def build_dataloader(dataset,
     rank, world_size = get_dist_info()
     if dist:
         sampler = DistributedSampler(
-            dataset, world_size, rank, shuffle=shuffle)
+            dataset, world_size, rank, shuffle=shuffle, seed=seed)
         shuffle = False
         batch_size = samples_per_gpu
         num_workers = workers_per_gpu
diff --git a/mmpose/datasets/samplers/distributed_sampler.py b/mmpose/datasets/samplers/distributed_sampler.py
--- a/mmpose/datasets/samplers/distributed_sampler.py
+++ b/mmpose/datasets/samplers/distributed_sampler.py
@@ -10,15 +10,22 @@ class DistributedSampler(_DistributedSampler):
     class will port one to DistributedSampler.
     """
 
-    def __init__(self, dataset, num_replicas=None, rank=None, shuffle=True):
-        super().__init__(dataset, num_replicas=num_replicas, rank=rank)
-        self.shuffle = shuffle
+    def __init__(self,
+                 dataset,
+                 num_replicas=None,
+                 rank=None,
+                 shuffle=True,
+                 seed=0):
+        super().__init__(
+            dataset, num_replicas=num_replicas, rank=rank, shuffle=shuffle)
+        # for the compatibility from PyTorch 1.3+
+        self.seed = seed if seed is not None else 0
 
     def __iter__(self):
         """Deterministically shuffle based on epoch."""
         if self.shuffle:
             g = torch.Generator()
-            g.manual_seed(self.epoch)
+            g.manual_seed(self.epoch + self.seed)
             indices = torch.randperm(len(self.dataset), generator=g).tolist()
         else:
             indices = torch.arange(len(self.dataset)).tolist()


Test patch:
Repository: open-mmlab/mmpose

Issue:
Confusion about udp target generation
[Code](https://github.com/open-mmlab/mmpose/blob/13d44d09260d95880b3aa504f93441eaab1ee347/mmpose/datasets/pipelines/top_down_transform.py#L559) from `top_down_transform.py`
```python
        elif self.encoding == 'UDP':
            if self.target_type == 'CombinedTarget':
                factors = self.valid_radius_factor
                channel_factor = 3
            elif self.target_type == 'GaussianHeatMap':
                factors = self.sigma
                channel_factor = 1
            if isinstance(factors, list):
                num_factors = len(self.kernel)
                cfg = results['ann_info']
                num_joints = cfg['num_joints']
                W, H = cfg['heatmap_size']

                target = np.empty((0, channel_factor * num_joints, H, W),
                                  dtype=np.float32)
                target_weight = np.empty((0, num_joints, 1), dtype=np.float32)
                for i in range(num_factors):
                    target_i, target_weight_i = self._udp_generate_target(
                        cfg, joints_3d, joints_3d_visible, factors[i],
                        self.target_type)
                    target = np.concatenate([target, target_i[None] * 255], axis=0)
                    target_weight = np.concatenate(
                        [target_weight, target_weight_i[None]], axis=0)
            else:
                target, target_weight = self._udp_generate_target(
                    results['ann_info'], joints_3d, joints_3d_visible, factors,
                    self.target_type)
```
If `factor` is not a list, it's clear that `factor` is either `sigma` or `valid_radius_factor`.
But if `factor` is a list, the length of factor, `num_factors`, is determined by the length of the kernel.
Kernel should have nothing to do with generating udp target, right?
Is there any specific reason for this?


Discussion:
I will check this.

Resolving patch:
diff --git a/mmpose/datasets/pipelines/top_down_transform.py b/mmpose/datasets/pipelines/top_down_transform.py
--- a/mmpose/datasets/pipelines/top_down_transform.py
+++ b/mmpose/datasets/pipelines/top_down_transform.py
@@ -564,7 +564,7 @@ def __call__(self, results):
                 factors = self.sigma
                 channel_factor = 1
             if isinstance(factors, list):
-                num_factors = len(self.kernel)
+                num_factors = len(factors)
                 cfg = results['ann_info']
                 num_joints = cfg['num_joints']
                 W, H = cfg['heatmap_size']


Test patch:
Repository: open-mmlab/mmpose

Issue:
(TopDown Inference) IndexError: tuple index out of range
**Describe the bug**

IndexError: tuple index out of range

**Reproduction**
```
python demo/top_down_pose_tracking_demo_with_mmdet.py  \
demo/mmdetection_cfg/faster_rcnn_r50_fpn_coco.py \
http://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r50_fpn_1x_coco/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth \
    configs/top_down/resnet/coco/res50_coco_256x192.py \
    https://download.openmmlab.com/mmpose/top_down/resnet/res50_coco_256x192-ec54d7f3_20200709.pth \
    --video-path /dev/video0 \
    --show
```

**Environment**

Docker env
 
**Error traceback**

```
Use load_from_http loader
Use load_from_http loader
Traceback (most recent call last):
  File "demo/top_down_pose_tracking_demo_with_mmdet.py", line 177, in <module>
    main()
  File "demo/top_down_pose_tracking_demo_with_mmdet.py", line 132, in main
    pose_results, returned_outputs = inference_top_down_pose_model(
  File "/mmpose/mmpose/apis/inference.py", line 370, in inference_top_down_pose_model
    assert bboxes.shape[1] == 5
IndexError: tuple index out of range
```
**Exception handling is not exist when the human bounding boxes are not detected**

**Bug fix**
https://github.com/open-mmlab/mmpose/blob/dc7adc2d11f4b752cc089e3ba7b57f0fbc3cce77/mmpose/apis/inference.py#L364
ADD
```
    if len(person_results) == 0:
        return pose_results, returned_outputs
```


Discussion:
Thanks for the report!

Resolving patch:
diff --git a/mmpose/apis/inference.py b/mmpose/apis/inference.py
--- a/mmpose/apis/inference.py
+++ b/mmpose/apis/inference.py
@@ -362,6 +362,9 @@ def inference_top_down_pose_model(model,
     pose_results = []
     returned_outputs = []
 
+    if len(person_results) == 0:
+        return pose_results, returned_outputs
+
     # Change for-loop preprocess each bbox to preprocess all bboxes at once.
     bboxes = np.array([box['bbox'] for box in person_results])
 


Test patch:
Repository: open-mmlab/mmpose

Issue:
resource limit bug
**Describe the feature**

**Motivation**

It is inconvenient when we run mmpose on slurm clustre which may has larger file-open's soft limit than 4096. The resource limit adjust here  [https://github.com/open-mmlab/mmpose/blob/master/mmpose/datasets/builder.py#L13-L19](url) will reduce the base file-open's soft limit to 4096. Sometimes it will result in 'OSError: [Error 24] Too many open files' during training process.


**Additional context**
the code maybe can be modified like below:
```python

if platform.system() != 'Windows':
    # https://github.com/pytorch/pytorch/issues/973
    import resource
    rlimit = resource.getrlimit(resource.RLIMIT_NOFILE)
    base_soft_limit = rlimit[0]
    hard_limit = rlimit[1]
    soft_limit = min(max(4096,base_soft_limit), hard_limit)
    resource.setrlimit(resource.RLIMIT_NOFILE, (soft_limit, hard_limit))






Discussion:

Resolving patch:
diff --git a/mmpose/datasets/builder.py b/mmpose/datasets/builder.py
--- a/mmpose/datasets/builder.py
+++ b/mmpose/datasets/builder.py
@@ -14,8 +14,9 @@
     # https://github.com/pytorch/pytorch/issues/973
     import resource
     rlimit = resource.getrlimit(resource.RLIMIT_NOFILE)
+    base_soft_limit = rlimit[0]
     hard_limit = rlimit[1]
-    soft_limit = min(4096, hard_limit)
+    soft_limit = min(max(4096, base_soft_limit), hard_limit)
     resource.setrlimit(resource.RLIMIT_NOFILE, (soft_limit, hard_limit))
 
 DATASETS = Registry('dataset')


Test patch:
Repository: open-mmlab/mmpose

Issue:
[Bug] Possible bug in `mmpose/apis/train.py`
https://github.com/open-mmlab/mmpose/blob/8d668a578f1580373d90a1eea88f23f6816df60e/mmpose/apis/train.py#L140

Here is the code that may have problem. And I think the default value for `workers_per_gpu` should be an integer but not a dict. 


Discussion:
Agree. Please use 1 as the default value.

Resolving patch:
diff --git a/mmpose/apis/train.py b/mmpose/apis/train.py
--- a/mmpose/apis/train.py
+++ b/mmpose/apis/train.py
@@ -137,7 +137,7 @@ def train_model(model,
         val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))
         dataloader_setting = dict(
             samples_per_gpu=1,
-            workers_per_gpu=cfg.data.get('workers_per_gpu', {}),
+            workers_per_gpu=cfg.data.get('workers_per_gpu', 1),
             # cfg.gpus will be ignored if distributed
             num_gpus=len(cfg.gpu_ids),
             dist=distributed,


Test patch:
Repository: open-mmlab/mmpose

Issue:
框架有很多没有通过测试的Bug
在我运行res50_freihand2d_224x224.py的过程中就碰到了两个问题

1. tools/dist_train.sh里面没有定义$MASTER_ADDR

2. res50_freihand2d_224x224.py 没有定义runner = dict(type='EpochBasedRunner', max_epochs=total_epochs)

其他的还没有跑，但感觉会有很多小问题

发布的版本有点粗糙呀，期待把这些小Bug尽快解决，后续很期待在这个框架上做更多实验



Discussion:
Please use English or English & Chinese for issues so that we could have broader discussion.
I met two problems when I run the res50_freihand2d_224x224.py

1. $MASTER_ADDR is not defined in tools/dist_train.sh

2. res50_freihand2d_224x224.py does not define "runner = dict(type='EpochBasedRunner', max_epochs=total_epochs)"

I haven't run the other models yet, but I feel like there will be a lot of small problems

The released version is a bit rough. hope to solve these small bugs as soon as possible. I would like to conduct more experiments on this framework in the future.
Thanks for reporting these issues. 

Q1: $MASTER_ADDR is not defined in tools/dist_train.sh
A1: Yes. This is missing. We will fix it soon. BTW, if you would like to fix the bugs yourself, please feel free to raise a PR.

Q2: res50_freihand2d_224x224.py does not define "runner = dict(type='EpochBasedRunner', max_epochs=total_epochs)"
A2: I think this is not necessary. Does it cause any errors?

Resolving patch:
diff --git a/tools/train.py b/tools/train.py
--- a/tools/train.py
+++ b/tools/train.py
@@ -70,9 +70,7 @@ def parse_args():
         choices=['none', 'pytorch', 'slurm', 'mpi'],
         default='none',
         help='job launcher')
-    parser.add_argument('--local-rank', type=int, default=0)
-    parser.add_argument(
-        '--local_rank', type=int, default=0, help='An alias to --local-rank')
+    parser.add_argument('--local_rank', type=int, default=0)
     parser.add_argument(
         '--autoscale-lr',
         action='store_true',


Test patch:
diff --git a/tools/test.py b/tools/test.py
--- a/tools/test.py
+++ b/tools/test.py
@@ -66,9 +66,7 @@ def parse_args():
         choices=['none', 'pytorch', 'slurm', 'mpi'],
         default='none',
         help='job launcher')
-    parser.add_argument('--local-rank', type=int, default=0)
-    parser.add_argument(
-        '--local_rank', type=int, default=0, help='An alias to --local-rank')
+    parser.add_argument('--local_rank', type=int, default=0)
     args = parser.parse_args()
     if 'LOCAL_RANK' not in os.environ:
         os.environ['LOCAL_RANK'] = str(args.local_rank)
Repository: open-mmlab/mmpose

Issue:
ImportError: cannot import name '_xywh2xyxy' from 'mmpose.apis.inference' 
https://github.com/open-mmlab/mmpose/blob/04e57f8765c9489390e4af58f81085d383083da5/demo/body3d_two_stage_img_demo.py#L130


Discussion:

Resolving patch:
diff --git a/demo/body3d_two_stage_img_demo.py b/demo/body3d_two_stage_img_demo.py
--- a/demo/body3d_two_stage_img_demo.py
+++ b/demo/body3d_two_stage_img_demo.py
@@ -11,7 +11,8 @@
 from mmpose.apis import (inference_pose_lifter_model,
                          inference_top_down_pose_model, vis_3d_pose_result)
 from mmpose.apis.inference import init_pose_model
-from mmpose.core import SimpleCamera
+from mmpose.core.bbox import bbox_xywh2xyxy
+from mmpose.core.camera import SimpleCamera
 from mmpose.datasets import DatasetInfo
 
 
@@ -127,7 +128,6 @@ def main():
     # First stage: 2D pose detection
     pose_det_results_list = []
     if args.only_second_stage:
-        from mmpose.apis.inference import _xywh2xyxy
 
         print('Stage 1: load 2D pose results from Json file.')
         for image_id, image in coco.imgs.items():
@@ -144,7 +144,7 @@ def main():
 
                 pose_det_result = {
                     'image_name': image_name,
-                    'bbox': _xywh2xyxy(bbox),
+                    'bbox': bbox_xywh2xyxy(bbox),
                     'keypoints': keypoints,
                     'keypoints_3d': keypoints_3d
                 }


Test patch:
Repository: open-mmlab/mmpose

Issue:
why smooth "keypoints" but not "keypoints3d" in body3d_two_stage_video_demo.py?
Line 300 in body3d_two_stage_video_demo.py
`
smoother = Smoother(filter_cfg=args.smooth_filter_cfg, keypoint_dim=3)
`
set keypoints_dim = 3 but do not set  keypoint_key which has default value 'keypoints'.

It seems that we should smooth "keypoints_3d" but not "keypoints".Something wrong here?


Discussion:
Yes, the keypoint_key should be set as "keypoints_3d" here. Thanks for pointing it out, we will fix it asap.

Resolving patch:
diff --git a/demo/body3d_two_stage_video_demo.py b/demo/body3d_two_stage_video_demo.py
--- a/demo/body3d_two_stage_video_demo.py
+++ b/demo/body3d_two_stage_video_demo.py
@@ -154,7 +154,6 @@ def main():
         default='configs/_base_/filters/one_euro.py',
         help='Config file of the filter to smooth the pose estimation '
         'results. See also --smooth.')
-
     parser.add_argument(
         '--use-multi-frames',
         action='store_true',
@@ -298,7 +297,10 @@ def main():
 
     # build pose smoother for temporal refinement
     if args.smooth:
-        smoother = Smoother(filter_cfg=args.smooth_filter_cfg, keypoint_dim=3)
+        smoother = Smoother(
+            filter_cfg=args.smooth_filter_cfg,
+            keypoint_key='keypoints_3d',
+            keypoint_dim=3)
     else:
         smoother = None
 


Test patch:
Repository: open-mmlab/mmpose

Issue:
KeyError: 'heatmap_size'
I just started learning mmpose，when I run the demo，using configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/hrformer_base_coco_384x288.py weights/hrformer_base_coco_384x288-ecf0758d_20220316.pth，I got this error，why？
   File "/mnt/home/projects/mmpose/update/mmpose/mmpose/datasets/pipelines/top_down_transform.py", line 396, in _msra_generate_target
      W, H = cfg['heatmap_size']
  KeyError: 'heatmap_size'

version：
mmpose==0.28.0
mmcv-full==1.6.0


Discussion:
@wolfworld6 I have checked this config file `configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/hrformer_base_coco_384x288.py`. 
And there is an unnecessary pipeline in the `val_pipeline` (in [line 156](https://github.com/open-mmlab/mmpose/blob/master/configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/hrformer_base_coco_384x288.py#L156)):
`dict(type='TopDownGenerateTarget', sigma=3)`.

Thanks for pointing it out. We will fix it ASAP.

Resolving patch:
diff --git a/configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/hrformer_base_coco_384x288.py b/configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/hrformer_base_coco_384x288.py
--- a/configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/hrformer_base_coco_384x288.py
+++ b/configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/hrformer_base_coco_384x288.py
@@ -153,7 +153,6 @@
         type='NormalizeTensor',
         mean=[0.485, 0.456, 0.406],
         std=[0.229, 0.224, 0.225]),
-    dict(type='TopDownGenerateTarget', sigma=3),
     dict(
         type='Collect',
         keys=['img'],
diff --git a/configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/hrformer_small_coco_384x288.py b/configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/hrformer_small_coco_384x288.py
--- a/configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/hrformer_small_coco_384x288.py
+++ b/configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/hrformer_small_coco_384x288.py
@@ -153,7 +153,6 @@
         type='NormalizeTensor',
         mean=[0.485, 0.456, 0.406],
         std=[0.229, 0.224, 0.225]),
-    dict(type='TopDownGenerateTarget', sigma=3),
     dict(
         type='Collect',
         keys=['img'],


Test patch:
Repository: open-mmlab/mmpose

Issue:
little config error in 1.x

mmpose/tree/1.x/configs/hand_2d_keypoint/topdown_heatmap/coco_wholebody_hand)/td-hm_mobilenetv2_8xb32-210e_coco-wholebody-hand-256x256.py

mobilenetv2 out_channels is 1280, however "in_channles" of the head is 2048 in this config file.  



Discussion:
Thanks for reporting this bug. Would you mind helping to raise a PR to fix this bug?



Resolving patch:
diff --git a/configs/hand_2d_keypoint/topdown_heatmap/coco_wholebody_hand/td-hm_mobilenetv2_8xb32-210e_coco-wholebody-hand-256x256.py b/configs/hand_2d_keypoint/topdown_heatmap/coco_wholebody_hand/td-hm_mobilenetv2_8xb32-210e_coco-wholebody-hand-256x256.py
--- a/configs/hand_2d_keypoint/topdown_heatmap/coco_wholebody_hand/td-hm_mobilenetv2_8xb32-210e_coco-wholebody-hand-256x256.py
+++ b/configs/hand_2d_keypoint/topdown_heatmap/coco_wholebody_hand/td-hm_mobilenetv2_8xb32-210e_coco-wholebody-hand-256x256.py
@@ -47,7 +47,7 @@
         init_cfg=dict(type='Pretrained', checkpoint='mmcls://mobilenet_v2')),
     head=dict(
         type='HeatmapHead',
-        in_channels=2048,
+        in_channels=1280,
         out_channels=21,
         loss=dict(type='KeypointMSELoss', use_target_weight=True),
         decoder=codec),


Test patch:
Repository: tensorlayer/TensorLayer

Issue:
Bug in tutorial_cifar10_tfrecords.py
There seems to be a bug in the examples/tutorials_cifar10_tfrecords.py

Using tensorflow 0.12.1 I get the following error:
  File "tutorial_cifar10_tfrecord.py", line 116, in read_and_decode
    img = tf.image.per_image_whitening(img)
AttributeError: 'module' object has no attribute 'per_image_whitening'
[deepmind@deepmind tensorlayer]$ 



Discussion:

Resolving patch:
diff --git a/example/tutorial_cifar10_tfrecord.py b/example/tutorial_cifar10_tfrecord.py
--- a/example/tutorial_cifar10_tfrecord.py
+++ b/example/tutorial_cifar10_tfrecord.py
@@ -113,12 +113,19 @@ def read_and_decode(filename, is_train=None):
         # 4. Randomly change contrast.
         img = tf.image.random_contrast(img, lower=0.2, upper=1.8)
         # 5. Subtract off the mean and divide by the variance of the pixels.
-        img = tf.image.per_image_whitening(img)
+        try: # TF12
+            img = tf.image.per_image_standardization(img)
+        except: #earlier TF versions
+            img = tf.image.per_image_whitening(img)
+
     elif is_train == False:
         # 1. Crop the central [height, width] of the image.
         img = tf.image.resize_image_with_crop_or_pad(img, 24, 24)
         # 2. Subtract off the mean and divide by the variance of the pixels.
-        img = tf.image.per_image_whitening(img)
+        try: # TF12
+            img = tf.image.per_image_standardization(img)
+        except: #earlier TF versions
+            img = tf.image.per_image_whitening(img)
     elif is_train == None:
         img = img
 
@@ -246,7 +253,7 @@ def inference_batch_norm(x_crop, y_, reuse, is_train):
         with tf.variable_scope("model", reuse=reuse):
             tl.layers.set_name_reuse(reuse)
             network = tl.layers.InputLayer(x_crop, name='input_layer')
-            
+
             network = tl.layers.Conv2dLayer(network, act=tf.identity,
                         shape=[5, 5, 3, 64], strides=[1, 1, 1, 1], padding='SAME', # 64 features for each 5x5x3 patch
                         W_init=W_init, b_init=None, name='cnn_layer1')                            # output: (batch_size, 24, 24, 64)


Test patch:
Repository: tensorlayer/TensorLayer

Issue:
SubpixelConv2d is too slow when construct a graph
The reason may be in layers.py#L2191, the loop adds too many ops.
An alternative way is as follow:
Assume input feature maps X is b\*h\*w\*(r^2\*c) tensor,
`Xs=tf.split(X,r,3) #b*h*w*r*r`
`Xr=tf.concat(Xs,2) #b*h*(r*w)*r`
`X=tf.reshape(Xr,(b,r*h,r*w,c)) # b*(r*h)*(r*w)*c`
Then X is the return value in L2197

This way only add three ops in the graph, and for an feature map 24*24*64, the time constructing the graph is much more short.
Also, time for constructing train-ops is shorten.

layers.py#L2188 to L2196 need to change, and L2170 to L2186 can be removed.


Discussion:
Thank you for your advice. As it should be your credit, It is possible that you can contribute your code via push request?
Many thanks.

Resolving patch:
diff --git a/tensorlayer/layers.py b/tensorlayer/layers.py
--- a/tensorlayer/layers.py
+++ b/tensorlayer/layers.py
@@ -2167,31 +2167,14 @@ def SubpixelConv2d(net, scale=2, n_out_channel=None, act=tf.identity, name='subp
     if scope_name:
         name = scope_name + '/' + name
 
-    def _phase_shift(I, r):
-        if tf.__version__ < '1.0':
-            raise Exception("Only support TF1.0+")
-        bsize, a, b, c = I.get_shape().as_list()
-        bsize = tf.shape(I)[0] # Handling Dimension(None) type for undefined batch dim
-        X = tf.reshape(I, (bsize, a, b, r, r))
-        X = tf.transpose(X, (0, 1, 2, 4, 3))  # bsize, a, b, 1, 1 # tf 0.12
-        # X = tf.split(1, a, X)  # a, [bsize, b, r, r] # tf 0.12
-        X = tf.split(X, a, 1)
-        # X = tf.concat(2, [tf.squeeze(x, axis=1) for x in X])  # bsize, b, a*r, r # tf 0.12
-        X = tf.concat([tf.squeeze(x, axis=1) for x in X], 2)
-        # X = tf.split(1, b, X)  # b, [bsize, a*r, r] # tf 0.12
-        X = tf.split(X, b, 1)
-        # X = tf.concat(2, [tf.squeeze(x, axis=1) for x in X])  # bsize, a*r, b*r # tf 0.12
-        X = tf.concat([tf.squeeze(x, axis=1) for x in X], 2)
-        return tf.reshape(X, (bsize, a*r, b*r, 1))
-
     def _PS(X, r, n_out_channel):
-        if n_out_channel > 1:
+        if n_out_channel >= 1:
             assert int(X.get_shape()[-1]) == (r ** 2) * n_out_channel, _err_log
-            Xc = tf.split(X, n_out_channel, 3)
-            X = tf.concat([_phase_shift(x, r) for x in Xc], 3)
-        elif n_out_channel == 1:
-            assert int(X.get_shape()[-1]) == (r ** 2), _err_log
-            X = _phase_shift(X, r)
+            bsize, a, b, c = X.get_shape().as_list()
+            bsize = tf.shape(X)[0] # Handling Dimension(None) type for undefined batch dim
+            Xs=tf.split(X,r,3) #b*h*w*r*r
+            Xr=tf.concat(Xs,2) #b*h*(r*w)*r
+            X=tf.reshape(Xr,(bsize,r*a,r*b,n_out_channel)) # b*(r*h)*(r*w)*c
         else:
             print(_err_log)
         return X


Test patch: