【问题标题】:How to change input and output shape of any model architecture in Keras?如何更改 Keras 中任何模型架构的输入和输出形状?
【发布时间】:2018-08-20 01:03:41
【问题描述】:

我最近收集了几个 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,那么改变最后一层的形状是可行的方案吗?

【问题讨论】:

  • set_shape 方法仅更新已定义形状的现有未知尺寸,因此不可行。此外,model.input 和 model.output 输出序列中的第一层和最后一层,以及模型中的第一层和多个输出层,与层类型无关。任何解决此问题的帮助将不胜感激。
  • from keras.models import clone_model newmodel = clone_model(model,Input(batch_shape=(None,32,32,3))) 仍然不知道如何动态更改输出类号。

标签: python tensorflow keras


【解决方案1】:

我想出了这个实现,但它在我目前拥有的所有模型中都适用,但远非完美。我将不胜感激使用其他模型进行进一步测试。我把它留在这里供参考。

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

【讨论】:

    猜你喜欢
    • 2017-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-18
    • 2020-11-18
    • 2019-01-26
    • 2019-12-12
    • 2021-06-05
    相关资源
    最近更新 更多