如何在Keras中更改任何模型架构的输入和输出形状?

时间:2018-08-16 02:20:06

标签: python tensorflow keras

我最近收集了几个Keras模型,正在使用keras.Models.model_from_json函数为其导入其体系结构(请注意,尚未进行任何培训)。我的图像数据生成器可以进行自定义,以生成具有不同大小和形状的批次的样本(在同一流量生成器中有所不同)。例如,我可以生成形状为(*batchsize*,32,32,3)且总共6个类的数据。当前,导入的模型具有不同的输入和输出形状,例如(5*100*100*3)和2个分配给它们的层的类。 我的目标是更改此类图层的输入和输出形状,以便在模型性能中比较不同的图像大小。

首先,在输入层中,我尝试过:

model.layers[0].input.set_shape((None,32,32,3))

我收到以下错误:

Dimension 1 in both shapes must be equal, but are 100 and 32. Shapes are [?,100,100,3] and [?,32,32,3].

类似地,对于输出层,使用

model.layers[len(model.layers)-1].output.set_shape((None,6))

抛出相同的错误

Dimension 1 in both shapes must be equal, but are 2 and 6. Shapes are [?,2] and [?,6].

TLDR:是否存在通用功能/实用工具来动态更改Keras中任何模型架构的输入和输出形状?

PS:如果模型有多个输出,或者最后两层是keras.layers.Dense,后跟keras.layers.Activation,那么更改最后一层的形状是否可行?< / p>

1 个答案:

答案 0 :(得分:0)

我想出了这种实现方式,但它远非完美,无法在我目前拥有的所有模型中使用。我希望对其他模型进行进一步测试。我把它留在这里供参考。

def modifySISO(model,inp,out): # Modify Single Input Single Output image classification model.

    ci,co = validation(model,inp,out)

    if(ci): #change input
      model = changeInp(model,inp)
    if(co): #change ouput
      model = changeOut(model,out)

    return model, any([ci,co]) # modified or original model, modified


def validation(model,inp,out):

    n_in = len(model.inputs)
    n_out =len(model.outputs) 
    assert (n_in) > 0, 'Model has not detectable inputs.'
    assert (n_out) > 0, 'Model has not detectable outputs.'
    assert (n_in) <= 1, 'Model has multiple %d inputs tensors. Cannot apply input transformation.' % (n_in)
    assert (n_out) <= 1, 'Model has multiple %d output tensors Cannot apply output transformation.' % (n_out)

    inp_old = model.input_shape

    assert len(inp_old) == 4, 'Model input tensor shape != 4: Not a valid image classification model (B x X x X x X).'

    assert isinstance(inp,tuple), 'Input parameter is not a valid tuple.'
    assert len(inp) == 4, 'Input parameter is not a valid 4-rank tensor shape.'

    out_old = model.output_shape
    assert len(out_old) == 2, 'Model output tensor shape !=2: Not a valid image classification model (B x C).'
    assert isinstance(out,tuple), 'Output parameter is not a valid tuple.'
    assert len(out) == 2, 'Output parameter is not a valid 2-rank tensor shape.'

    ci = any([inp[i] != inp_old[i] for i in range(0,len(inp))])
    co = any([out[i] != out_old[i] for i in range(0,len(out))])

    return ci,co

def changeInp(model,inp):
    return clone_model(model,Input(batch_shape=inp))

def changeOut(model,out):
    idx = findPreTop(model) # Finds the pre-topping layer (must be tested more extensively)
    preds = reshapeOutput(model,idx,out)
    model = Model(inputs=model.input, outputs=preds)

def findPreTop(model):
   i = len(model.layers)-1
   cos = model.output_shape
   while(model.layers[i].output_shape == cos):
     i -= 1
   return i

def reshapeOutput(model,i,out): # Reshapes model accordingly to https://keras.io/applications/#usage-examples-for-image-classification-models
    layer=model.layers[i]
    pool = layer.output_shape[-1]
    x = layer.output
    x = Dense(int(pool/2),activation='relu')(x)
    x = Dense(out[1], activation='softmax')(x)
    return x

newmodel = modifySISO(model,(None,100,100,3),(None,6)) #Implementation