Repository: onnx/onnx

Issue:
Add col2im operator
# col2im

### Describe the operator
Rearranges input tensor in blocks. Same behavior as https://pytorch.org/cppdocs/api/function_namespaceat_1a979fbf85d8c7362d60d766bbf1639f10.html

### Can this operator be constructed using existing onnx operators?
If so, why not add it as a function?

### Is this operator used by any model currently? Which one?

Used by `torch.fold`.

Enables model [SS-DCNet](https://github.com/xhp-hust-2018-2011/SS-DCNet)
Enables model [DSTT](https://github.com/ruiliu-ai/DSTT)

Requests for this on the PyTorch converter:
https://github.com/pytorch/pytorch/issues/41423 https://github.com/pytorch/pytorch/issues/64012

### Are you willing to contribute it? (Y/N)

Y





Discussion:

Resolving patch:
diff --git a/onnx/helper.py b/onnx/helper.py
--- a/onnx/helper.py
+++ b/onnx/helper.py
@@ -345,7 +345,7 @@ def make_tensor(
         data_type (int): a value such as onnx.TensorProto.FLOAT
         dims (List[int]): shape
         vals: values
-        raw (bool): if True, vals contains the seralized content of the tensor,
+        raw (bool): if True, vals contains the serialized content of the tensor,
             otherwise, vals should be a list of values of the type defined by *data_type*
 
     Returns:


Test patch:
diff --git a/onnx/backend/test/case/node/col2im.py b/onnx/backend/test/case/node/col2im.py
new file mode 100644
--- /dev/null
+++ b/onnx/backend/test/case/node/col2im.py
@@ -0,0 +1,349 @@
+# SPDX-License-Identifier: Apache-2.0
+
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+import numpy as np  # type: ignore
+
+import onnx
+
+from ..base import Base
+from . import expect
+
+
+class Col2Im(Base):
+    """Col2Im operator with N-dimension support
+
+    The tests below can be reproduced in Python using https://github.com/f-dangel/unfoldNd/
+    """
+
+    @staticmethod
+    def export() -> None:
+        input = np.array(
+            [
+                [
+                    [1.0, 6.0, 11.0, 16.0, 21.0],  # (1, 5, 5)
+                    [2.0, 7.0, 12.0, 17.0, 22.0],
+                    [3.0, 8.0, 13.0, 18.0, 23.0],
+                    [4.0, 9.0, 14.0, 19.0, 24.0],
+                    [5.0, 0.0, 15.0, 20.0, 25.0],
+                ]
+            ]
+        ).astype(np.float32)
+
+        image_shape = np.array([5, 5]).astype(np.int64)
+        block_shape = np.array([1, 5]).astype(np.int64)
+        node = onnx.helper.make_node(
+            "Col2Im", ["input", "image_shape", "block_shape"], ["output"]
+        )
+
+        output = np.array(
+            [
+                [
+                    [
+                        [1.0, 2.0, 3.0, 4.0, 5.0],  # (1, 1, 5, 5)
+                        [6.0, 7.0, 8.0, 9.0, 0.0],
+                        [11.0, 12.0, 13.0, 14.0, 15.0],
+                        [16.0, 17.0, 18.0, 19.0, 20.0],
+                        [21.0, 22.0, 23.0, 24.0, 25.0],
+                    ]
+                ]
+            ]
+        ).astype(np.float32)
+
+        expect(
+            node,
+            inputs=[input, image_shape, block_shape],
+            outputs=[output],
+            name="test_col2im",
+        )
+
+    @staticmethod
+    def export_col2im_strides() -> None:
+        input = np.array(
+            [
+                [
+                    [0.0, 0.0, 0.0, 0.0],  # (1, 9, 4)
+                    [1.0, 1.0, 1.0, 1.0],
+                    [1.0, 1.0, 1.0, 1.0],
+                    [1.0, 1.0, 1.0, 1.0],
+                    [0.0, 0.0, 0.0, 0.0],
+                    [0.0, 0.0, 0.0, 0.0],
+                    [0.0, 0.0, 0.0, 0.0],
+                    [1.0, 1.0, 1.0, 1.0],
+                    [0.0, 0.0, 0.0, 0.0],
+                ]
+            ]
+        ).astype(np.float32)
+        image_shape = np.array([5, 5]).astype(np.int64)
+        block_shape = np.array([3, 3]).astype(np.int64)
+
+        output = np.array(
+            [
+                [
+                    [
+                        [0.0, 1.0, 1.0, 1.0, 1.0],  # (1, 1, 5, 5)
+                        [1.0, 0.0, 1.0, 0.0, 0.0],
+                        [0.0, 2.0, 1.0, 2.0, 1.0],
+                        [1.0, 0.0, 1.0, 0.0, 0.0],
+                        [0.0, 1.0, 0.0, 1.0, 0.0],
+                    ]
+                ]
+            ]
+        ).astype(np.float32)
+
+        node = onnx.helper.make_node(
+            "Col2Im",
+            ["input", "image_shape", "block_shape"],
+            ["output"],
+            strides=[2, 2],
+        )
+        expect(
+            node,
+            inputs=[input, image_shape, block_shape],
+            outputs=[output],
+            name="test_col2im_strides",
+        )
+
+    @staticmethod
+    def export_col2im_pads() -> None:
+        input = np.array(
+            [
+                [
+                    [
+                        1.0,
+                        6.0,
+                        11.0,
+                        16.0,
+                        21.0,
+                        26,
+                        31,
+                        36,
+                        41,
+                        46,
+                        51,
+                        56,
+                        61,
+                        66,
+                        71,
+                    ],  # (1, 5, 15)
+                    [
+                        2.0,
+                        7.0,
+                        12.0,
+                        17.0,
+                        22.0,
+                        27,
+                        32,
+                        37,
+                        42,
+                        47,
+                        52,
+                        57,
+                        62,
+                        67,
+                        72,
+                    ],
+                    [
+                        3.0,
+                        8.0,
+                        13.0,
+                        18.0,
+                        23.0,
+                        28,
+                        33,
+                        38,
+                        43,
+                        48,
+                        53,
+                        58,
+                        63,
+                        68,
+                        73,
+                    ],
+                    [
+                        4.0,
+                        9.0,
+                        14.0,
+                        19.0,
+                        24.0,
+                        29,
+                        34,
+                        39,
+                        44,
+                        49,
+                        54,
+                        59,
+                        64,
+                        69,
+                        74,
+                    ],
+                    [
+                        5.0,
+                        10.0,
+                        15.0,
+                        20.0,
+                        25.0,
+                        30,
+                        35,
+                        40,
+                        45,
+                        50,
+                        55,
+                        60,
+                        65,
+                        70,
+                        75,
+                    ],
+                ]
+            ]
+        ).astype(np.float32)
+        image_shape = np.array([5, 5]).astype(np.int64)
+        block_shape = np.array([1, 5]).astype(np.int64)
+
+        output = np.array(
+            [
+                [
+                    [
+                        [8.0, 21.0, 24.0, 27.0, 14.0],  # (1, 1, 5, 5)
+                        [38.0, 66.0, 69.0, 72.0, 54.0],
+                        [68.0, 111.0, 114.0, 117.0, 84.0],
+                        [98.0, 156.0, 159.0, 162.0, 114.0],
+                        [128.0, 201.0, 204.0, 207.0, 144.0],
+                    ]
+                ]
+            ]
+        ).astype(np.float32)
+
+        node = onnx.helper.make_node(
+            "Col2Im",
+            ["input", "image_shape", "block_shape"],
+            ["output"],
+            pads=[0, 1, 0, 1],
+        )
+        expect(
+            node,
+            inputs=[input, image_shape, block_shape],
+            outputs=[output],
+            name="test_col2im_pads",
+        )
+
+    @staticmethod
+    def export_col2im_dilations() -> None:
+        input = np.array(
+            [
+                [
+                    [1.0, 5.0, 9.0, 13.0, 17],  # (1, 4, 5)
+                    [2.0, 6.0, 10.0, 14.0, 18],
+                    [3.0, 7.0, 11.0, 15.0, 19],
+                    [4.0, 8.0, 12.0, 16.0, 20],
+                ]
+            ]
+        ).astype(np.float32)
+        image_shape = np.array([6, 6]).astype(np.int64)
+        block_shape = np.array([2, 2]).astype(np.int64)
+
+        output = np.array(
+            [
+                [
+                    [
+                        [1.0, 0.0, 0.0, 0.0, 0.0, 2.0],  # (1, 1, 6, 6)
+                        [8.0, 0.0, 0.0, 0.0, 0.0, 10.0],
+                        [16.0, 0.0, 0.0, 0.0, 0.0, 18.0],
+                        [24.0, 0.0, 0.0, 0.0, 0.0, 26.0],
+                        [32.0, 0.0, 0.0, 0.0, 0.0, 34.0],
+                        [19.0, 0.0, 0.0, 0.0, 0.0, 20.0],
+                    ]
+                ]
+            ]
+        ).astype(np.float32)
+
+        node = onnx.helper.make_node(
+            "Col2Im",
+            ["input", "image_shape", "block_shape"],
+            ["output"],
+            dilations=[1, 5],
+        )
+        expect(
+            node,
+            inputs=[input, image_shape, block_shape],
+            outputs=[output],
+            name="test_col2im_dilations",
+        )
+
+    @staticmethod
+    def export_col2im_5d() -> None:
+        input = np.array(
+            [
+                [
+                    [1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56],  # (1, 10, 12)
+                    [2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57],
+                    [3, 8, 13, 18, 23, 28, 33, 38, 43, 48, 53, 58],
+                    [4, 9, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59],
+                    [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60],
+                    [61, 66, 71, 76, 81, 86, 91, 96, 101, 106, 111, 116],
+                    [62, 67, 72, 77, 82, 87, 92, 97, 102, 107, 112, 117],
+                    [63, 68, 73, 78, 83, 88, 93, 98, 103, 108, 113, 118],
+                    [64, 69, 74, 79, 84, 89, 94, 99, 104, 109, 114, 119],
+                    [65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120],
+                ]
+            ]
+        ).astype(np.float32)
+        image_shape = np.array([3, 4, 5]).astype(np.int64)
+        block_shape = np.array([1, 1, 5]).astype(np.int64)
+
+        output = np.array(
+            [
+                [
+                    [
+                        [
+                            [1, 2, 3, 4, 5],  # (1, 2, 3, 4, 5)
+                            [6, 7, 8, 9, 10],
+                            [11, 12, 13, 14, 15],
+                            [16, 17, 18, 19, 20],
+                        ],
+                        [
+                            [21, 22, 23, 24, 25],
+                            [26, 27, 28, 29, 30],
+                            [31, 32, 33, 34, 35],
+                            [36, 37, 38, 39, 40],
+                        ],
+                        [
+                            [41, 42, 43, 44, 45],
+                            [46, 47, 48, 49, 50],
+                            [51, 52, 53, 54, 55],
+                            [56, 57, 58, 59, 60],
+                        ],
+                    ],
+                    [
+                        [
+                            [61, 62, 63, 64, 65],
+                            [66, 67, 68, 69, 70],
+                            [71, 72, 73, 74, 75],
+                            [76, 77, 78, 79, 80],
+                        ],
+                        [
+                            [81, 82, 83, 84, 85],
+                            [86, 87, 88, 89, 90],
+                            [91, 92, 93, 94, 95],
+                            [96, 97, 98, 99, 100],
+                        ],
+                        [
+                            [101, 102, 103, 104, 105],
+                            [106, 107, 108, 109, 110],
+                            [111, 112, 113, 114, 115],
+                            [116, 117, 118, 119, 120],
+                        ],
+                    ],
+                ]
+            ]
+        ).astype(np.float32)
+
+        node = onnx.helper.make_node(
+            "Col2Im", ["input", "image_shape", "block_shape"], ["output"]
+        )
+        expect(
+            node,
+            inputs=[input, image_shape, block_shape],
+            outputs=[output],
+            name="test_col2im_5d",
+        )
diff --git a/onnx/backend/test/data/node/test_acos/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_acos/test_data_set_0/output_0.pb
Binary files a/onnx/backend/test/data/node/test_acos/test_data_set_0/output_0.pb and b/onnx/backend/test/data/node/test_acos/test_data_set_0/output_0.pb differ
diff --git a/onnx/backend/test/data/node/test_acosh/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_acosh/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_acosh/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_acosh/test_data_set_0/output_0.pb
@@ -1 +1 @@
-ByJ���@D{,@�#@��@�8@��&@w�@��8@Zm=@@�22@*�@�@>;@���?ZT�?~/?�5@�81@Վ7@�P>@%�2@��@�d1@\<�?�N&@~2�?�G<@�6@�@���?��0@�@��@��?j[$@��#@sK$@>9<@o�)@��@��@+@V�?5�(@a�(@յ�?(ճ?�V@�k@��@\@��>@�^�?��?O��?�n'@��?<<@YZ�?
\ No newline at end of file
+ByJ���@D{,@�#@��@�8@��&@w�@��8@[m=@@�22@*�@�@>;@���?ZT�?~/?�5@�81@Վ7@�P>@&�2@��@�d1@\<�?�N&@}2�?�G<@�6@�@���?��0@�@��@��?j[$@��#@sK$@>9<@o�)@��@��@+@V�?4�(@a�(@յ�?'ճ?�V@�k@��@\@��>@�^�?��?O��?�n'@��?<<@YZ�?
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_asin/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_asin/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_asin/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_asin/test_data_set_0/output_0.pb
@@ -1 +1 @@
-ByJ�ĸ?PL?*�%?�?���>��3?J��>���?8s�?l{�>��i?�? �?�_�?���=ت�=�<��{?#Hd?��?���?fm?C��>F@e?[��=��1?M>`H�?T�?���>��>Z�b?%��>$�?c�<um*?�(?3*?��?D@?{H�>]��>k�E?9�v=;�:?q-<?�Y>�c>N�>X��>�S?/x�>L��?)Z�=�yW>��%>�06?�>a�>��|>
\ No newline at end of file
+ByJ�ø?OL?(�%?�?���>��3?J��>���?8s�?l{�>��i?�? �?�_�?���=ت�=�<��{?"Hd?��?���?fm?C��>E@e?[��=��1?M>`H�?T�?���>��>Z�b?%��>$�?c�<tm*?�(?3*?��?B@?{H�>]��>k�E?9�v=:�:?p-<?�Y>�c>N�>X��>�S?/x�>L��?)Z�=�yW>��%>�06?�>a�>��|>
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_asinh/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_asinh/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_asinh/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_asinh/test_data_set_0/output_0.pb
@@ -1 +1 @@
-ByJ�ɚ�?���>%�]?,��?)��?�~]��{X?ng��ӽ'��>��>���?A�3?b��=�c�>�ѧ><��?��P�ȝ>!<F��Wտ�??>H?��/��q�?�����\;=�>�W=�?��?�	>@G�>�L�����\����t>!��?M=�?���v����Pj��$��Q馿��?����I�پ�P���	7?LϠ�D<X��4N�4u�>bQ��-s����漎�>� �=���>���ߵ�
\ No newline at end of file
+ByJ�ɚ�?���>%�]?,��?(��?�~]��{X?ng��ӽ'��>��>���?A�3?b��=�c�>�ѧ><��?��P�ȝ>!<F��Wտ�??>H?��/��q�?�����\;=�>�V=�?��?�	>AG�>�L�����\����t>!��?M=�?���v����Pj��$��P馿��?����J�پ�P���	7?LϠ�D<X��4N�4u�>cQ��-s����漎�>� �=���>���ߵ�
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_atan/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_atan/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_atan/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_atan/test_data_set_0/output_0.pb
@@ -1 +1 @@
-ByJ�#�?~��>�OF?V�?�"�?�F�܂B?~��p�ҽ�z�>4~>|�w?��&?���=���>��>� {?�4O��W�>=�4��F���3?{6?�r#�z�?m�w��K;=�{=�}#~?�%y?j>��>��9�:8���l����>�fc?0�`?�3���N��� O�u��4���m�?jS�fӾH�e�c.)?���d�V�B�:�(�>Q��'8^����s3�>��=�b�>ٵ�t*��
\ No newline at end of file
+ByJ�#�?��>�OF?V�?�"�?�F�܂B?~��p�ҽ�z�>4~>|�w?��&?���=���>��>� {?�4O��W�>=�4��F���3?{6?�r#�z�?m�w��K;=�{=�}#~?�%y?j>��>��9�98���l����>�fc?0�`?�3���N��� O�u��4���m�?jS�fӾH�e�c.)?���d�V�A�:�(�>Q��&8^����s3�>��=�b�>ٵ�t*��
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_atanh/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_atanh/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_atanh/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_atanh/test_data_set_0/output_0.pb
@@ -1,2 +1,2 @@
-ByJ���?q�e?̍2?eo?�~�>+�D?�@�>B�?�W�?���>���?�?�%?/9�?0��=��=Ԧ�<�*�?5�?���?C�@�R�?���>��?w]�=�B?��>
-��??1?���>���>��?!�>;,%?��<Ϟ8?W6?�T8?۸�?;U?��>���>��\?��v=�N?��O?��Z>g�>(3�>�&�>)�%?��>��$@���=�Y>�&>��G?��>T^?�v>
\ No newline at end of file
+ByJ���?q�e?̍2?eo?�~�>+�D?�@�>B�?�W�?���>���?�?�%?/9�?0��=��=զ�<�*�?5�?���?C�@�R�?���>��?w]�=�B?��>
+��??1?���>���>��?!�>;,%?��<Ξ8?W6?�T8?ܸ�?;U?��>���>��\?��v=�N?��O?��Z>h�>'3�>�&�>)�%?��>��$@���=�Y>�&>��G?��>T^?�v>
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_col2im/model.onnx b/onnx/backend/test/data/node/test_col2im/model.onnx
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im/model.onnx differ
diff --git a/onnx/backend/test/data/node/test_col2im/test_data_set_0/input_0.pb b/onnx/backend/test/data/node/test_col2im/test_data_set_0/input_0.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im/test_data_set_0/input_0.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im/test_data_set_0/input_1.pb b/onnx/backend/test/data/node/test_col2im/test_data_set_0/input_1.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im/test_data_set_0/input_1.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im/test_data_set_0/input_2.pb b/onnx/backend/test/data/node/test_col2im/test_data_set_0/input_2.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im/test_data_set_0/input_2.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_col2im/test_data_set_0/output_0.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im/test_data_set_0/output_0.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_5d/model.onnx b/onnx/backend/test/data/node/test_col2im_5d/model.onnx
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_5d/model.onnx differ
diff --git a/onnx/backend/test/data/node/test_col2im_5d/test_data_set_0/input_0.pb b/onnx/backend/test/data/node/test_col2im_5d/test_data_set_0/input_0.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_5d/test_data_set_0/input_0.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_5d/test_data_set_0/input_1.pb b/onnx/backend/test/data/node/test_col2im_5d/test_data_set_0/input_1.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_5d/test_data_set_0/input_1.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_5d/test_data_set_0/input_2.pb b/onnx/backend/test/data/node/test_col2im_5d/test_data_set_0/input_2.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_5d/test_data_set_0/input_2.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_5d/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_col2im_5d/test_data_set_0/output_0.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_5d/test_data_set_0/output_0.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_dilations/model.onnx b/onnx/backend/test/data/node/test_col2im_dilations/model.onnx
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_dilations/model.onnx differ
diff --git a/onnx/backend/test/data/node/test_col2im_dilations/test_data_set_0/input_0.pb b/onnx/backend/test/data/node/test_col2im_dilations/test_data_set_0/input_0.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_dilations/test_data_set_0/input_0.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_dilations/test_data_set_0/input_1.pb b/onnx/backend/test/data/node/test_col2im_dilations/test_data_set_0/input_1.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_dilations/test_data_set_0/input_1.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_dilations/test_data_set_0/input_2.pb b/onnx/backend/test/data/node/test_col2im_dilations/test_data_set_0/input_2.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_dilations/test_data_set_0/input_2.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_dilations/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_col2im_dilations/test_data_set_0/output_0.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_dilations/test_data_set_0/output_0.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_pads/model.onnx b/onnx/backend/test/data/node/test_col2im_pads/model.onnx
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_pads/model.onnx differ
diff --git a/onnx/backend/test/data/node/test_col2im_pads/test_data_set_0/input_0.pb b/onnx/backend/test/data/node/test_col2im_pads/test_data_set_0/input_0.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_pads/test_data_set_0/input_0.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_pads/test_data_set_0/input_1.pb b/onnx/backend/test/data/node/test_col2im_pads/test_data_set_0/input_1.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_pads/test_data_set_0/input_1.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_pads/test_data_set_0/input_2.pb b/onnx/backend/test/data/node/test_col2im_pads/test_data_set_0/input_2.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_pads/test_data_set_0/input_2.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_pads/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_col2im_pads/test_data_set_0/output_0.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_pads/test_data_set_0/output_0.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_strides/model.onnx b/onnx/backend/test/data/node/test_col2im_strides/model.onnx
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_strides/model.onnx differ
diff --git a/onnx/backend/test/data/node/test_col2im_strides/test_data_set_0/input_0.pb b/onnx/backend/test/data/node/test_col2im_strides/test_data_set_0/input_0.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_strides/test_data_set_0/input_0.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_strides/test_data_set_0/input_1.pb b/onnx/backend/test/data/node/test_col2im_strides/test_data_set_0/input_1.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_strides/test_data_set_0/input_1.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_strides/test_data_set_0/input_2.pb b/onnx/backend/test/data/node/test_col2im_strides/test_data_set_0/input_2.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_strides/test_data_set_0/input_2.pb differ
diff --git a/onnx/backend/test/data/node/test_col2im_strides/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_col2im_strides/test_data_set_0/output_0.pb
new file mode 100644
Binary files /dev/null and b/onnx/backend/test/data/node/test_col2im_strides/test_data_set_0/output_0.pb differ
diff --git a/onnx/backend/test/data/node/test_cosh/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_cosh/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_cosh/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_cosh/test_data_set_0/output_0.pb
@@ -1 +1 @@
-ByJ��<@@�b�?C\�?!!�@'T@�%�?�?�?x�?���?9�?�T�?gz@1�?��?<ь?)1�?��@��?�R�??��?���@LT�?��?]�?_|�@w}@P"�?�?�?U@�r@&��?C�?ص?�]l@@Ӈ?S��?@��?q9�?ٸ�?��?��?�@�6@H�e@���?�z�?�J�?��?2'@P�?^׶?T��?��?��?�?/�?�H�?l�?_��?���?
\ No newline at end of file
+ByJ��<@@�b�?B\�?!!�@'T@�%�?�?�?x�?���?9�?�T�?gz@1�?��?;ь?)1�?��@��?�R�?>��?���@LT�?��?]�?^|�@w}@P"�?�?�?U@�r@%��?C�?ص?�]l@@Ӈ?S��?@��?q9�?ظ�?��?��?�@�6@G�e@���?�z�?�J�?��?2'@Q�?^׶?T��?��?��?�?/�?�H�?l�?_��?���?
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_cosh_example/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_cosh_example/test_data_set_0/output_0.pb
Binary files a/onnx/backend/test/data/node/test_cosh_example/test_data_set_0/output_0.pb and b/onnx/backend/test/data/node/test_cosh_example/test_data_set_0/output_0.pb differ
diff --git a/onnx/backend/test/data/node/test_lstm_batchwise/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_lstm_batchwise/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_lstm_batchwise/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_lstm_batchwise/test_data_set_0/output_0.pb
@@ -1 +1 @@
-BYJT�٪>�٪>�٪>�٪>�٪>�٪>�٪>)U?)U?)U?)U?)U?)U?)U?��7?��7?��7?��7?��7?��7?��7?
\ No newline at end of file
+BYJT�٪>�٪>�٪>�٪>�٪>�٪>�٪>)U?)U?)U?)U?)U?)U?)U?��7?��7?��7?��7?��7?��7?��7?
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_lstm_batchwise/test_data_set_0/output_1.pb b/onnx/backend/test/data/node/test_lstm_batchwise/test_data_set_0/output_1.pb
--- a/onnx/backend/test/data/node/test_lstm_batchwise/test_data_set_0/output_1.pb
+++ b/onnx/backend/test/data/node/test_lstm_batchwise/test_data_set_0/output_1.pb
@@ -1 +1 @@
-BY_hJT�٪>�٪>�٪>�٪>�٪>�٪>�٪>)U?)U?)U?)U?)U?)U?)U?��7?��7?��7?��7?��7?��7?��7?
\ No newline at end of file
+BY_hJT�٪>�٪>�٪>�٪>�٪>�٪>�٪>)U?)U?)U?)U?)U?)U?)U?��7?��7?��7?��7?��7?��7?��7?
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_lstm_defaults/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_lstm_defaults/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_lstm_defaults/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_lstm_defaults/test_data_set_0/output_0.pb
@@ -1 +1 @@
-BY_hJ$��=��=��=��>��>��>.u�>.u�>.u�>
\ No newline at end of file
+BY_hJ$��=��=��=��>��>��>.u�>.u�>.u�>
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_lstm_with_initial_bias/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_lstm_with_initial_bias/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_lstm_with_initial_bias/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_lstm_with_initial_bias/test_data_set_0/output_0.pb
@@ -1 +1 @@
-BY_hJ0��>��>��>��>�f	?�f	?�f	?�f	?|�*?|�*?|�*?|�*?
\ No newline at end of file
+BY_hJ0��>��>��>��>�f	?�f	?�f	?�f	?|�*?|�*?|�*?|�*?
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_lstm_with_peepholes/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_lstm_with_peepholes/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_lstm_with_peepholes/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_lstm_with_peepholes/test_data_set_0/output_0.pb
@@ -1 +1 @@
-BY_hJ	�>	�>	�>.?.?.?
\ No newline at end of file
+BY_hJ	�>	�>	�>.?.?.?
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_mish/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_mish/test_data_set_0/output_0.pb
Binary files a/onnx/backend/test/data/node/test_mish/test_data_set_0/output_0.pb and b/onnx/backend/test/data/node/test_mish/test_data_set_0/output_0.pb differ
diff --git a/onnx/backend/test/data/node/test_mish_expanded/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_mish_expanded/test_data_set_0/output_0.pb
Binary files a/onnx/backend/test/data/node/test_mish_expanded/test_data_set_0/output_0.pb and b/onnx/backend/test/data/node/test_mish_expanded/test_data_set_0/output_0.pb differ
diff --git a/onnx/backend/test/data/node/test_reduce_log_sum_exp_do_not_keepdims_example/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_reduce_log_sum_exp_do_not_keepdims_example/test_data_set_0/output_0.pb
Binary files a/onnx/backend/test/data/node/test_reduce_log_sum_exp_do_not_keepdims_example/test_data_set_0/output_0.pb and b/onnx/backend/test/data/node/test_reduce_log_sum_exp_do_not_keepdims_example/test_data_set_0/output_0.pb differ
diff --git a/onnx/backend/test/data/node/test_reduce_log_sum_exp_do_not_keepdims_random/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_reduce_log_sum_exp_do_not_keepdims_random/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_reduce_log_sum_exp_do_not_keepdims_random/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_reduce_log_sum_exp_do_not_keepdims_random/test_data_set_0/output_0.pb
@@ -1,2 +1,2 @@
-BreducedJ0�eMIz�@�&~X@{��U��忎c;��^@n6���"@��
+BreducedJ0�eMIz�@�&~X@{��U��忎c;��^@n6���"@��
 �1�?
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_reduce_log_sum_exp_keepdims_example/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_reduce_log_sum_exp_keepdims_example/test_data_set_0/output_0.pb
Binary files a/onnx/backend/test/data/node/test_reduce_log_sum_exp_keepdims_example/test_data_set_0/output_0.pb and b/onnx/backend/test/data/node/test_reduce_log_sum_exp_keepdims_example/test_data_set_0/output_0.pb differ
diff --git a/onnx/backend/test/data/node/test_reduce_log_sum_exp_keepdims_random/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_reduce_log_sum_exp_keepdims_random/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_reduce_log_sum_exp_keepdims_random/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_reduce_log_sum_exp_keepdims_random/test_data_set_0/output_0.pb
@@ -1,2 +1,2 @@
-BreducedJ0�eMIz�@�&~X@{��U��忎c;��^@n6���"@��
+BreducedJ0�eMIz�@�&~X@{��U��忎c;��^@n6���"@��
 �1�?
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_reduce_log_sum_exp_negative_axes_keepdims_example/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_reduce_log_sum_exp_negative_axes_keepdims_example/test_data_set_0/output_0.pb
Binary files a/onnx/backend/test/data/node/test_reduce_log_sum_exp_negative_axes_keepdims_example/test_data_set_0/output_0.pb and b/onnx/backend/test/data/node/test_reduce_log_sum_exp_negative_axes_keepdims_example/test_data_set_0/output_0.pb differ
diff --git a/onnx/backend/test/data/node/test_reduce_log_sum_exp_negative_axes_keepdims_random/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_reduce_log_sum_exp_negative_axes_keepdims_random/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_reduce_log_sum_exp_negative_axes_keepdims_random/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_reduce_log_sum_exp_negative_axes_keepdims_random/test_data_set_0/output_0.pb
@@ -1,2 +1,2 @@
-BreducedJ0�eMIz�@�&~X@{��U��忎c;��^@n6���"@��
+BreducedJ0�eMIz�@�&~X@{��U��忎c;��^@n6���"@��
 �1�?
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_rnn_seq_length/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_rnn_seq_length/test_data_set_0/output_0.pb
Binary files a/onnx/backend/test/data/node/test_rnn_seq_length/test_data_set_0/output_0.pb and b/onnx/backend/test/data/node/test_rnn_seq_length/test_data_set_0/output_0.pb differ
diff --git a/onnx/backend/test/data/node/test_simple_rnn_batchwise/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_simple_rnn_batchwise/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_simple_rnn_batchwise/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_simple_rnn_batchwise/test_data_set_0/output_0.pb
@@ -1 +1 @@
-BYJ0˷g?˷g?˷g?˷g?��?��?��?��?��?��?��?��?
\ No newline at end of file
+BYJ0̷g?̷g?̷g?̷g?��?��?��?��?��?��?��?��?
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_simple_rnn_batchwise/test_data_set_0/output_1.pb b/onnx/backend/test/data/node/test_simple_rnn_batchwise/test_data_set_0/output_1.pb
--- a/onnx/backend/test/data/node/test_simple_rnn_batchwise/test_data_set_0/output_1.pb
+++ b/onnx/backend/test/data/node/test_simple_rnn_batchwise/test_data_set_0/output_1.pb
@@ -1 +1 @@
-BY_hJ0˷g?˷g?˷g?˷g?��?��?��?��?��?��?��?��?
\ No newline at end of file
+BY_hJ0̷g?̷g?̷g?̷g?��?��?��?��?��?��?��?��?
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_simple_rnn_defaults/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_simple_rnn_defaults/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_simple_rnn_defaults/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_simple_rnn_defaults/test_data_set_0/output_0.pb
@@ -1 +1 @@
-BY_hJ0�&�>�&�>�&�>�&�>ٷ?ٷ?ٷ?ٷ?��L?��L?��L?��L?
\ No newline at end of file
+BY_hJ0�&�>�&�>�&�>�&�>ٷ?ٷ?ٷ?ٷ?��L?��L?��L?��L?
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_sinh/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_sinh/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_sinh/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_sinh/test_data_set_0/output_0.pb
@@ -1 +1 @@
-ByJ�$E5@gd�>�B�?̹�@�,J@����6��?����ӽ�.�>�>��@//V?F��=E��>w�>�b@�S��>�7v�H��a3?��y?6�O��-�@��~;=,�@�uH@W�@DM>cD�>�)����c����"� >0R�?^��?�N˾�%��`2���O��ru*��\@g1����ݸͿ��[?�W�5~[�\�����>��¼�>����>�S�=�<�>V-��ҽ�
\ No newline at end of file
+ByJ�%E5@hd�>�B�?͹�@�,J@����6��?����ӽ�.�>�>��@./V?F��=E��>w�>�b@�S��>�7v�H��a3?��y?6�O��-�@��~;=,�@�uH@W�@DM>cD�>�)����c����"� >0R�?_��?�N˾�%��`2���O��ru*��\@f1����ݸͿ��[?�W�6~[�\�����>��¼�>����>�S�=�<�>V-��ҽ�
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_tan/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_tan/test_data_set_0/output_0.pb
--- a/onnx/backend/test/data/node/test_tan/test_data_set_0/output_0.pb
+++ b/onnx/backend/test/data/node/test_tan/test_data_set_0/output_0.pb
@@ -1 +1 @@
-ByJ�R������>�R�?=����JQ�f�����?-/�j%ԽF��>�>��A[�s?pm�=�u�>5z�>&PAzU����>s꒿��*?�D? �?��j��I�����̎;=]�A��T�A�0A��>�h�>�P��Q@@!���6k!>��4@��%@��оD����e޿������@�> �7���RmB���{?Y~�Ap1]��Ο�͛�>pw�՟������>�m�=�ğ>xZ<�R¾
\ No newline at end of file
+ByJ�R������>�R�?=����JQ�f�����?-/�k%ԽF��>��>��A[�s?pm�=�u�>5z�>&PAzU����>s꒿��*?�D?!�?��j��I�����̎;=]�A��T�A�0A��>�h�>�P��P@@!���6k!>��4@��%@��оD����e޿������@�> �7���RmB���{?Y~�Ap1]��Ο�̛�>pw�ԟ������>�m�=�ğ>xZ<�~R¾
\ No newline at end of file
diff --git a/onnx/backend/test/data/node/test_tanh/test_data_set_0/output_0.pb b/onnx/backend/test/data/node/test_tanh/test_data_set_0/output_0.pb
Binary files a/onnx/backend/test/data/node/test_tanh/test_data_set_0/output_0.pb and b/onnx/backend/test/data/node/test_tanh/test_data_set_0/output_0.pb differ
diff --git a/onnx/test/automatic_upgrade_test.py b/onnx/test/automatic_upgrade_test.py
--- a/onnx/test/automatic_upgrade_test.py
+++ b/onnx/test/automatic_upgrade_test.py
@@ -256,6 +256,12 @@ def test_Clip_4(self) -> None:
             "Clip", 1, attrs={"consumed_inputs": [0], "min": -1.4, "max": 2.6}
         )
 
+    def test_Col2Im_4D(self) -> None:
+        self._test_op_upgrade("Col2Im", 18, [[1, 5, 5], [2], [2]], [[1, 1, 5, 5]])
+
+    def test_Col2Im_5D(self) -> None:
+        self._test_op_upgrade("Col2Im", 18, [[1, 10, 12], [3], [3]], [[1, 2, 3, 4, 5]])
+
     def test_Compress(self) -> None:
         self._test_op_upgrade(
             "Compress",
diff --git a/onnx/test/shape_inference_test.py b/onnx/test/shape_inference_test.py
--- a/onnx/test/shape_inference_test.py
+++ b/onnx/test/shape_inference_test.py
@@ -293,6 +293,126 @@ def test_cast_like(self) -> None:
             graph, [make_tensor_value_info("y", TensorProto.FLOAT16, (2, 4, 3))]
         )
 
+    def test_col2im(self) -> None:
+        graph = self._make_graph(
+            [
+                ("input", TensorProto.FLOAT, (1, 5, 5)),
+                ("output_shape", TensorProto.INT64, (2,)),
+                ("kernel_shape", TensorProto.INT64, (2,)),
+            ],
+            [
+                make_node(
+                    "Col2Im", ["input", "output_shape", "kernel_shape"], ["output"]
+                )
+            ],
+            [],
+            initializer=[
+                make_tensor("output_shape", TensorProto.INT64, (2,), (5, 5)),
+                make_tensor("kernel_shape", TensorProto.INT64, (2,), (1, 5)),
+            ],
+        )
+        self._assert_inferred(
+            graph, [make_tensor_value_info("output", TensorProto.FLOAT, (1, 1, 5, 5))]
+        )
+
+    def test_col2im_strides(self) -> None:
+        graph = self._make_graph(
+            [
+                ("input", TensorProto.FLOAT, (1, 9, 4)),
+                ("output_shape", TensorProto.INT64, (2,)),
+                ("kernel_shape", TensorProto.INT64, (2,)),
+            ],
+            [
+                make_node(
+                    "Col2Im",
+                    ["input", "output_shape", "kernel_shape"],
+                    ["output"],
+                    strides=[2, 2],
+                )
+            ],
+            [],
+            initializer=[
+                make_tensor("output_shape", TensorProto.INT64, (2,), (5, 5)),
+                make_tensor("kernel_shape", TensorProto.INT64, (2,), (3, 3)),
+            ],
+        )
+        self._assert_inferred(
+            graph, [make_tensor_value_info("output", TensorProto.FLOAT, (1, 1, 5, 5))]
+        )
+
+    def test_col2im_pads(self) -> None:
+        graph = self._make_graph(
+            [
+                ("input", TensorProto.FLOAT, (1, 5, 15)),
+                ("output_shape", TensorProto.INT64, (2,)),
+                ("kernel_shape", TensorProto.INT64, (2,)),
+            ],
+            [
+                make_node(
+                    "Col2Im",
+                    ["input", "output_shape", "kernel_shape"],
+                    ["output"],
+                    pads=[0, 1, 0, 1],
+                )
+            ],
+            [],
+            initializer=[
+                make_tensor("output_shape", TensorProto.INT64, (2,), (5, 5)),
+                make_tensor("kernel_shape", TensorProto.INT64, (2,), (1, 5)),
+            ],
+        )
+        self._assert_inferred(
+            graph, [make_tensor_value_info("output", TensorProto.FLOAT, (1, 1, 5, 5))]
+        )
+
+    def test_col2im_dilations(self) -> None:
+        graph = self._make_graph(
+            [
+                ("input", TensorProto.FLOAT, (1, 4, 5)),
+                ("output_shape", TensorProto.INT64, (2,)),
+                ("kernel_shape", TensorProto.INT64, (2,)),
+            ],
+            [
+                make_node(
+                    "Col2Im",
+                    ["input", "output_shape", "kernel_shape"],
+                    ["output"],
+                    dilations=[1, 5],
+                )
+            ],
+            [],
+            initializer=[
+                make_tensor("output_shape", TensorProto.INT64, (2,), (6, 6)),
+                make_tensor("kernel_shape", TensorProto.INT64, (2,), (2, 2)),
+            ],
+        )
+        self._assert_inferred(
+            graph, [make_tensor_value_info("output", TensorProto.FLOAT, (1, 1, 6, 6))]
+        )
+
+    def test_col2im_5d(self) -> None:
+        graph = self._make_graph(
+            [
+                ("input", TensorProto.FLOAT, (1, 10, 12)),
+                ("output_shape", TensorProto.INT64, (3,)),
+                ("kernel_shape", TensorProto.INT64, (3,)),
+            ],
+            [
+                make_node(
+                    "Col2Im", ["input", "output_shape", "kernel_shape"], ["output"]
+                )
+            ],
+            [],
+            initializer=[
+                make_tensor("output_shape", TensorProto.INT64, (3,), (3, 4, 5)),
+                make_tensor("kernel_shape", TensorProto.INT64, (3,), (1, 1, 5)),
+            ],
+        )
+        self._assert_inferred(
+            graph,
+            [make_tensor_value_info("output", TensorProto.FLOAT, (1, 2, 3, 4, 5))],
+        )
+
     def test_concat(self) -> None:
         graph = self._make_graph(
             [("x", TensorProto.FLOAT, (2, 4, 3)), ("y", TensorProto.FLOAT, (7, 4, 3))],