构建keras模型

Bar*_*ich 2 python neural-network deep-learning keras keras-layer

我不明白这段代码中发生了什么:

def construct_model(use_imagenet=True):
    # line 1: how do we keep all layers of this model ?
    model = keras.applications.InceptionV3(include_top=False, input_shape=(IMG_SIZE, IMG_SIZE, 3),
                                          weights='imagenet' if use_imagenet else None) # line 1: how do we keep all layers of this model ?

    new_output = keras.layers.GlobalAveragePooling2D()(model.output)

    new_output = keras.layers.Dense(N_CLASSES, activation='softmax')(new_output)
    model = keras.engine.training.Model(model.inputs, new_output)
    return model
Run Code Online (Sandbox Code Playgroud)

具体来说,当我们调用最后一个构造函数时,我的困惑是

model = keras.engine.training.Model(model.inputs, new_output)
Run Code Online (Sandbox Code Playgroud)

我们指定输入层和输出层,但它如何知道我们希望所有其他层保留?

换句话说,我们将new_output层附加到我们在第1行加载的预训练模型,即new_output层,然后在最终构造函数(最后一行)中,我们只创建并返回具有指定输入的模型,输出图层,但它如何知道我们想要的其他图层?

问题1):keras.engine.training.Model和keras.models.Model有什么区别?

问题2):当我们做new_layer = keras.layers.Dense(...)(prev_layer)时到底发生了什么?()操作是否返回新图层,它究竟做了什么?

Dan*_*ler 5

此模型是使用Functional API模型创建的

基本上它的工作方式是这样的(也许如果你在阅读之前去下面的"侧面问题2"它可能会更清楚):

  • 你有一个输入张量(你也可以把它看作"输入数据")
  • 您可以创建(或重复使用)图层
  • 您将输入张量传递给图层(您使用输入"调用"图层)
  • 你得到一个输出张量

在创建整个图形之前,您一直在使用这些张量.

但这还没有创造出"模型".(你可以训练和使用其他东西).
你所拥有的只是一张图表,告诉你哪些张量在哪里.

要创建模型,请定义它的起始端点.


在示例中.

  • 他们采用现有模型: model = keras.applications.InceptionV3(...)
  • 他们想要扩展这个模型,所以他们得到它的输出张量:model.output
  • 它们将此张量作为GlobalAveragePooling2D图层 的输入传递
  • 他们将此图层的输出张量设为 new_output
  • 他们将此作为输入传递到另一层: Dense(N_CLASSES, ....)
  • 得到它的输出new_output(这个var被替换,因为他们不想保持它的旧值......)

但是,由于它与功能API一起使用,我们还没有模型,只有图表.为了创建模型,我们使用Model定义输入张量和输出张量:

new_model = Model(old_model.inputs, new_output)    
Run Code Online (Sandbox Code Playgroud)

现在你有了你的模型.
如果你在另一个var中使用它,就像我做的那样(new_model),旧模型仍将存在model.并且这些模型共享相同的层,每当您训练其中一个时,另一个也会更新.


问题:它如何知道我们想要的其他层?

当你这样做时:

outputTensor = SomeLayer(...)(inputTensor)    
Run Code Online (Sandbox Code Playgroud)

你有输入和输出之间的连接.(Keras将使用内部张量流机制并将这些张量和节点添加到图形中).没有输入,输出张量就不存在.整个InceptionV3模型从头到尾连接.它的输入张量遍历所有层以产生一个ouptut张量.数据只有一种可能的方式,图表就是这样.

当您获得此模型的输出并使用它来获得更多输出时,所有新输出都将连接到此模型,从而连接到模型的第一个输入.

_keras_history添加到张量的属性可能与它跟踪图形的方式密切相关.

因此,做法Model(old_model.inputs, new_output)自然会遵循唯一可能的方式:图表.

如果您尝试使用未连接的张量进行此操作,则会出现错误.


问题1

喜欢从"keras.models"导入.基本上,这个模块将从其他模块导入:

请注意,文件从中keras/models.py导入.所以,这是一回事. Modelkeras.engine.training

问题2

事实并非如此new_layer = keras.layers.Dense(...)(prev_layer).

是的output_tensor = keras.layers.Dense(...)(input_tensor).

你在同一行做两件事:

  • 创建一个图层 - 用 keras.layers.Dense(...)
  • 使用输入张量调用图层以获得输出张量

如果要使用具有不同输入的相同图层:

denseLayer = keras.layers.Dense(...) #creating a layer

output1 = denseLayer(input1)  #calling a layer with an input and getting an output
output2 = denseLayer(input2)  #calling the same layer on another input
output3 = denseLayer(input3)  #again   
Run Code Online (Sandbox Code Playgroud)

奖励 - 创建与顺序模型相同的功能模型

如果您创建此顺序模型:

model = Sequential()
model.add(Layer1(...., input_shape=some_shape))   
model.add(Layer2(...))
model.add(Layer3(...))
Run Code Online (Sandbox Code Playgroud)

你做的完全一样:

inputTensor = Input(some_shape)
outputTensor = Layer1(...)(inputTensor)
outputTensor = Layer2(...)(outputTensor)    
outputTensor = Layer3(...)(outputTensor)

model = Model(inputTensor,outputTensor)
Run Code Online (Sandbox Code Playgroud)

有什么不同?

那么,功能API模型完全可以随意构建,无论如何.您可以创建分支:

out1 = Layer1(..)(inputTensor)    
out2 = Layer2(..)(inputTensor)
Run Code Online (Sandbox Code Playgroud)

你可以加入张量:

joinedOut = Concatenate()([out1,out2])   
Run Code Online (Sandbox Code Playgroud)

有了这个,您可以使用各种花哨的东西,分支,门,连接,添加等创建您想要的任何东西,这是顺序模型无法做到的.

实际上,Sequential模型也是一种模型Model,但是为了在没有分支的模型中快速使用而创建.