R语言optim函数maxit参数设置不生效问题求助
R语言optim函数maxit参数不生效的原因与解决方法
问题背景
使用R语言optim函数时,设置control=list(maxit=2)指定迭代次数为2,但代码运行耗时久,且通过目标函数内的计数变量发现实际调用次数远超设定值。
原始代码
cost <- function(theta){ record <- NULL record_2 <- NULL num <<- num + 1 for(i in 1:124){ loss <- log(1 + exp(-data_train$CellType[i] * (t(theta) %*% as.numeric(data_train[i,-1228])))) record <- c(record,loss) loss_2 <- log(1 + exp(-data_test$CellType[i] * (t(theta) %*% as.numeric(data_test[i,-1228])))) record_2 <- c(record_2,loss_2) } training_cost[num] <<- mean(record) test_cost[num] <<- mean(record_2) result <- mean(record) return(result) } num <- 0 training_cost <- NULL test_cost <- NULL theta_initial <- rep(0, 1227) optimum_theta <- optim(par = theta_initial, fn = cost, method = "BFGS", control=list(maxit=2))
问题更新后的代码
colnames(data_plot)[3] <- "CellType" n <- nrow(data_plot) set.seed(12345) id <- sample(1:n,floor(n * 0.5)) data_train <- data_plot[id,] data_test <- data_plot[-id,] data_train$CellType <- ifelse(data_train$CellType == "T-cell",1,-1) data_test$CellType <- ifelse(data_test$CellType == "T-cell",1,-1) data_train_p <- as.matrix(data_train[,-3]) data_test_p <- as.matrix(data_train[,-3]) # 此处存在错误 lossfun <- function(theta,X, Y){ result <- mean(log(1 + exp(-Y * (X %*%theta)))) return(result) } cost <- function(theta){ loss_train <- lossfun(theta,X = data_train_p,Y = data_train$CellType) loss_test <- lossfun(theta,X= data_test_p,Y = data_test$CellType) num <<- num + 1 training_cost[num] <<- loss_train test_cost[num] <<- loss_test return(loss_train) } num <- 0 training_cost <- NULL test_cost <- NULL theta_initial <- rep(0,2) optimum_theta <- optim(par = theta_initial,fn = cost,method = "BFGS",control=list(maxit=20)) iteration <- 1:num data_plot <- data.frame(iteration,training_cost,test_cost) data_plot <- reshape2::melt(data_plot,id.var = "iteration") library(ggplot2) ggplot(data_plot,aes(x=iteration,y= value,color= variable)) + geom_line()
原因分析
混淆「算法迭代次数」与「目标函数调用次数」:
optim的maxit参数控制的是BFGS算法本身的迭代次数,但每一次算法迭代需要多次调用目标函数(比如计算梯度的有限差分、线搜索过程)。你在cost函数里用num <<- num +1统计的是目标函数被调用的次数,这个数值必然远大于maxit设定的迭代次数,并非参数不生效。测试集数据赋值错误:
更新后的代码中data_test_p <- as.matrix(data_train[,-3])错误地将训练集数据赋值给测试集矩阵,导致测试损失计算错误,但这和maxit参数无关。目标函数效率低下:
原始代码用循环逐个计算损失,R语言中循环效率极低,导致运行耗时久,让你误以为是迭代次数超标的问题。
解决方法
1. 正确区分迭代次数与函数调用次数
- 查看
optim返回结果的counts字段:optimum_theta$counts,其中第一个值是目标函数调用次数,第二个是梯度调用次数(若使用解析梯度)。 - 若需要追踪算法迭代次数,使用
control=list(maxit=2, trace=1),optim会打印每一步迭代的信息,直接查看实际迭代次数,无需在目标函数内计数。
2. 修正测试集数据错误
将data_test_p <- as.matrix(data_train[,-3])修改为:
data_test_p <- as.matrix(data_test[,-3])
3. 优化目标函数性能(解决耗时问题)
- 用矩阵化运算替代循环,大幅提升计算速度:
比如原始循环中的损失计算可以替换为:# 训练集损失矩阵化计算 train_loss <- log(1 + exp(-data_train$CellType * (data_train_p %*% theta))) training_cost[num] <- mean(train_loss) # 测试集损失矩阵化计算 test_loss <- log(1 + exp(-data_test$CellType * (data_test_p %*% theta))) test_cost[num] <- mean(test_loss) - 避免使用全局变量(
<<-),可以通过闭包或后续单独计算各迭代点的损失来记录训练/测试损失,比如在optim运行后,提取每一步迭代的theta值(需开启trace或自定义追踪),再批量计算损失。
内容的提问来源于stack exchange,提问作者Jin Yan
相关产品推荐
相关产品推荐

