Python 是否有可能延长;im2col";及;col2im“;到N-D图像?

Python 是否有可能延长;im2col";及;col2im“;到N-D图像?,python,keras,convolution,max-pooling,Python,Keras,Convolution,Max Pooling,“Im2col”已经在Python中高效地实现了二维图像。我想知道是否有可能将其扩展到任意N-D图像?许多应用程序都涉及高维数据(例如卷积、过滤、最大池等)。因此,这个问题的目的实际上只是公开发布我对这个问题的解决方案。我似乎在谷歌上找不到这样的解决方案,所以我决定自己尝试一下。事实证明,从我的问题中提到的帖子中的“方法2”扩展,实现实际上非常简单 有效实施N-D“im2col” 高效实施N-D“col2im” 验证它是否有效 让我们定义一个任意的三维输入: x = np.arange(216)

“Im2col”已经在Python中高效地实现了二维图像。我想知道是否有可能将其扩展到任意N-D图像?许多应用程序都涉及高维数据(例如卷积、过滤、最大池等)。

因此,这个问题的目的实际上只是公开发布我对这个问题的解决方案。我似乎在谷歌上找不到这样的解决方案,所以我决定自己尝试一下。事实证明,从我的问题中提到的帖子中的“方法2”扩展,实现实际上非常简单

有效实施N-D“im2col”

高效实施N-D“col2im”

验证它是否有效

让我们定义一个任意的三维输入:

x = np.arange(216).reshape(6, 6, 6)
print(x)

[[[  0   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 121 122 123 124 125]
  [126 127 128 129 130 131]
  [132 133 134 135 136 137]
  [138 139 140 141 142 143]]

 [[144 145 146 147 148 149]
  [150 151 152 153 154 155]
  [156 157 158 159 160 161]
  [162 163 164 165 166 167]
  [168 169 170 171 172 173]
  [174 175 176 177 178 179]]

 [[180 181 182 183 184 185]
  [186 187 188 189 190 191]
  [192 193 194 195 196 197]
  [198 199 200 201 202 203]
  [204 205 206 207 208 209]
  [210 211 212 213 214 215]]]
让我们使用非均匀窗口和相等步幅提取所有面片:

y = im2col(x, [1, 3, 2], strides = [1, 3, 2])
print(y.T) # transposed for ease of visualization

[[  0   1   6   7  12  13]
 [  2   3   8   9  14  15]
 [  4   5  10  11  16  17]
 [ 18  19  24  25  30  31]
 [ 20  21  26  27  32  33]
 [ 22  23  28  29  34  35]
 [ 36  37  42  43  48  49]
 [ 38  39  44  45  50  51]
 [ 40  41  46  47  52  53]
 [ 54  55  60  61  66  67]
 [ 56  57  62  63  68  69]
 [ 58  59  64  65  70  71]
 [ 72  73  78  79  84  85]
 [ 74  75  80  81  86  87]
 [ 76  77  82  83  88  89]
 [ 90  91  96  97 102 103]
 [ 92  93  98  99 104 105]
 [ 94  95 100 101 106 107]
 [108 109 114 115 120 121]
 [110 111 116 117 122 123]
 [112 113 118 119 124 125]
 [126 127 132 133 138 139]
 [128 129 134 135 140 141]
 [130 131 136 137 142 143]
 [144 145 150 151 156 157]
 [146 147 152 153 158 159]
 [148 149 154 155 160 161]
 [162 163 168 169 174 175]
 [164 165 170 171 176 177]
 [166 167 172 173 178 179]
 [180 181 186 187 192 193]
 [182 183 188 189 194 195]
 [184 185 190 191 196 197]
 [198 199 204 205 210 211]
 [200 201 206 207 212 213]
 [202 203 208 209 214 215]]
让我们将其转换回(下采样)图像:

如您所见,最终输出确实是我们期望的下采样图像(您可以通过逐个值轻松检查)。我选择的维度和步幅纯粹是说明性的。没有理由说窗口大小必须与步幅相同,或者不能超过3维

应用程序

如果你想实际使用它,你所要做的就是截取im2col的输出,然后再将其转换回图像。例如,如果要进行池化,可以在第0个轴上取平均值或最大值。如果你想做卷积运算,你只需要把它乘以平坦的卷积滤波器


在Tensorflow等软件的保护下,可能会有比“im2col”更快的更有效的替代方案。这并不是最有效的实现。当然,您可以通过消除“im2col”中的中间重塑步骤来进一步优化我的代码,但这对我来说不是很明显,所以我就不说了。如果你有更好的解决方案,请告诉我。无论如何,希望这能帮助其他人寻找同样的答案

所以这个问题的目的实际上只是公开发布我对这个问题的解决方案。我似乎在谷歌上找不到这样的解决方案,所以我决定自己尝试一下。事实证明,从我的问题中提到的帖子中的“方法2”扩展,实现实际上非常简单

有效实施N-D“im2col”

高效实施N-D“col2im”

验证它是否有效

让我们定义一个任意的三维输入:

x = np.arange(216).reshape(6, 6, 6)
print(x)

[[[  0   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 121 122 123 124 125]
  [126 127 128 129 130 131]
  [132 133 134 135 136 137]
  [138 139 140 141 142 143]]

 [[144 145 146 147 148 149]
  [150 151 152 153 154 155]
  [156 157 158 159 160 161]
  [162 163 164 165 166 167]
  [168 169 170 171 172 173]
  [174 175 176 177 178 179]]

 [[180 181 182 183 184 185]
  [186 187 188 189 190 191]
  [192 193 194 195 196 197]
  [198 199 200 201 202 203]
  [204 205 206 207 208 209]
  [210 211 212 213 214 215]]]
让我们使用非均匀窗口和相等步幅提取所有面片:

y = im2col(x, [1, 3, 2], strides = [1, 3, 2])
print(y.T) # transposed for ease of visualization

[[  0   1   6   7  12  13]
 [  2   3   8   9  14  15]
 [  4   5  10  11  16  17]
 [ 18  19  24  25  30  31]
 [ 20  21  26  27  32  33]
 [ 22  23  28  29  34  35]
 [ 36  37  42  43  48  49]
 [ 38  39  44  45  50  51]
 [ 40  41  46  47  52  53]
 [ 54  55  60  61  66  67]
 [ 56  57  62  63  68  69]
 [ 58  59  64  65  70  71]
 [ 72  73  78  79  84  85]
 [ 74  75  80  81  86  87]
 [ 76  77  82  83  88  89]
 [ 90  91  96  97 102 103]
 [ 92  93  98  99 104 105]
 [ 94  95 100 101 106 107]
 [108 109 114 115 120 121]
 [110 111 116 117 122 123]
 [112 113 118 119 124 125]
 [126 127 132 133 138 139]
 [128 129 134 135 140 141]
 [130 131 136 137 142 143]
 [144 145 150 151 156 157]
 [146 147 152 153 158 159]
 [148 149 154 155 160 161]
 [162 163 168 169 174 175]
 [164 165 170 171 176 177]
 [166 167 172 173 178 179]
 [180 181 186 187 192 193]
 [182 183 188 189 194 195]
 [184 185 190 191 196 197]
 [198 199 204 205 210 211]
 [200 201 206 207 212 213]
 [202 203 208 209 214 215]]
让我们将其转换回(下采样)图像:

如您所见,最终输出确实是我们期望的下采样图像(您可以通过逐个值轻松检查)。我选择的维度和步幅纯粹是说明性的。没有理由说窗口大小必须与步幅相同,或者不能超过3维

应用程序

如果你想实际使用它,你所要做的就是截取im2col的输出,然后再将其转换回图像。例如,如果要进行池化,可以在第0个轴上取平均值或最大值。如果你想做卷积运算,你只需要把它乘以平坦的卷积滤波器

在Tensorflow等软件的保护下,可能会有比“im2col”更快的更有效的替代方案。这并不是最有效的实现。当然,您可以通过消除“im2col”中的中间重塑步骤来进一步优化我的代码,但这对我来说不是很明显,所以我就不说了。如果你有更好的解决方案,请告诉我。无论如何,希望这能帮助其他人寻找同样的答案

z = col2im(y, x.shape, [1, 3, 2], strides = [1, 3, 2])
print(z)

[[[  0   2   4]
  [ 18  20  22]]

 [[ 36  38  40]
  [ 54  56  58]]

 [[ 72  74  76]
  [ 90  92  94]]

 [[108 110 112]
  [126 128 130]]

 [[144 146 148]
  [162 164 166]]

 [[180 182 184]
  [198 200 202]]]