【问题标题】:How can I get constant value val accuracy and val loss in keras如何在keras中获得恒定值val精度和val损失
【发布时间】:2023-02-04 19:30:22
【问题描述】:

我是神经网络的新手,我尝试使用 keras 进行 mlp 文本分类。每次我运行代码时,它都会得到不同的 val 损失和 val 准确性。每次我重新运行它时,Val loss 都会增加,val accuracy 会减少。我正在使用的代码是这样的:

#Split data training and testing (80:20)
Train_X2, Test_X2, Train_Y2, Test_Y2 = model_selection.train_test_split(dataset['review'],dataset['sentiment'],test_size=0.2, random_state=1)

Encoder = LabelEncoder()

Train_Y2 = Encoder.fit_transform(Train_Y2)
Test_Y2 = Encoder.fit_transform(Test_Y2)

Tfidf_vect2 = TfidfVectorizer(max_features=None)
Tfidf_vect2.fit(dataset['review'])
Train_X2_Tfidf = Tfidf_vect2.transform(Train_X2)
Test_X2_Tfidf = Tfidf_vect2.transform(Test_X2)

#Model
model = Sequential()
model.add(Dense(100, input_dim= 1148, activation='sigmoid'))
model.add(Dense(1, activation='sigmoid'))
opt = Adam (learning_rate=0.01)
model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])
model.summary()
    
from keras.backend import clear_session
clear_session()
    
es = EarlyStopping(monitor="val_loss",mode='min',patience=10)
history = model.fit(arr_Train_X2_Tfidf, Train_Y2, epochs=100,verbose=1, validation_split=0.2,validation_data=(arr_Test_X2_Tfidf, Test_Y2), batch_size=32, callbacks =[es])

我尝试使用 clear_session() 来使模型不以先前训练的计算权重开始。但它仍然得到差异值。如何解决?谢谢

【问题讨论】:

  • 请提供完整代码
  • @mujjiga 很高兴。我已经添加了完整的代码

标签: python keras neural-network mlp


【解决方案1】:

在训练过程中,存在几种不同的随机性来源。您需要消除所有这些以获得完美可重现的结果。以下是其中的一些:

  1. 随机权重和偏置初始化导致每次训练运行不同。

  2. 在训练过程中使用了小批量,每次都会对训练过程的轨迹产生不同的影响。因此,使用随机梯度下降 (SGD) 作为优化技术的每个训练过程都会观察到不同的输入顺序。

  3. 由正则化技术(如 Dropout)引起的随机性。

    可以通过设置固定种子来克服其中一些随机性来源,this older question 中描述了如何做到这一点。 paper 列出了其他几个可能的偏差来源(例如数据扩充或硬件差异)。

【讨论】:

  • 感谢您的回复,如果我可以再次询问如何在我的代码中应用它?
【解决方案2】:
How can I get constant value val accuracy and val loss in keras

我猜你想要的是可重现的火车运行。为此你必须播种随机数生成器.使用种子获得可重现的结果在 GPU 上很棘手,因为 GPU 上的某些操作是不确定的。但是,对于您正在使用的模型架构,这不是问题。

make model not start off with the computed weights from the previous training.

事实并非如此,您每次都在创建模型,并且您正在使用的 Dense 层是从 glorot_uniform 分布中初始化的。

样本:

from sklearn.preprocessing import LabelEncoder
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras import optimizers
from tensorflow.keras import callbacks
import matplotlib.pyplot as plt

import os
import numpy as np
import random as rn
import random as python_random

def seed():  
  os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
  os.environ["CUDA_VISIBLE_DEVICES"] = ""
  np.random.seed(123)
  python_random.seed(123)
  tf.random.set_seed(1234)


def train(set_seed):
  if set_seed:
    seed()

  dataset = {
      'review': [
          'This is the first document.',
          'This document is the second document.',
          'And this is the third one.',
          'Is this the first document?',
      ],
      'sentiment': [0,1,0,1]
  }

  Train_X2, Test_X2, Train_Y2, Test_Y2 = train_test_split(
      dataset['review'],dataset['sentiment'],test_size=0.2, random_state=1)

  Encoder = LabelEncoder()

  Train_Y2 = Encoder.fit_transform(Train_Y2)
  Test_Y2 = Encoder.fit_transform(Test_Y2)

  Tfidf_vect2 = TfidfVectorizer(max_features=None)
  Tfidf_vect2.fit(dataset['review'])
  Train_X2_Tfidf = Tfidf_vect2.transform(Train_X2).toarray()
  Test_X2_Tfidf = Tfidf_vect2.transform(Test_X2).toarray()

  #Model
  model = keras.Sequential()
  model.add(layers.Dense(100, input_dim= 9, activation='sigmoid'))
  model.add(layers.Dense(1, activation='sigmoid'))
  opt = optimizers.Adam (learning_rate=0.01)
  model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])
  #model.summary()
    
  history = model.fit(Train_X2_Tfidf, Train_Y2, epochs=10,verbose=0, 
                      validation_data=(Test_X2_Tfidf, Test_Y2), batch_size=32)
  return history


def run(set_seed=False):
  plt.figure(figsize=(7,7))
  for i in range(5):
    history = train(set_seed)
    plt.plot(history.history['val_loss'], label=f"{i+1}")
    plt.legend()
    plt.title("With Seed" if set_seed else "Wihout Seed")


run()
run(True)

输出:

您可以看到 val_loss 在没有种子的情况下有何不同(因为它取决于 Dense 层的初始值和使用随机数生成的其他地方)以及 val_loss 如何与确保初始值的种子完全相同您正在使用的密集层的值在运行之间是相同的(以及在使用随机数生成的其他地方)。

【讨论】:

    猜你喜欢
    • 2019-11-10
    • 2017-07-16
    • 1970-01-01
    • 2018-10-06
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多