将调整大小层添加到keras顺序模型

将调整大小层添加到keras顺序模型,keras,keras-layer,Keras,Keras Layer,如何将调整大小的图层添加到 model = Sequential() 使用 model.add(...) 要将图像的大小从形状(160、320、3)调整为(224、224、3)?通常情况下,您会使用图层进行此操作: model.add(Reshape((224,224,3), input_shape=(160,320,3)) 但是,由于您的目标维度不允许保存来自输入维度的所有数据(224*224!=160*320),这将不起作用。只有在元素数量不变的情况下,才能使用重塑 如果您对图像中的某

如何将调整大小的图层添加到

model = Sequential()
使用

model.add(...)

要将图像的大小从形状(160、320、3)调整为(224、224、3)?

通常情况下,您会使用图层进行此操作:

model.add(Reshape((224,224,3), input_shape=(160,320,3))
但是,由于您的目标维度不允许保存来自输入维度的所有数据(
224*224!=160*320
),这将不起作用。只有在元素数量不变的情况下,才能使用
重塑

如果您对图像中的某些数据丢失感到满意,则可以指定自己的有损重塑:

model.add(Reshape(-1,3), input_shape=(160,320,3))
model.add(Lambda(lambda x: x[:50176])) # throw away some, so that #data = 224^2
model.add(Reshape(224,224,3))

这样说,通常这些变换是在将数据应用到模型之前完成的,因为如果在每个训练步骤中都这样做,这实质上是浪费计算时间。

< P>我想你应该考虑使用TysFooSe的ResiZeIsI图层。p>

keras似乎不包括这一点,可能是因为theano中不存在该功能。我已经编写了一个自定义keras层,它也做了同样的工作。这是一个快速的黑客,所以它可能不适合你的情况

import keras
import keras.backend as K
from keras.utils import conv_utils
from keras.engine import InputSpec
from keras.engine import Layer
from tensorflow import image as tfi

class ResizeImages(Layer):
    """Resize Images to a specified size

    # Arguments
        output_size: Size of output layer width and height
        data_format: A string,
            one of `channels_last` (default) or `channels_first`.
            The ordering of the dimensions in the inputs.
            `channels_last` corresponds to inputs with shape
            `(batch, height, width, channels)` while `channels_first`
            corresponds to inputs with shape
            `(batch, channels, height, width)`.
            It defaults to the `image_data_format` value found in your
            Keras config file at `~/.keras/keras.json`.
            If you never set it, then it will be "channels_last".

    # Input shape
        - If `data_format='channels_last'`:
            4D tensor with shape:
            `(batch_size, rows, cols, channels)`
        - If `data_format='channels_first'`:
            4D tensor with shape:
            `(batch_size, channels, rows, cols)`

    # Output shape
        - If `data_format='channels_last'`:
            4D tensor with shape:
            `(batch_size, pooled_rows, pooled_cols, channels)`
        - If `data_format='channels_first'`:
            4D tensor with shape:
            `(batch_size, channels, pooled_rows, pooled_cols)`
    """
    def __init__(self, output_dim=(1, 1), data_format=None, **kwargs):
        super(ResizeImages, self).__init__(**kwargs)
        data_format = conv_utils.normalize_data_format(data_format)
        self.output_dim = conv_utils.normalize_tuple(output_dim, 2, 'output_dim')
        self.data_format = conv_utils.normalize_data_format(data_format)
        self.input_spec = InputSpec(ndim=4)

    def build(self, input_shape):
        self.input_spec = [InputSpec(shape=input_shape)]

    def compute_output_shape(self, input_shape):
        if self.data_format == 'channels_first':
            return (input_shape[0], input_shape[1], self.output_dim[0], self.output_dim[1])
        elif self.data_format == 'channels_last':
            return (input_shape[0], self.output_dim[0], self.output_dim[1], input_shape[3])

    def _resize_fun(self, inputs, data_format):
        try:
            assert keras.backend.backend() == 'tensorflow'
            assert self.data_format == 'channels_last'
        except AssertionError:
            print "Only tensorflow backend is supported for the resize layer and accordingly 'channels_last' ordering"
        output = tfi.resize_images(inputs, self.output_dim)
        return output

    def call(self, inputs):
        output = self._resize_fun(inputs=inputs, data_format=self.data_format)
        return output

    def get_config(self):
        config = {'output_dim': self.output_dim,
                  'padding': self.padding,
                  'data_format': self.data_format}
        base_config = super(ResizeImages, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

可接受的答案使用的图层,其工作原理类似于,可用于将4x4矩阵重塑为2x8矩阵,但这将导致图像丢失位置信息:

0 0 0 0
1 1 1 1    ->    0 0 0 0 1 1 1 1
2 2 2 2          2 2 2 2 3 3 3 3
3 3 3 3
相反,应使用(例如)重新缩放/调整图像数据的大小。 但是要小心正确的和错误! 如中所示,这可用于lambda层:

model.add( keras.layers.Lambda( 
    lambda image: tf.image.resize_images( 
        image, 
        (224, 224), 
        method = tf.image.ResizeMethod.BICUBIC,
        align_corners = True, # possibly important
        preserve_aspect_ratio = True
    )
))

在您的情况下,由于您有一个160x320图像,您还必须决定是否保持纵横比。如果要使用预先训练过的网络,则应使用与训练过的网络相同的大小调整。

修改@KeithWM的答案,添加输出比例,例如输出比例=2表示输出是输入形状的2倍:)


要将给定输入图像调整为目标大小(在本例中为224x224x3),请执行以下操作:

在常规KERA中使用Lambda层:

from keras.backend import tf as ktf

inp = Input(shape=(None, None, 3))

[Ref::

我不明白你关于计算时间的说法。每个图像都必须进行一次重塑。如果之前进行过重塑,而不是作为模型管道的一部分进行重塑,会有什么不同?如果只训练模型一次,则不会有什么不同(如果我们不考虑这些操作在GPU上是否更快)。但只要您对模型进行两次训练并多次计算重塑,您就会从一次操作中获益,将结果缓存到文件中(numpy save或PICKER)问题是关于调整大小,而不是调整形状。在调整形状中,数组的总大小必须保持不变,这对于调整大小是不正确的。Frome Keras函数注释:“如果输出形状的总数组大小与输入形状不同,或者指定了多个未知维度,则会引发值错误。”我很确定这是一个坏主意。建议的重塑将使输入数据中的所有空间结构松散。此外,如果输入层和输出层的大小(元素总数)非常不同,则所产生的损失将非常大。我对此投了反对票,因为这个问题几乎肯定是在寻找图像下采样/上采样/插值,而不是像你建议的那样进行张量重塑。在我的例子中,我仍然得到错误:
TypeError:模型的输出张量必须是Keras张量。发现:张量(“ResizeBilinear_1:0”,shape=(?,224224,224,3),dtype=float32)
@VadymB.您使用的是哪个后端,以及Keras的哪个版本?您确定为层提供了正确的输入吗?Keras 2.0.6.我已经发现了一个问题,我使用的是
tf.image.resize\u images
并且我必须将其放入
Keras.layers.Lambda
@VadymB.不是为了对该线程进行死灵术,而是当您放入该线程时在lambda层中,你能成功地调用“fit”或“fit_generator”吗?你能发布你是如何做到的吗?我断断续续地处理一个类似的问题已经好几天了,在安装过程中仍然会出现错误…谢谢!@Decker,它过去是有效的,但不幸的是我没有使用此函数的工作代码。对于我的用例,我使用了事件在仍然使用Lambda层的情况下,手动切换到
tf.depth\u to\u space
。下面是伪代码:```def custom\u fun(input,k=2,**kwargs):导入tensorflow作为tf返回tf.depth\u to\u space(input,block\u size=k)input=input(…)…out=Lambda(custom\u fun)(input)“这是一个很好的方法,但公认答案的问题不是它“丢失了位置信息”——而是它完全做了错事,“丢失位置信息”只是一个症状。
from keras.backend import tf as ktf

inp = Input(shape=(None, None, 3))