我在尝试使用R包neuralnet中预设的“logistic”和“tanh”之外的激活函数。具体来说,我想使用整流线性单元(ReLU)f(x) = max{x,0}。请看我下面的代码。
我认为如果定义了自定义函数(例如)
custom <- function(a) {x*2}
我可以使用自定义函数,但如果我用max(x,0)替换x*2,R会告诉我“max不在导数表中”,使用“>”运算符时也是如此。所以我在寻找一个合理的解决方法,因为我认为在这种情况下对max进行数值积分应该不是问题。
nn <- neuralnet( as.formula(paste("X",paste(names(Z[,2:10]), collapse="+"),sep="~")), data=Z[,1:10], hidden=5, err.fct="sse", act.fct="logistic", rep=1, linear.output=TRUE)
有什么想法吗?我有点困惑,因为我没想到neuralnet
包会进行解析微分。
回答:
neuralnet
包的内部会尝试对提供给act.fct
的任何函数进行微分。你可以在这里查看源代码这里。
在第211行你会找到以下代码块:
if (is.function(act.fct)) { act.deriv.fct <- differentiate(act.fct) attr(act.fct, "type") <- "function"}
differentiate
函数是对deriv
函数的更复杂使用,你也可以在上面的源代码中看到。因此,目前无法将max(0,x)
提供给act.fct
。这需要在代码中添加一个例外来识别ReLU并“知道”其导数。这将是一个很好的练习,可以获取源代码,添加这个内容并提交给维护者以扩展(但这可能有点过分)。
然而,关于一个合理的解决方法,你可以使用softplus函数,这是ReLU的平滑近似。你的自定义函数看起来会像这样:
custom <- function(x) {log(1+exp(x))}
你也可以在R中查看这个近似:
softplus <- function(x) log(1+exp(x))relu <- function(x) sapply(x, function(z) max(0,z))x <- seq(from=-5, to=5, by=0.1)library(ggplot2)library(reshape2)fits <- data.frame(x=x, softplus = softplus(x), relu = relu(x))long <- melt(fits, id.vars="x")ggplot(data=long, aes(x=x, y=value, group=variable, colour=variable))+ geom_line(size=1) + ggtitle("ReLU & Softplus") + theme(plot.title = element_text(size = 26)) + theme(legend.title = element_blank()) + theme(legend.text = element_text(size = 18))