如何实现R语言Keras神经网络模型训练结果可复现
R语言Keras神经网络结果不可复现解决方案
核心原因
R原生的set.seed()仅能控制R层面的随机数生成逻辑,Keras依托TensorFlow后端运行,其权重初始化、训练批次打乱、优化器随机更新、GPU/多线程并行计算带来的浮点运算顺序差异,都不受R原生随机种子控制,因此仅在代码中添加set.seed()无法保证结果可复现。
配置步骤
要实现完全可复现,需要覆盖所有随机环节的配置:
- 提前设置环境变量,强制TensorFlow调用确定性计算算子,禁用非确定性的并行优化
- 同时设置R、Python解释器、TensorFlow三个层面的随机种子,不能仅设置R的种子
- 限制TensorFlow运算线程数为1,避免多线程下浮点运算顺序不一致带来的结果偏差
- 如果使用GPU运行仍存在微小差异,可强制禁用GPU、使用单线程CPU运行,即可得到100%一致的结果
修正后的可复现代码
library(keras) library(caret) library(tensorflow) # -------------------------- # 可复现性基础配置(必须放在所有随机操作、模型构建之前执行) # -------------------------- # 配置环境变量强制确定性运算 Sys.setenv(TF_DETERMINISTIC_OPS = "1") Sys.setenv(PYTHONHASHSEED = "0") # 限制TensorFlow为单线程运行,消除并行计算带来的随机性 tf$config$threading$set_intra_op_parallelism_threads(1L) tf$config$threading$set_inter_op_parallelism_threads(1L) # 统一设置所有层面的随机种子 seed_value <- 123 set.seed(seed_value) tf$random$set_seed(seed_value) use_session_with_seed( seed = seed_value, disable_gpu = FALSE, # 若GPU运行仍有差异可改为TRUE,强制用CPU运行 disable_parallel_cpu = TRUE ) # -------------------------- # 原数据生成、拆分逻辑 # -------------------------- n = 400 s = seq(.1, n / 10, .1) x1 = s * sin(s / 50) - rnorm(n) * 5 x2 = s * sin(s) + rnorm(n) * 10 x3 = s * sin(s / 100) + 2 + rnorm(n) * 10 y1 = x1 + x2 + x3 + 2 + rnorm(n) * 2 y2 = x1 + x2 / 2 - x3 - 4 - rnorm(n) df = data.frame(x1, x2, x3, y1, y2) plot(s, df$y1, ylim = c(min(df), max(df)), type = "l", col = "blue") lines(s, df$y2, type = "l", col = "red") lines(s, df$x1, type = "l", col = "green") lines(s, df$x2, type = "l", col = "yellow") lines(s, df$x3, type = "l", col = "gray") indexes = createDataPartition(df$x1, p = .85, list = F) train = df[indexes,] test = df[-indexes,] xtrain = as.matrix(data.frame(train$x1, train$x2, train$x3)) ytrain = as.matrix(data.frame(train$y1, train$y2)) xtest = as.matrix(data.frame(test$x1, test$x2, test$x3)) ytest = as.matrix(data.frame(test$y1, test$y2)) in_dim = dim(xtrain)[2] out_dim = dim(ytrain)[2] # -------------------------- # 模型构建与训练 # -------------------------- model = keras_model_sequential() %>% layer_dense(units = 100, activation="relu", input_shape=in_dim) %>% layer_dense(units = 32, activation = "relu") %>% layer_dense(units = out_dim, activation = "linear") model %>% compile( loss = "mse", optimizer = "adam" ) model %>% summary() # 训练时固定数据顺序,避免批次打乱带来的差异 model %>% fit( xtrain, ytrain, epochs = 100, verbose = 1, shuffle = FALSE ) scores = model %>% evaluate(xtrain, ytrain, verbose = 0) print(scores) ypred = model %>% predict(xtest) cat("y1 RMSE:", RMSE(ytest[, 1], ypred[, 1])) cat("y2 RMSE:", RMSE(ytest[, 2], ypred[, 2]))
注意事项
- 所有可复现性配置必须放在代码最开头、加载包之后立刻执行,在数据生成、模型构建之前完成配置才会生效
- 如果安装的TensorFlow版本较高,
use_session_with_seed函数可能被标记为软弃用,保留上述其他配置项也可实现可复现 - 若GPU运行时仍存在结果波动,将
disable_gpu参数改为TRUE强制使用CPU运行,即可保证每次运行结果完全一致
内容的提问来源于stack exchange,提问作者TUSTLGC
相关产品推荐
相关产品推荐

