ResNet50传输学习失败

时间:2018-08-22 15:38:26

标签: python tensorflow keras transfer-learning

我需要一个或多个提示来克服迁移学习中的第一个痛苦。

以下代码是我实际尝试执行的精简版本,但是即使在其中使用了一个伪图片(A:空白/ B:空白+小方块),它也显示了问题。在最终版本中,输入的图像将更加复杂(这证明了所应用的基本模型的复杂性)。

问题看起来很简单。输入:两种类型的图像,输出:二进制分类(“正方形存在是/否”)。通过ImageDataGenerator向修改后的ResNet50模型提供准备好的训练数据。由于我可以创建任意数量的假数据,因此代码中没有数据扩充步骤。

无论如何,当我运行代码时,显示的损耗(对于AdamSDG优化器而言)似乎并没有改善,并且准确性很快趋于接近数量的比率。两个图像类(即B / A)中的示例。 (注意:在周末,我什至尝试了500个时代……没有变化。)

enter image description here

对于这两个(最可能连接的)问题,我还无法找出原因……可以吗?它是超参数之一,模型设置或实现的任何其他部分是否存在明显的故障?可能这只是愚蠢的事情,但是在追逐它并尝试使用越来越多且越来越简化的版本之后,我将无所适从。


import cv2
import matplotlib.pyplot as plt

import numpy as np

from tqdm import tqdm
from random import randint

from keras.layers import Dense, GlobalAveragePooling2D
from keras.optimizers import Adam
from keras.models import Model
from keras.applications import ResNet50

from keras.preprocessing.image import ImageDataGenerator


def modified_resnet_model():

    # load ResNet50 model excluding classification layers
    basemodel = ResNet50(weights='imagenet', include_top=False, input_shape=(224, 224, 3))

    # freeze model weights
    for layer in basemodel.layers:
        layer.trainable = False

    # add new classification head
    x = GlobalAveragePooling2D()(basemodel.output)
    x = Dense(128, activation='relu')(x)
    predictions = Dense(1, activation='softmax')(x)
    modresnet50model = Model(inputs=basemodel.input, outputs=predictions)

    # return the result
    return modresnet50model


def data_set_creator(numsamples, probpos, target_image_size=(224, 224)):

    dataset = {}
    image_stack = []
    immean = np.array([0.0, 0.0, 0.0])
    imstat = {}

    # first create target labels
    lbbuf = np.zeros((numsamples, 1))
    lbbuf[:int(probpos*numsamples)] = 1
    lbbuf = np.random.permutation(lbbuf)

    # second create matching "fake" images according to label stack
    for index in tqdm(range(numsamples)):

        # zero labeled images are empty
        img = np.zeros((target_image_size[0], target_image_size[1], 3)).astype(np.float32)
        sh = 10
        if lbbuf[index]:
            # all others contain a suqare somewhere
            xp = randint(sh, target_image_size[0]-1-sh)
            yp = randint(sh, target_image_size[1]-1-sh)
            randval = 100  # randint(1, 255)
            # print('center: ({0:d},{1:d}); value: {2:d}'.format(xp, yp, randval))
            img[yp-sh:yp+sh, xp-sh:xp+sh, :] = randval
        # else:
        #     print(' --- ')

        # normalize image and add it to the image stack
        img /= 255.0  # normalize image
        image_stack.append(img)

        # update mean vector
        immean += cv2.mean(img)[:-1]

    # assemple data set
    imstat['mean'] = immean/numsamples

    image_stack = np.array(image_stack)

    dataset['images'] = image_stack
    dataset['imstat'] = imstat
    dataset['labels'] = lbbuf

    # return the result
    return dataset


if __name__ == '__main__':

    # define some parameters
    imagesize = (224, 224)
    nsamples = 10000
    pos_prob_train = 0.3
    probposval = pos_prob_train
    valfrac = 0.1   # use 10% of the data for validation
    batchsize = 24
    epochs = 30
    stepsperepoch = 100
    validationsteps = 25

    # ================================================================================

    # create training and validation data sets
    nst = int(nsamples*(1-valfrac))
    dataset_training = data_set_creator(nst, pos_prob_train, target_image_size=imagesize)
    dataset_validation = data_set_creator(nsamples-nst, probposval, target_image_size=imagesize)

    # subtract the mean (training data!) from all the images
    for ci in range(3):
        dataset_training['images'][:, :, :, ci] -= dataset_training['imstat']['mean'][ci]
        dataset_validation['images'][:, :, :, ci] -= dataset_training['imstat']['mean'][ci]

    # get the (modified) model
    model = modified_resnet_model()
    theoptimizer = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8)
    model.compile(optimizer=theoptimizer, loss='binary_crossentropy', metrics=['accuracy'])
    print(model.summary())

    # setup data input generators
    train_datagen = ImageDataGenerator()
    validation_datagen = ImageDataGenerator()
    train_generator = train_datagen.flow(dataset_training['images'],
                                         dataset_training['labels'],
                                         batch_size=batchsize)
    validation_generator = validation_datagen.flow(dataset_validation['images'],
                                                   dataset_validation['labels'],
                                                   batch_size=batchsize)

    # train the (modified) model
    history = model.fit_generator(train_generator, steps_per_epoch=stepsperepoch,
                                  epochs=epochs, validation_data=validation_generator,
                                  validation_steps=validationsteps)

    #visualize the training and validation performance
    acc = history.history['acc']
    val_acc = history.history['val_acc']
    loss = history.history['loss']
    val_loss = history.history['val_loss']
    nepochs = range(1, len(acc)+1)
    plt.plot(nepochs, acc, 'bo', label='Training acc')
    plt.plot(nepochs, val_acc, 'b', label='Validation acc')
    plt.title('Training and validation accuracy')
    plt.legend()
    plt.savefig('trainval_acc.png')

    plt.figure()
    plt.plot(nepochs, loss, 'bo', label='Training loss')
    plt.plot(nepochs, val_loss, 'b', label='Validation loss')
    plt.title('Training and validation loss')
    plt.legend()
    plt.savefig('trainval_loss.png')
    plt.show()

0 个答案:

没有答案