为什么我的结果仍然无法重现?

立即编码

我想获得CNN的可重复结果。我将Keras和Google Colab与GPU配合使用。

除了建议插入某些代码段(应具有可重复性)的建议之外,我还向各层添加了种子。

###### This is the first code snipped to run #####

!pip install -U -q PyDrive
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from google.colab import auth
from oauth2client.client import GoogleCredentials

# Authenticate and create the PyDrive client.
# This only needs to be done once per notebook.
auth.authenticate_user()
gauth = GoogleAuth()
gauth.credentials = GoogleCredentials.get_application_default()
drive = GoogleDrive(gauth)
###### This is the second code snipped to run #####

from __future__ import print_function  
import numpy as np 

import tensorflow as tf
print(tf.test.gpu_device_name())

import random as rn 
import os 
os.environ['PYTHONASHSEED'] = '0' 
np.random.seed(1)   
rn.seed(1)   
session_conf = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1) 

###### This is the third code snipped to run #####

from keras import backend as K

tf.set_random_seed(1) 
sess = tf.Session(graph=tf.get_default_graph(), config=session_conf)  
K.set_session(sess)   
###### This is the fourth code snipped to run #####

def model_cnn():
  model = Sequential()
  model.add(Conv2D(32, kernel_size=(3,3), kernel_initializer=initializers.glorot_uniform(seed=1), input_shape=(28,28,1)))
  model.add(BatchNormalization())
  model.add(Activation('relu'))

  model.add(Conv2D(32, kernel_size=(3,3), kernel_initializer=initializers.glorot_uniform(seed=2)))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(2,2)))
  model.add(Dropout(0.25, seed=1))  

  model.add(Flatten())

  model.add(Dense(512, kernel_initializer=initializers.glorot_uniform(seed=2)))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Dropout(0.5, seed=1))
  model.add(Dense(10, kernel_initializer=initializers.glorot_uniform(seed=2)))
  model.add(Activation('softmax'))

  model.compile(loss="categorical_crossentropy", optimizer=Adam(lr=0.001), metrics=['accuracy'])
  return model


def split_data(X,y):
  X_train_val, X_val, y_train_val, y_val = train_test_split(X, y, random_state=42, test_size=1/5, stratify=y) 
  return(X_train_val, X_val, y_train_val, y_val) 


def train_model_with_EarlyStopping(model, X, y):
  # make train and validation data
  X_tr, X_val, y_tr, y_val = split_data(X,y)

  es = EarlyStopping(monitor='val_loss', patience=20, mode='min', restore_best_weights=True)

  history = model.fit(X_tr, y_tr,
                      batch_size=64,
                      epochs=200, 
                      verbose=1,
                      validation_data=(X_val,y_val),
                      callbacks=[es])    

  return history
###### This is the fifth code snipped to run #####

train_model_with_EarlyStopping(model_cnn(), X, y)

总是我运行上面的代码,我得到不同的结果。原因是否出在代码中,还是根本无法在支持GPU的Google Colab中获得可重复的结果?


完整的代码(代码中有不必要的部分,例如未使用的库):

!pip install -U -q PyDrive
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from google.colab import auth
from oauth2client.client import GoogleCredentials
auth.authenticate_user()
gauth = GoogleAuth()
gauth.credentials = GoogleCredentials.get_application_default()
drive = GoogleDrive(gauth)
from __future__ import print_function # NEU 
import numpy as np 

import tensorflow as tf
import random as rn 
import os 
os.environ['PYTHONASHSEED'] = '0' 
np.random.seed(1)   
rn.seed(1)   
session_conf = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1) 
from keras import backend as K

tf.set_random_seed(1)  
sess = tf.Session(graph=tf.get_default_graph(), config=session_conf)   
K.set_session(sess)  

import os
local_root_path = os.path.expanduser("~/data/data")
print(local_root_path)
try:
  os.makedirs(local_root_path, exist_ok=True)  
except: pass

def ListFolder(google_drive_id, destination):
  file_list = drive.ListFile({'q': "'%s' in parents and trashed=false" % google_drive_id}).GetList()
  counter = 0
  for f in file_list:
    # If it is a directory then, create the dicrectory and upload the file inside it
    if f['mimeType']=='application/vnd.google-apps.folder': 
      folder_path = os.path.join(destination, f['title'])
      os.makedirs(folder_path, exist_ok=True)
      print('creating directory {}'.format(folder_path))
      ListFolder(f['id'], folder_path)
    else:
      fname = os.path.join(destination, f['title'])
      f_ = drive.CreateFile({'id': f['id']})
      f_.GetContentFile(fname)
      counter += 1
  print('{} files were uploaded in {}'.format(counter, destination))
ListFolder("1DyM_D2ZJ5UHIXmXq4uHzKqXSkLTH-lSo", local_root_path)

import glob
import h5py
from time import time
from keras import initializers 
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential, model_from_json
from keras.layers import Dense, Dropout, Activation, Flatten, BatchNormalization, merge
from keras.layers import Convolution2D, MaxPooling2D, AveragePooling2D
from keras.optimizers import SGD, Adam, RMSprop, Adagrad, Adadelta, Adamax, Nadam
from keras.utils import np_utils
from keras.callbacks import LearningRateScheduler, ModelCheckpoint, TensorBoard, ReduceLROnPlateau
from keras.regularizers import l2
from keras.layers.advanced_activations import LeakyReLU, ELU
from keras import backend as K
import numpy as np
import pickle as pkl
from matplotlib import pyplot as plt
%matplotlib inline
import gzip
import numpy as np
from keras.utils import to_categorical
from keras.models import Sequential
from keras.layers import Dense, Conv2D, Flatten
from keras.datasets import fashion_mnist
from numpy import mean, std
import matplotlib.pyplot as plt
from sklearn.model_selection import KFold, StratifiedKFold
from keras.datasets import fashion_mnist
from keras.utils import to_categorical
from keras.layers import Conv2D, MaxPooling2D, Dense, Flatten
from keras.optimizers import SGD, Adam
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
from sklearn.metrics import auc, average_precision_score, f1_score

import time
from keras.callbacks import EarlyStopping
from keras.callbacks import ModelCheckpoint
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
from google.colab import files
from PIL import Image 



def model_cnn():
  model = Sequential()
  model.add(Conv2D(32, kernel_size=(3,3), kernel_initializer=initializers.glorot_uniform(seed=1), input_shape=(28,28,1)))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Conv2D(32, kernel_size=(3,3), kernel_initializer=initializers.glorot_uniform(seed=2)))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(2,2)))
  model.add(Dropout(0.25, seed=1))  
  model.add(Flatten())
  model.add(Dense(512, kernel_initializer=initializers.glorot_uniform(seed=2)))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Dropout(0.5, seed=1))
  model.add(Dense(10, kernel_initializer=initializers.glorot_uniform(seed=2)))
  model.add(Activation('softmax'))
  model.compile(loss="categorical_crossentropy", optimizer=Adam(lr=0.001), metrics=['accuracy'])
  return model

def train_model_with_EarlyStopping(model, X, y):
  X_tr, X_val, y_tr, y_val = split_train_val_data(X,y)
  es = EarlyStopping(monitor='val_loss', patience=20, mode='min', restore_best_weights=True)      
  history = model.fit(X_tr, y_tr,
                      batch_size=64,
                      epochs=200, 
                      verbose=1,
                      validation_data=(X_val,y_val),
                      callbacks=[es])    
  evaluate_model(model, history, X_tr, y_tr)
  return history 


```



霸王龙

该问题不仅限于Colab,而且可以在本地重现。但是,这种行为可能是不可避免的。

底部的代码是代码的最低可复制版本,并调整了适合参数以加快测试速度。我观察到的是,在5次运行中,每次运行468次迭代的最大损失差异仅为0.0144%很好 使用batch_size=6460000样本和20时期,您将进行18750次迭代-这将大大放大此数字。

无论如何,GPU并行性驱动随机数的最可能的罪魁祸首-随着时间的推移,细微差异的确会累积,从而产生实质性差异-如下所示。如果1e-8看起来很小,请尝试将随机噪声添加到您的一半权重1e-8,将其剪裁为,并见证其生活理念的变化。

如果您不使用种子,它们的作用将变得非常明显-尝试一下,您的所有指标在前10次迭代中都会泛滥。同样,损失更适合测量运行时间差异,因为准确性对数值精度误差更为敏感:10个样本批次的60%准确性和70%准确性之间的差异是根据0.000001wrt进行的预测0.5-但损失几乎不会动摇。

最后,请注意,您选择超参数对模型性能的影响远大于随机性。不管您扔多少种子,它们都不会将模型变成SOTA。-我推荐这个精美的剪辑


您的代码-很好。您已采取所有实际步骤来确保可重复性,但有一个例外:PYTHONHASHSEED必须在启动Python内核之前进行设置


您可以采取什么措施减少随机性?

  1. 重复运行,平均结果可以理解这是很昂贵的,但是请注意,即使是完全可重现的运行也不能完全提供信息,因为带有训练和验证集的模型方差可能远大于噪声引起的随机性

  2. K折交叉验证:可以显着减轻数据和噪声差异

  3. 更大的验证集:由于噪声,提取的特征可能相差太大;验证集越大,权重的扰动应在指标中反映的越少


GPU并行性:放大浮动错误

print(2. * 11. / 9.)  # 2.4444444444444446
print(2. / 9. * 11.)  # 2.444444444444444

操作顺序很重要,并且通过利用多线程,GPU并行性无法保证以相同顺序执行任何操作。乍一看,差异可能看起来是无害的-但要给予足够的迭代...

one = 1
for _ in range(int(1e8)):
    one *= (2. / 9. * 11.) / (2. * 11. / 9.)
print(one)     # 0.9999999777955395
print(1 - one) # 1.8167285897874308e-08

...“一个”是一个典型的很小的权重值,它1e-08远离了它的原始自我。如果1亿次迭代似乎很繁琐,请考虑一下该操作在大约半分钟内完成,而您的模型可以训练一个多小时,而前一个模型完全在CPU上运行。


最少的可重复实验

import tensorflow as tf
import random as rn 
import numpy as np
np.random.seed(1)   
rn.seed(2)   
tf.set_random_seed(3)

from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten, BatchNormalization
from keras.layers import MaxPooling2D, Conv2D
from keras.optimizers import Adam

def model_cnn():
  model = Sequential()
  model.add(Conv2D(32, kernel_size=(3,3), 
                   kernel_initializer='he_uniform', input_shape=(28,28,1)))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Conv2D(32, kernel_size=(3,3), kernel_initializer='he_uniform'))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(2,2)))
  model.add(Dropout(0.25))
  model.add(Flatten())
  model.add(Dense(512, kernel_initializer='he_uniform'))
  model.add(BatchNormalization())
  model.add(Activation('relu'))
  model.add(Dropout(0.5))
  model.add(Dense(10, kernel_initializer='he_uniform'))
  model.add(Activation('softmax'))
  model.compile(loss="categorical_crossentropy", optimizer=Adam(lr=0.001), 
                metrics=['accuracy'])
  return model

np.random.seed(1)   
rn.seed(2)     
tf.set_random_seed(3) 

X_train = np.random.randn(30000, 28, 28, 1)
y_train = np.random.randint(0, 2, (30000, 10))
X_val   = np.random.randn(30000, 28, 28, 1)
y_val   = np.random.randint(0, 2, (30000, 10))
model = model_cnn()

np.random.seed(1)   
rn.seed(2)   
tf.set_random_seed(3)

history = model.fit(X_train, y_train, batch_size=64,shuffle=True, 
                    epochs=1, verbose=1, validation_data=(X_val,y_val))

运行差异

loss: 12.5044 - acc: 0.0971 - val_loss: 11.5389 - val_acc: 0.1051
loss: 12.5047 - acc: 0.0958 - val_loss: 11.5369 - val_acc: 0.1018
loss: 12.5055 - acc: 0.0955 - val_loss: 11.5382 - val_acc: 0.0980
loss: 12.5042 - acc: 0.0961 - val_loss: 11.5382 - val_acc: 0.1179
loss: 12.5062 - acc: 0.0960 - val_loss: 11.5366 - val_acc: 0.1082

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么即使在我的路上,pip仍然无法识别?

来自分类Dev

为什么我仍然收到“无法发布”消息?

来自分类Dev

为什么我添加列后我的SQLite仍然无法在我的片段中工作

来自分类Dev

反应-为什么我已经更改状态后仍然得到相同的结果

来自分类Dev

为什么我在Google CSE结果中仍然看到底部边框?

来自分类Dev

为什么我仍然无法将我的代码推送到 github?

来自分类Dev

为什么我的全文搜索无法产生结果?

来自分类Dev

为什么我的功能无法产生理想的结果?

来自分类Dev

为什么我无法从Angular的父组件获得结果

来自分类Dev

为什么我的函数无法从提取中获取结果?

来自分类Dev

为什么我无法从Alamofire获得请求结果

来自分类Dev

为什么我无法访问多个网络调用的结果?

来自分类Dev

为什么我的弦仍然是空的?

来自分类Dev

为什么我仍然看到旧图标?

来自分类Dev

为什么我的nsmutuablearray仍然为null?

来自分类Dev

为什么iptables仍然阻止我的samba?

来自分类Dev

无法弄清楚为什么我的else语句仍然使用负输入调用此函数

来自分类Dev

AngularJS $ scope包含我的绑定变量,但是以后仍然无法访问,为什么?

来自分类Dev

为什么我仍然收到“由于其保护级别而无法访问”错误?

来自分类Dev

为什么我的 azurewebsites.net 在连接到虚拟网络后仍然无法访问

来自分类Dev

为什么我的计划任务正确地更新了其“上次运行时间”,并给出了“上次运行结果”为“(0x0)”,但仍然无法正常工作?

来自分类Dev

为什么我的php代码无法使用chr输出与我的C ++相同的结果

来自分类Dev

为什么我仍然找不到Java SE Runtime Environment?

来自分类Dev

斯威夫特:为什么我仍然需要可选件?

来自分类Dev

为什么我仍然需要拆开Swift字典值?

来自分类Dev

为什么我使用这样的for循环,但仍然收到IndexError?

来自分类Dev

为什么我的表单提交仍然刷新页面?

来自分类Dev

为什么我们仍然使用CPU而不是GPU?

来自分类Dev

为什么我的python在安装2.7.6之后仍然显示2.7.3

Related 相关文章

  1. 1

    为什么即使在我的路上,pip仍然无法识别?

  2. 2

    为什么我仍然收到“无法发布”消息?

  3. 3

    为什么我添加列后我的SQLite仍然无法在我的片段中工作

  4. 4

    反应-为什么我已经更改状态后仍然得到相同的结果

  5. 5

    为什么我在Google CSE结果中仍然看到底部边框?

  6. 6

    为什么我仍然无法将我的代码推送到 github?

  7. 7

    为什么我的全文搜索无法产生结果?

  8. 8

    为什么我的功能无法产生理想的结果?

  9. 9

    为什么我无法从Angular的父组件获得结果

  10. 10

    为什么我的函数无法从提取中获取结果?

  11. 11

    为什么我无法从Alamofire获得请求结果

  12. 12

    为什么我无法访问多个网络调用的结果?

  13. 13

    为什么我的弦仍然是空的?

  14. 14

    为什么我仍然看到旧图标?

  15. 15

    为什么我的nsmutuablearray仍然为null?

  16. 16

    为什么iptables仍然阻止我的samba?

  17. 17

    无法弄清楚为什么我的else语句仍然使用负输入调用此函数

  18. 18

    AngularJS $ scope包含我的绑定变量,但是以后仍然无法访问,为什么?

  19. 19

    为什么我仍然收到“由于其保护级别而无法访问”错误?

  20. 20

    为什么我的 azurewebsites.net 在连接到虚拟网络后仍然无法访问

  21. 21

    为什么我的计划任务正确地更新了其“上次运行时间”,并给出了“上次运行结果”为“(0x0)”,但仍然无法正常工作?

  22. 22

    为什么我的php代码无法使用chr输出与我的C ++相同的结果

  23. 23

    为什么我仍然找不到Java SE Runtime Environment?

  24. 24

    斯威夫特:为什么我仍然需要可选件?

  25. 25

    为什么我仍然需要拆开Swift字典值?

  26. 26

    为什么我使用这样的for循环,但仍然收到IndexError?

  27. 27

    为什么我的表单提交仍然刷新页面?

  28. 28

    为什么我们仍然使用CPU而不是GPU?

  29. 29

    为什么我的python在安装2.7.6之后仍然显示2.7.3

热门标签

归档