¿Cómo dividir un tensor en Keras
introducción
Ejecute el código siguiente:
# coding=utf-8
from keras.layers import *
if __name__ == '__main__':
import numpy as np
inp1 = Input(batch_shape=(None, 12, 30, 40))
inp2 = Input(batch_shape=(None, 12, 30, 40))
# 分割&Concat
concat = merge([inp1[:, 0:6, ...], inp2], mode='concat', concat_axis=-1)
conv = Convolution2D(32, 3, 3, name='conv1')(concat)
Se reportó el siguiente error:
Exception: You tried to call layer "conv1". This layer has no information about its expected input shape, and thus cannot be built. You can build it manually via: `layer.build(batch_input_shape)`
De hecho, mis necesidades son simples, el medio ent1 de nuestro canal, y de combinación ING2, y luego la convolución, y una operación más sencilla, Keras también informó de un error. El error que es muy fan, trato de buscar la tarde, conseguir que funcione. . .
Noche eureka momento, no está obligado a personalizar una capa Keras, se da input_shape
se da en el caso de output_shape
que? Tal capa de una parte posterior fueron capaces de deducir la forma.
Dividir una capa personalizada
diferentes versiones Keras lograr autodefinida interfaces de capa para lograr ligeramente diferente, Keras versión 1.1.0 uso I, así que Referencia: http://faroit.com/keras-docs/1.1.0/layers/writing- -propio-Keras-Capas / . 1.1.0 Keras en una capa personalizada es el siguiente:
from keras import backend as K
from keras.engine.topology import Layer
import numpy as np
class MyLayer(Layer):
def __init__(self, output_dim, **kwargs):
self.output_dim = output_dim
super(MyLayer, self).__init__(**kwargs)
def build(self, input_shape):
input_dim = input_shape[1]
initial_weight_value = np.random.random((input_dim, output_dim))
self.W = K.variable(initial_weight_value)
self.trainable_weights = [self.W]
def call(self, x, mask=None):
return K.dot(x, self.W)
def get_output_shape_for(self, input_shape):
return (input_shape[0], self.output_dim)
La necesidad de lograr __init__
, build
, call
y get_output_shape_for
otras interfaces. Si una fracción de tensor, necesita dar salida a una pluralidad de tensor, por lo que necesita para lograr compute_mask
, para devolver una lista de forma.
En resumen, para lograr una capa de Split de la siguiente manera:
# coding=utf-8
from keras.layers import *
class Split(Layer):
def __init__(self, **kwargs):
super(Split, self).__init__(**kwargs)
def build(self, input_shape):
# 调用父类的build函数,build本层
super(Split, self).build(input_shape)
# 存一下shape,其他函数要用
self.shape = input_shape
def call(self, x, mask=None):
# 将x分割为两个tensor
seq = [x[:, 0:self.shape[1] // 2, ...],
x[:, self.shape[1] // 2:, ...]]
return seq
def compute_mask(self, inputs, input_mask=None):
# 本层输出两个tensor,需要返回多个mask,mask可以为None
return [None, None]
def get_output_shape_for(self, input_shape):
# 本层返回两个tensor,就要返回两个tensor的shape
shape0 = list(self.shape)
shape1 = list(self.shape)
shape0[1] = self.shape[1] // 2
shape1[1] = self.shape[1] - self.shape[1] // 2
# print [shape0, shape1]
return [shape0, shape1]
capa derramado con lo anterior:
if __name__ == '__main__':
import numpy as np
inp1 = Input(batch_shape=(None, 17, 30, 40))
inp2 = Input(batch_shape=(None, 12, 30, 40))
sp = Split()(inp1)
# 分割&Concat
concat = merge([sp[0], inp2], mode='concat', concat_axis=1)
conv = Convolution2D(32, 3, 3, name='conv1')(concat)
data = {inp1: np.random.rand(12, 17, 30, 40).astype(np.float32),
inp2: np.random.rand(12, 12, 30, 40).astype(np.float32)}
print sp[0].eval({inp1: np.random.rand(12, 17, 30, 40).astype(np.float32)}).shape
print sp[1].eval({inp1: np.random.rand(12, 17, 30, 40).astype(np.float32)}).shape
print concat.eval(data).shape
print conv.eval(data).shape
Ejecutar el programa anterior, salida:
(12L, 8L, 30L, 40L)
(12L, 9L, 30L, 40L)
(12L, 20L, 30L, 40L)
(12L, 32L, 28L, 38L)
Satisfacer las necesidades sin error.