keras CNN能比经过预先训练的CNN做得更好吗?

wlzqhblo  于 2022-11-13  发布在  其他
关注(0)|答案(3)|浏览(201)

据我所知,经过预训练的CNN比CNN有更好的效果。我有一个855幅图像的数据集。我应用CNN,得到了94%的准确率。然后我应用了预训练模型(VGG16、ResNet50、初始化_V3、MobileNet)也进行了微调,但我仍然得到了最高的60%,其中两个在分类上做得很差。CNN真的能比预先训练的模型做得更好吗?或者我的实现是错误的。我已经把我的图像转换成100乘100维,并遵循keras application的方式。那么问题是什么??
天真的CNN方法:

def cnn_model():
    size = (100,100,1)
    num_cnn_layers =2
    NUM_FILTERS = 32
    KERNEL = (3, 3)
    MAX_NEURONS = 120

    model = Sequential()

    for i in range(1, num_cnn_layers+1):
        if i == 1:
            model.add(Conv2D(NUM_FILTERS*i, KERNEL, input_shape=size, 
            activation='relu', padding='same'))
        else:
            model.add(Conv2D(NUM_FILTERS*i, KERNEL, activation='relu', 
            padding='same'))

    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(Flatten())
    model.add(Dense(int(MAX_NEURONS), activation='relu'))
    model.add(Dropout(0.25))
    model.add(Dense(int(MAX_NEURONS/2), activation='relu'))
    model.add(Dropout(0.4))
    model.add(Dense(3, activation='softmax'))

    model.compile(loss='categorical_crossentropy', optimizer='adam', 
    metrics=['accuracy'])
    return model

VGG16进近:

def vgg():
`  `vgg_model = keras.applications.vgg16.VGG16(weights='imagenet',include_top=False,input_shape = (100,100,3))
    model = Sequential()
    for layer in vgg_model.layers:
        model.add(layer)

    # Freeze the layers 
    for layer in model.layers:
        layer.trainable = False

    model.add(keras.layers.Flatten())
    model.add(keras.layers.Dense(3, activation='softmax'))

    model.compile(optimizer=keras.optimizers.Adam(lr=1e-5),
              loss='categorical_crossentropy',
              metrics=['accuracy'])
    return model
jyztefdp

jyztefdp1#

在这两种情况下,CNN所指的是同一件事,即一种神经网络模型,只是预先训练好的模型是在其他数据上训练的,而不是在你正在处理并试图分类的数据集上。
这里通常使用的是迁移学习。不要冻结所有的层,而是尝试让最后几层保持开放,这样它们就可以用你自己的数据重新训练,这样预训练的模型就可以编辑它的权重和偏差,以满足你的需要。可能的情况是,你试图分类的数据集对预训练的模型来说是陌生的。
这是我自己工作中的一个例子,有一些额外的代码片段,但是你可以让它与你自己的代码一起工作,逻辑保持不变

#You extract the layer which you want to manipulate, usually the last few.
last_layer = pre_trained_model.get_layer(name_of_layer)

# Flatten the output layer to 1 dimension
x = layers.Flatten()(last_output)
# Add a fully connected layer with 1,024 hidden units and ReLU activation
x = layers.Dense(1024,activation='relu')(x)
# Add a dropout rate of 0.2
x = layers.Dropout(0.2)(x)                  
# Add a final sigmoid layer for classification
x = layers.Dense(1,activation='sigmoid')(x)           

#Here we combine your newly added layers and the pre-trained model.
model = Model( pre_trained_model.input, x) 

model.compile(optimizer = RMSprop(lr=0.0001), 
              loss = 'binary_crossentropy', 
              metrics = ['accuracy'])
cetgtptt

cetgtptt2#

除@Ilknur Mustafa提到的内容外,由于您的数据集可能与用于预训练的图像无关,您可以尝试重新训练预训练模型的最后几层,而不是添加全新的层。以下示例代码除了输出层之外,不会添加任何额外的可训练层。这样,您可以通过在现有权重上重新训练最后几层来获益。而不是从头开始训练。如果您没有大型数据集可供训练,这可能会很有用。

# load model without classifier layers 
vgg = VGG16(include_top=False, input_shape=(100, 100, 3), weights='imagenet', pooling='avg')
# make only last 2 conv layers trainable 
for layer in vgg.layers[:-4]:
    layer.trainable = False
# add output layer  
out_layer = Dense(3, activation='softmax')(vgg.layers[-1].output)
model_pre_vgg = Model(vgg.input, out_layer)
# compile model 
opt = SGD(lr=1e-5) 
model_pre_vgg.compile(optimizer=opt, loss=keras.losses.categorical_crossentropy, metrics=['accuracy'])
t3irkdon

t3irkdon3#

#You extract the layer which you want to manipulate, usually the last few.
last_layer = pre_trained_model.get_layer(name_of_layer)

# Flatten the output layer to 1 dimension
x = layers.Flatten()(last_output)
# Add a fully connected layer with 1,024 hidden units and ReLU activation
x = layers.Dense(1024,activation='relu')(x)
# Add a dropout rate of 0.2
x = layers.Dropout(0.2)(x)                  
# Add a final sigmoid layer for classification
x = layers.Dense(1,activation='sigmoid')(x)           

#Here we combine your newly added layers and the pre-trained model.
model = Model( pre_trained_model.input, x) 

model.compile(optimizer = RMSprop(lr=0.0001), 
              loss = 'binary_crossentropy', 
              metrics = ['accuracy'])

相关问题