我有一个关于如何修改预训练模型以对 3 个类别而不是 1000 个类别进行分类的问题。这是我到目前为止想到的 2 种方法..我不确定哪一个是最好的。
NASNetMobile_model = tf.keras.applications.NASNetMobile (
input_shape=(224,224,3),
include_top=False,
pooling='avg',
classes=3,
weights='imagenet'
)
NASNetMobile_model.trainable=False
NASNetMobile_model.summary()type here
在方法 1 中,NASNetMobile 模型使用预训练的 ImageNet 权重进行初始化,排除顶层并使用平均池化。该模型被设置为不可训练,以防止其权重在训练期间更新。然后构建一个新的序列模型,其中包括预训练的 NASNetMobile 模型,后跟两个密集层:一个具有 128 个单元和 ReLU 激活,另一个具有 3 个单元和用于最终分类的 softmax 激活。顺序模型是使用 Adam 优化器和稀疏分类交叉熵损失编译的。最后,模型在数据集上训练 20 个时期,批量大小为 4,验证分割为 20%。
new_pretrained_model = tf.keras.Sequential()
new_pretrained_model.add(NASNetMobile_model)
new_pretrained_model.add(tf.keras.layers.Dense(128, activation='relu'))
new_pretrained_model.add(tf.keras.layers.Dense(3, activation='softmax'))
new_pretrained_model.layers[0].trainable = False
new_pretrained_model.summary() here
new_pretrained_model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
new_pretrained_model.fit(
Xtrain,
Ytrain,
epochs=20,
batch_size=4,
validation_split=0.2
)
方法2中,使用函数式API创建新模型。预训练的 NASNetMobile 模型的输出被用作具有 128 个单元和 ReLU 激活的新密集层的输入,后面是具有 3 个单元和 softmax 激活的最终密集层。这种方法将 NASNetMobile 模型的输入显式连接到新的输出层,形成一个新模型,其输入与原始 NASNetMobile 模型相同,但具有用于分类的附加密集层。然后使用 Adam 优化器和稀疏分类交叉熵损失编译新模型,并在数据集上训练 20 个时期,批量大小为 4,验证分割为 20%。
NASNetMobile_model_out = NASNetMobile_model.output
x = tf.keras.layers.Dense(128, activation='relu')(NASNetMobile_model_out)
output = tf.keras.layers.Dense(3, activation='softmax')(x)
model_2 = tf.keras.Model(inputs = NASNetMobile_model.input, outputs=output)
model_2.summary()
model_2.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
model_2.fit(
Xtrain,
Ytrain,
epochs=20,
batch_size=4,
validation_split=0.2
)
顺序 API 和功能 API 都产生了相同的结果 由于类似的架构,您的代码我更喜欢方法 2,即
Functional
API 通常因其处理复杂问题的灵活性而受到青睐
具有多个输入和输出的模型。功能 API 允许共享
层,可以为不同的任务重用特征。顺序 API 有
独立的层,使得分支之间难以共享信息。