【问题标题】:very very low validation accuracy and very high training accuracy python [closed]非常非常低的验证准确度和非常高的训练准确度python [关闭]
【发布时间】:2020-10-03 16:05:51
【问题描述】:

我正在训练一个深度学习模型,但准确度非常低。我使用 L2 正则化来阻止过度拟合并获得高精度,但它并没有解决问题。造成这种非常低的准确性的原因是什么?我该如何阻止它?

模型准确率几乎完美 (>90%),而验证准确率非常低 (

Epoch 1/15
2601/2601 - 38s - loss: 1.6510 - accuracy: 0.5125 - val_loss: 1.6108 - val_accuracy: 0.4706
Epoch 2/15
2601/2601 - 38s - loss: 1.1733 - accuracy: 0.7009 - val_loss: 1.5660 - val_accuracy: 0.4971
Epoch 3/15
2601/2601 - 38s - loss: 0.9169 - accuracy: 0.8147 - val_loss: 1.6223 - val_accuracy: 0.4948
Epoch 4/15
2601/2601 - 38s - loss: 0.7820 - accuracy: 0.8551 - val_loss: 1.7773 - val_accuracy: 0.4683
Epoch 5/15
2601/2601 - 38s - loss: 0.6539 - accuracy: 0.8989 - val_loss: 1.7968 - val_accuracy: 0.4937
Epoch 6/15
2601/2601 - 38s - loss: 0.5691 - accuracy: 0.9204 - val_loss: 1.8743 - val_accuracy: 0.4844
Epoch 7/15
2601/2601 - 38s - loss: 0.5090 - accuracy: 0.9327 - val_loss: 1.9348 - val_accuracy: 0.5029
Epoch 8/15
2601/2601 - 40s - loss: 0.4465 - accuracy: 0.9500 - val_loss: 1.9566 - val_accuracy: 0.4787
Epoch 9/15
2601/2601 - 38s - loss: 0.3931 - accuracy: 0.9596 - val_loss: 2.0824 - val_accuracy: 0.4764
Epoch 10/15
2601/2601 - 41s - loss: 0.3786 - accuracy: 0.9596 - val_loss: 2.1185 - val_accuracy: 0.4925
Epoch 11/15
2601/2601 - 38s - loss: 0.3471 - accuracy: 0.9604 - val_loss: 2.1972 - val_accuracy: 0.4879
Epoch 12/15
2601/2601 - 38s - loss: 0.3169 - accuracy: 0.9669 - val_loss: 2.1091 - val_accuracy: 0.4948
Epoch 13/15
2601/2601 - 38s - loss: 0.3018 - accuracy: 0.9685 - val_loss: 2.2073 - val_accuracy: 0.5006
Epoch 14/15
2601/2601 - 38s - loss: 0.2629 - accuracy: 0.9746 - val_loss: 2.2086 - val_accuracy: 0.4971
Epoch 15/15
2601/2601 - 38s - loss: 0.2700 - accuracy: 0.9650 - val_loss: 2.2178 - val_accuracy: 0.4879

我尝试增加 epoch 的数量,它只会增加模型的准确率,降低验证的准确率。

关于如何克服这个问题的任何建议?

我的代码:

def createModel():
    input_shape=(11, 3840,1)
    model = Sequential()
    #C1
    model.add(Conv2D(16, (5, 5), strides=( 2, 2), padding='same',activation='relu', input_shape=input_shape))
    model.add(keras.layers.MaxPooling2D(pool_size=( 2, 2),  padding='same'))
    model.add(BatchNormalization())
    #C2
    model.add(Conv2D(32, ( 3, 3), strides=(1,1), padding='same',  activation='relu'))
    model.add(keras.layers.MaxPooling2D(pool_size=(2, 2), padding='same'))
    model.add(BatchNormalization())
    
     #C3
    model.add(Conv2D(64, (3, 3), strides=( 1,1), padding='same',  activation='relu'))
    model.add(keras.layers.MaxPooling2D(pool_size=(2, 2), padding='same'))
    model.add(BatchNormalization())
    model.add(Dense(64, input_dim=64,kernel_regularizer=regularizers.l2(0.01)))
    
    model.add(Flatten())
    model.add(Dropout(0.5))
    model.add(Dense(256, activation='sigmoid'))
    model.add(Dropout(0.5))
    model.add(Dense(2, activation='softmax'))  
  
    opt_adam = keras.optimizers.Adam(lr=0.0001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0)
    model.compile(loss='categorical_crossentropy', optimizer=opt_adam, metrics=['accuracy']) 
    return model

def getFilesPathWithoutSeizure(indexSeizure, indexPat):
    filesPath=[]
    print(indexSeizure)
    print(indexPat)
    for i in range(0, nSeizure):
        if(i==indexSeizure):
            filesPath.extend(interictalSpectograms[i])
            filesPath.extend(preictalSpectograms[i])
    shuffle(filesPath)
    return filesPath

def generate_arrays_for_training(indexPat, paths, start=0, end=100):
    while True:
        from_=int(len(paths)/100*start)
        to_=int(len(paths)/100*end)
        for i in range(from_, int(to_)):
            f=paths[i]
            x = np.load(PathSpectogramFolder+f)
            x = np.expand_dims(np.expand_dims(x, axis=0), axis = 0)
            x = x.transpose(0, 2, 3, 1)
            if('P' in f):
                y = np.repeat([[0,1]],x.shape[0], axis=0)
            else:
                y =np.repeat([[1,0]],x.shape[0], axis=0)
            yield(x,y)
filesPath=getFilesPathWithoutSeizure(i, indexPat)
history=model.fit_generator(generate_arrays_for_training(indexPat, filesPath, end=75),#It take the first 75%
                                validation_data=generate_arrays_for_training(indexPat, filesPath, start=75), #It take the last 25%
                                steps_per_epoch=int((len(filesPath)-int(len(filesPath)/100*25))),
                                validation_steps=int((len(filesPath)-int(len(filesPath)/100*75))),
                                verbose=2,class_weight = {0:1, 1:1},
                                epochs=15, max_queue_size=2, shuffle=True)

【问题讨论】:

  • 是您的getFilesPathWithoutSeizure() 函数中的shuffle() 方法作为用户定义的函数还是从某个模块导入它?
  • @mb0850 是的,我使用 from random import shuffle 导入它
  • 如果filesPath 包含您数据的所有文件名,那么似乎改组不是您的问题。你的训练数据集的大小如何?如果训练图像的数量很少,那么您的模型将自动过拟合。
  • @mb0850 我在 filesPath 中有 3467 个 numpy 文件。我将 75% 用于训练,25% 用于验证。
  • 这类题题外,过拟合不是编程问题,需要使用正则化

标签: python tensorflow machine-learning keras neural-network


【解决方案1】:

您似乎已经在函数getFilesPathWithoutSeizure() 中实现了改组,尽管您可以通过多次打印文件名来验证改组是否实际工作。

filesPath=getFilesPathWithoutSeizure(i, indexPat) - i 更新了吗?

根据您在方法getFilesPathWithoutSeizure 中的代码if(i==indexSeizure):,当indexSeizure 等于计数器(for 循环的i)时,只会返回 1 个文件

如果您没有更改函数调用期间传递的 i 参数,这可能意味着只有 1 个文件返回到 filePath 变量,并且您的整个训练是在 1 个输入数据上完成的,而不是 75%共 3467 个文件。

--

在确认改组有效并且您的函数调用正在将所有数据插入您的filePath 变量后,它仍然不能解决您的问题,然后尝试以下操作:

数据增强可以通过应用随机但现实的变换(例如图像旋转、剪切、水平和垂直翻转、缩放、去中心等)增加数据集的多样性来帮助解决过度拟合问题。

但更重要的是,您需要手动查看数据并了解训练数据的相似性。

另一种选择是获取更多和多样化的数据进行训练。

【讨论】:

  • 我已经确认洗牌有效。我不更新 i 但我将 indexSeizurenSeizure 设置为零,具有相同的 i 值,因此所有文件都返回到 filesPath 。此外,我确认所有数据文件都通过打印filesPath 返回到filesPathfilesPath 的形状为 (3467,) 。现在我将尝试使用数据增强。
【解决方案2】:

您的模型过度拟合,无法正确泛化。如果您的训练集与验证集完全不同(您将 75% 和 25% 分开,但 75% 可能与 25% 完全不同),您的模型将很难泛化。

在拆分为训练和验证之前对数据进行洗牌。这应该会改善您的结果。

【讨论】:

  • 如何在拆分前打乱数据??我已经将model.fit_generator 中的数据改组为shuffle=True
  • fit_generator() 方法中的参数 shuffle=True 被忽略,因为 input_data 是一个生成器。
  • 我猜您正在使用一种名为generate_arrays_for_training() 的用户定义方法。您必须对此方法进行一些更改并添加一个随机播放组件。您可以参考tf.data: Build TensorFlow input pipelines Guide了解更多信息
  • @mb0850 我很好理解。您的意思是 shuffle=True 不适用于 fit_generator 。我在这个函数 getFilesPathWithoutSeizure 中使用 shuffle 并将 filesPath 传递给 generate_arrays_for_training() 。请检查我的代码
猜你喜欢
  • 2020-10-16
  • 2023-04-03
  • 2020-10-24
  • 1970-01-01
  • 1970-01-01
  • 2012-04-13
  • 2021-07-22
  • 2018-04-23
  • 2021-11-12
相关资源
最近更新 更多