Tensorflow:如何池化深度?
Tensorflow: How to Pool over Depth?
我定义了以下参数,用于在图像深度 (rgb) 上进行最大池化,以便在密集层和读出之前进行压缩...我失败了,错误是我无法池化深度和其他一切:
sunset_poolmax_1x1x3_div_2x2x3_params = \
{'pool_function':tf.nn.max_pool,
'ksize':[1,1,1,3],
'strides':[1,1,1,3],
'padding': 'SAME'}
我将步幅更改为 [1,1,1,3]
,因此深度是泳池减少的唯一维度……但它仍然不起作用。我无法通过微小的图像获得良好的效果,我必须将所有内容压缩到以保持颜色...
实际错误:
ValueError: Current implementation does not support pooling in the batch and depth dimensions.
tf.nn.max_pool 不支持在深度维度上进行池化,这就是您收到错误的原因。
您可以使用最大减少来实现您想要的:
tf.reduce_max(input_tensor, reduction_indices=[3], keep_dims=True)
上面的keep_dims
参数确保张量的秩被保留。这确保最大缩减的行为将与 tf.nn.max_pool 操作在支持深度维度上的池化时将执行的操作一致。
这里是 tensorflow 原始问题的一个简短示例。我在具有 3 个通道的大小 225 x 225
的库存 RGB 图像上对其进行了测试。
导入标准库,启用eager_execution
快速查看结果
import tensorflow as tf
from scipy.misc import imread
import matplotlib.pyplot as plt
import numpy as np
tf.enable_eager_execution()
读取图像并从 uint8
投射到 tf.float32
x = tf.cast(imread('tiger.jpeg'), tf.float32)
x = tf.reshape(x, shape=[-1, x.shape[0], x.shape[1], x.shape[2]])
print(x.shape)
input_channels = x.shape[3]
为深度卷积创建过滤器
filters = tf.contrib.eager.Variable(tf.random_normal(shape=[3, 3, input_channels, 4]))
print(x.shape)
使用 channel multiplier
执行深度卷积 4. 请注意,填充已保持为 'SAME'
。可以随意更改。
x = tf.nn.depthwise_conv2d(input=x, filter=filters, strides=[1, 1, 1, 1], padding='SAME', name='conv_1')
print(x.shape)
执行max_pooling2d
。由于池化层的输出是(input_size - pool_size + 2 * padding)/stride + 1
,padding是'valid'
,我们应该得到(225 - 2 + 0)/1 + 1 = 223
.
的输出
x = tf.layers.max_pooling2d(inputs=x, pool_size=2, strides=1,padding='valid', name='maxpool1')
print(x.shape)
绘制数字以确认。
fig, ax = plt.subplots(nrows=4, ncols=3)
q = 0
for ii in range(4):
for jj in range(3):
ax[ii, jj].imshow(np.squeeze(x[:,:,:,q]))
ax[ii,jj].set_axis_off()
q += 1
plt.tight_layout()
plt.show()
TensorFlow 现在支持 tf.nn.max_pool()
的深度最大池化。例如,这里是如何使用池化内核大小 3、步幅 3 和有效填充来实现它:
import tensorflow as tf
output = tf.nn.max_pool(images,
ksize=(1, 1, 1, 3),
strides=(1, 1, 1, 3),
padding="VALID")
您可以在 Keras 模型中使用它,方法是将其包装在 Lambda
层中:
from tensorflow import keras
depth_pool = keras.layers.Lambda(
lambda X: tf.nn.max_pool(X,
ksize=(1, 1, 1, 3),
strides=(1, 1, 1, 3),
padding="VALID"))
model = keras.models.Sequential([
..., # other layers
depth_pool,
... # other layers
])
或者,您可以编写自定义 Keras 层:
class DepthMaxPool(keras.layers.Layer):
def __init__(self, pool_size, strides=None, padding="VALID", **kwargs):
super().__init__(**kwargs)
if strides is None:
strides = pool_size
self.pool_size = pool_size
self.strides = strides
self.padding = padding
def call(self, inputs):
return tf.nn.max_pool(inputs,
ksize=(1, 1, 1, self.pool_size),
strides=(1, 1, 1, self.pool_size),
padding=self.padding)
然后您可以像使用任何其他层一样使用它:
model = keras.models.Sequential([
..., # other layers
DepthMaxPool(3),
... # other layers
])
这是《使用 scikit 学习 keras 和 tensorflow 进行机器学习实践》一书的节选。
Keras 不包含深度最大池化层,但 TensorFlow 的底层
深度学习 API 做:只需使用 tf.nn.max_pool() 函数,并指定
内核大小和步幅为 4 元组(即大小为 4 的元组)。每个的前三个值
应为 1:这表示内核大小和步长沿批次、高度和
宽度尺寸应该是 1。最后一个值应该是任何内核大小和
沿深度维度所需的步幅——例如,3(这必须是除数
输入深度;如果前一层输出 20 个特征图,它将不起作用,因为
20 不是 3 的倍数):
output = tf.nn.max_pool(images,
ksize=(1, 1, 1, 3),
strides=(1, 1, 1, 3),
padding="valid")
如果您想将其作为一个层包含在您的 Keras 模型中,请将其包装在 Lambda 层中
(或创建自定义 Keras 层):
depth_pool = keras.layers.Lambda(
lambda X: tf.nn.max_pool(X, ksize=(1, 1, 1, 3), strides=(1, 1, 1, 3),
padding="valid"))
您可以使用自定义 Keras 层:
class DepthPool(tf.keras.layers.Layer):
def __init__(self, pool_size=2, **kwargs):
super().__init__(**kwargs)
self.pool_size = pool_size
def call(self, inputs):
old_shape = tf.shape(inputs)
num_channels = old_shape[-1]
num_channel_groups = num_channels // self.pool_size
new_shape = tf.concat(
[old_shape[:-1], [num_channel_groups, self.pool_size]], axis=0)
reshaped_inputs = tf.reshape(inputs, new_shape)
return tf.reduce_max(reshaped_inputs, axis=-1)
备注:
- 没有
strides
参数:假定等于池大小
- TensorFlow的
tf.nn.max_pool()
操作支持depthwise pooling(见我的另一个回答),但它只对CPU起作用,所以这个自定义层一般更好
我定义了以下参数,用于在图像深度 (rgb) 上进行最大池化,以便在密集层和读出之前进行压缩...我失败了,错误是我无法池化深度和其他一切:
sunset_poolmax_1x1x3_div_2x2x3_params = \
{'pool_function':tf.nn.max_pool,
'ksize':[1,1,1,3],
'strides':[1,1,1,3],
'padding': 'SAME'}
我将步幅更改为 [1,1,1,3]
,因此深度是泳池减少的唯一维度……但它仍然不起作用。我无法通过微小的图像获得良好的效果,我必须将所有内容压缩到以保持颜色...
实际错误:
ValueError: Current implementation does not support pooling in the batch and depth dimensions.
tf.nn.max_pool 不支持在深度维度上进行池化,这就是您收到错误的原因。
您可以使用最大减少来实现您想要的:
tf.reduce_max(input_tensor, reduction_indices=[3], keep_dims=True)
上面的keep_dims
参数确保张量的秩被保留。这确保最大缩减的行为将与 tf.nn.max_pool 操作在支持深度维度上的池化时将执行的操作一致。
这里是 tensorflow 原始问题的一个简短示例。我在具有 3 个通道的大小 225 x 225
的库存 RGB 图像上对其进行了测试。
导入标准库,启用eager_execution
快速查看结果
import tensorflow as tf
from scipy.misc import imread
import matplotlib.pyplot as plt
import numpy as np
tf.enable_eager_execution()
读取图像并从 uint8
投射到 tf.float32
x = tf.cast(imread('tiger.jpeg'), tf.float32)
x = tf.reshape(x, shape=[-1, x.shape[0], x.shape[1], x.shape[2]])
print(x.shape)
input_channels = x.shape[3]
为深度卷积创建过滤器
filters = tf.contrib.eager.Variable(tf.random_normal(shape=[3, 3, input_channels, 4]))
print(x.shape)
使用 channel multiplier
执行深度卷积 4. 请注意,填充已保持为 'SAME'
。可以随意更改。
x = tf.nn.depthwise_conv2d(input=x, filter=filters, strides=[1, 1, 1, 1], padding='SAME', name='conv_1')
print(x.shape)
执行max_pooling2d
。由于池化层的输出是(input_size - pool_size + 2 * padding)/stride + 1
,padding是'valid'
,我们应该得到(225 - 2 + 0)/1 + 1 = 223
.
x = tf.layers.max_pooling2d(inputs=x, pool_size=2, strides=1,padding='valid', name='maxpool1')
print(x.shape)
绘制数字以确认。
fig, ax = plt.subplots(nrows=4, ncols=3)
q = 0
for ii in range(4):
for jj in range(3):
ax[ii, jj].imshow(np.squeeze(x[:,:,:,q]))
ax[ii,jj].set_axis_off()
q += 1
plt.tight_layout()
plt.show()
TensorFlow 现在支持 tf.nn.max_pool()
的深度最大池化。例如,这里是如何使用池化内核大小 3、步幅 3 和有效填充来实现它:
import tensorflow as tf
output = tf.nn.max_pool(images,
ksize=(1, 1, 1, 3),
strides=(1, 1, 1, 3),
padding="VALID")
您可以在 Keras 模型中使用它,方法是将其包装在 Lambda
层中:
from tensorflow import keras
depth_pool = keras.layers.Lambda(
lambda X: tf.nn.max_pool(X,
ksize=(1, 1, 1, 3),
strides=(1, 1, 1, 3),
padding="VALID"))
model = keras.models.Sequential([
..., # other layers
depth_pool,
... # other layers
])
或者,您可以编写自定义 Keras 层:
class DepthMaxPool(keras.layers.Layer):
def __init__(self, pool_size, strides=None, padding="VALID", **kwargs):
super().__init__(**kwargs)
if strides is None:
strides = pool_size
self.pool_size = pool_size
self.strides = strides
self.padding = padding
def call(self, inputs):
return tf.nn.max_pool(inputs,
ksize=(1, 1, 1, self.pool_size),
strides=(1, 1, 1, self.pool_size),
padding=self.padding)
然后您可以像使用任何其他层一样使用它:
model = keras.models.Sequential([
..., # other layers
DepthMaxPool(3),
... # other layers
])
这是《使用 scikit 学习 keras 和 tensorflow 进行机器学习实践》一书的节选。 Keras 不包含深度最大池化层,但 TensorFlow 的底层 深度学习 API 做:只需使用 tf.nn.max_pool() 函数,并指定 内核大小和步幅为 4 元组(即大小为 4 的元组)。每个的前三个值 应为 1:这表示内核大小和步长沿批次、高度和 宽度尺寸应该是 1。最后一个值应该是任何内核大小和 沿深度维度所需的步幅——例如,3(这必须是除数 输入深度;如果前一层输出 20 个特征图,它将不起作用,因为 20 不是 3 的倍数):
output = tf.nn.max_pool(images,
ksize=(1, 1, 1, 3),
strides=(1, 1, 1, 3),
padding="valid")
如果您想将其作为一个层包含在您的 Keras 模型中,请将其包装在 Lambda 层中 (或创建自定义 Keras 层):
depth_pool = keras.layers.Lambda(
lambda X: tf.nn.max_pool(X, ksize=(1, 1, 1, 3), strides=(1, 1, 1, 3),
padding="valid"))
您可以使用自定义 Keras 层:
class DepthPool(tf.keras.layers.Layer):
def __init__(self, pool_size=2, **kwargs):
super().__init__(**kwargs)
self.pool_size = pool_size
def call(self, inputs):
old_shape = tf.shape(inputs)
num_channels = old_shape[-1]
num_channel_groups = num_channels // self.pool_size
new_shape = tf.concat(
[old_shape[:-1], [num_channel_groups, self.pool_size]], axis=0)
reshaped_inputs = tf.reshape(inputs, new_shape)
return tf.reduce_max(reshaped_inputs, axis=-1)
备注:
- 没有
strides
参数:假定等于池大小 - TensorFlow的
tf.nn.max_pool()
操作支持depthwise pooling(见我的另一个回答),但它只对CPU起作用,所以这个自定义层一般更好