Keras模型的可重复性仅在单线程运行时才有可能?

在过去几个小时里,我一直在处理我的Keras/TensorFlow代码,试图通过为每个使用的随机生成器设定种子来获得可重复的结果。现在我的解决方案确实有效,但奇怪的是,只有当我使用单线程运行代码时才有效,使用的代码如下:

from keras import backend as Kconfig = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)sess = tf.Session(graph=tf.get_default_graph(), config=config)K.set_session(sess)

我无法解释这种行为,因此我想了解你们对此的看法。为了进一步理解,我将在下面发布我的完整代码:

import tensorflow as tfrandom.seed(seed_value)np.random.seed(seed_value)tf.set_random_seed(seed_value)from keras import backend as Kconfig = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)sess = tf.Session(graph=tf.get_default_graph(), config=config)K.set_session(sess)""""""import pandas as pd # 数据处理,CSV文件I/O(例如pd.read_csv)import matplotlib.pyplot as pltfrom sklearn import preprocessing, model_selectionfrom sklearn.decomposition import PCAfrom keras.models import load_modelfrom keras.utils import np_utilsfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.preprocessing import LabelEncoder, StandardScalerfrom keras.utils.np_utils import to_categoricalfrom sklearn.utils import shufflefrom sklearn.metrics import confusion_matrixfrom TimingCallback import TimeHistorydef train():    files = ['RAW_combined_shuffled.csv']    # select = ['html_tag_script', 'js_max_value_assignments', 'url_found_scripttags', 'url_param_count_"', 'label']    # read_files = (pd.read_csv(f, usecols=select) for f in files)      # 只读取选定的特征    read_files = (pd.read_csv(f) for f in files)                        # 读取所有特征    data = pd.concat(read_files, ignore_index=True)    data = data.drop(['data'], axis=1)  # 删除单个列 // 通过KNIME完成    # data = shuffle(data)  # 随机化数据集的顺序  //通过KNIME完成    i = 100    data_to_predict = data[:i].reset_index(drop=True)  # 分割用于测试模型的数据(从开始到i)    real_label = data_to_predict.label    real_label = np.array(real_label)    prediction = np.array(data_to_predict.drop(['label'], axis=1))    data = data[i:].reset_index(drop=True)  # 分割用于训练和测试的数据(从i到结束)    X = data.drop(['label'], axis=1)  # X 是除输出标签外的所有列    X = np.array(X)    Y = data['label']  # Y 是包含输出标签的列    # 将名称种类转换为数值    encoder = LabelEncoder()    encoder.fit(Y)    Y = encoder.transform(Y)    Y = np_utils.to_categorical(Y)    # 我们有类别:输出看起来像:    # 0,1 : 类别1    # 1,0 : 类别2    # 分割训练和测试数据;random_state 是用于生成随机数的种子,用于确定哪些数据集用于训练,哪些用于测试    train_x, test_x, train_y, test_y = model_selection.train_test_split(X, Y, test_size=0.3, random_state=5, shuffle=False)    input_dim = len(data.columns) - 1    print(input_dim)    callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)    time_callback = TimeHistory()    model = tf.keras.Sequential()    model.add(tf.keras.layers.Dense(8, input_dim=input_dim, activation='sigmoid'))    model.add(tf.keras.layers.Dense(10, activation='sigmoid'))    model.add(tf.keras.layers.Dense(10, activation='sigmoid'))    model.add(tf.keras.layers.Dense(10, activation='sigmoid'))    model.add(tf.keras.layers.Dense(2, activation='softmax'))    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])    # 开始训练若干轮次    # validation_split 取训练数据的一部分用于验证(用于在每轮结束时确定val_acc和val_loss)    # verbose 控制显示;0=无显示,1=显示一个进度条,2=每轮显示一个进度条    history = model.fit(train_x, train_y, validation_split=0.33, epochs=1000, batch_size=1000, verbose=1, callbacks=[callback, time_callback], shuffle=False)    scores = model.evaluate(test_x, test_y)

如您所见,我还在model.fit方法和train_test_split中禁用了洗牌选项。因为我想进一步提高训练性能,我通常希望使用多个线程和因此更多的CPU核心。


回答:

是的,这是有道理的,这个问题由两部分组成:

  • 浮点数只是对实数的近似,特别是因为不是所有数字都能被表示,并且加法不是结合律的。例如 (a + b) + c != a + (b + c),因为每次加法都可能四舍五入到最接近的浮点数,从而产生略有不同的结果。例如在Python中:

    (0.1 + 0.2) + 0.3 的结果是0.6000000000000001。

    0.1 + (0.2 + 0.3) 的结果是0.6。

  • 使用多线程进行并行计算会给过程引入更多的随机性,因为现在涉及到了调度器和其他进程。问题发生在从多个线程中添加变量时,例如当合并来自多个线程的结果时,通常使用锁并写入同一个变量,但每个线程执行此操作的顺序是未定义的,并且会改变结果。

这也发生在GPU内部,所以不幸的是,如果你想要可重复的结果,你需要尽量减少跨线程的并行使用(因此不使用多线程)。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注