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)时到底发生了什么?()操作是否返回新图层,它究竟做了什么?
此模型是使用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)
自然会遵循唯一可能的方式:图表.
如果您尝试使用未连接的张量进行此操作,则会出现错误.
喜欢从"keras.models"导入.基本上,这个模块将从其他模块导入:
请注意,文件从中keras/models.py
导入.所以,这是一回事. Model
keras.engine.training
事实并非如此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
,但是为了在没有分支的模型中快速使用而创建.