公式错误导致神经网络出错

3
这实际上是一个完全有用的问题的副本,其答案(部分)由提问者得出。原标题:“在R中用于文本分析的neuralnet模型的超过512个字符的公式”。他最终解决了问题,尽管他给出的推理是不正确的,并且通过删除问题并使评论和解决方案不可见而使这个错误更加复杂。
我正在尝试拟合一个神经网络模型,用于将网站分类到两个桶中的一个。训练数据特征是网站上所有链接中的单词,因此例如,一个网站可能具有“主页”,“关于”,“联系人”,“产品”等功能。数据结构化为一个包含类列以及每个训练中单词的列的数据帧。每行都具有类别(合格或不合格)和在该网站上出现的每个单词的0和1。
出现相当数量次数的单词总列表约为1000个,我想使用它们作为功能。但是,公式似乎存在225个字符的限制,因此我无法这样做。
我没有一个好的数据集来给出可重复的输出,但这里是我的代码和我得到的错误。
如果我尝试进行公式,则会被截断:
nn.model <- neuralnet(paste("class ~ ", paste(clean.features, collapse = "+", sep = "")), data = training.data, 
                hidden = num.nodes)
                )
Error in parse(text = x, keep.source = FALSE) : :2:0: unexpected end of input 1: ranty+recipes+contract+just+inventory+types+working+wine+hampshire+suppliers+rise+body+selection+laurel+trek+arlington+cabinet+citrus+advertisers+rhode+highway+intl+province+jewelers+cycles+wy

使用as.formula时也会发生同样的事情:
f <- as.formula(paste("class ~ ", paste(clean.features, collapse = "+", sep = "")))
Error in parse(text = x, keep.source = FALSE) : :2:0: unexpected end of input 1: ranty+recipes+contract+just+inventory+types+working+wine+hampshire+suppliers+rise+body+selection+laurel+trek+arlington+cabinet+citrus+advertisers+rhode+highway+intl+province+jewelers+cycles+wy

如果我尝试使用数据集中的所有功能,它会显示没有“data”参数(即使有):

nn.model <- neuralnet(class ~ . , data = training.data, 
                hidden = num.nodes, 0))
                )
Error in terms.formula(formula) : '.' in formula and no 'data' argument

> sessionInfo()
R version 3.3.2 (2016-10-31) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows >= 8 x64 (build 9200)

有什么解决方法吗?

原文链接:http://stackoverflow.com/questions/42235474/formulas-with-more-than-512-characters-for-neuralnet-model-in-r-for-text-analysi - IRTFM
2个回答

2
我将建议一个可能的起点来隔离问题。如果问题仅与公式长度有关,则应该可以通过创建公式本身来重现问题。请尝试以下方法:
form <- reformulate( clean.features, quote(class) )

额,仅仅打这个让我的R解析器内部感到不适。请将你的LHS变量重命名为除了这个核心R函数以外的其他名称。也许可以改成这样:

names( training.data)[ names(training.data) %in% "class"] <- "myclass"
form <- reformulate( clean.features, quote(myclass) )

问题的提问者在回复其他评论时提到了一个他不再重复的问题。我曾经告诉他,他关于字符限制为512个字符的理论是不正确的,但他随后发帖说:
“因此,在进行了大量手动审核后,看起来单词‘for’恰好位于其他帖子中提到的字符限制(512)处。但实际问题是‘for’被识别为公式中的函数。对于所有的混淆,我感到抱歉。”
这是不正确的。问题与公式中的字符限制无关,而是与他的列名“for”有关。这是R中的保留控制函数,并且会在公式中的任何位置出现。请参见此演示(显示一些保留字确实会这样做,但并非全部)。
f <- reformulate(c( paste(sep="","X",1:5), "for", paste(sep="","X",1:5)), quote(Y))
Error in parse(text = termtext, keep.source = FALSE) : 
  <text>:1:30: unexpected '+'
1: response ~ X1+X2+X3+X4+X5+for+
                                 ^
> f <- reformulate(c( paste(sep="","X",1:5), "class", paste(sep="","X",1:5)), quote(Y))
# no error ... OK perhaps not a reserved word
> f <- reformulate(c( paste(sep="","X",1:5), "in", paste(sep="","X",1:5)), quote(Y))
Error in parse(text = termtext, keep.source = FALSE) : 
  <text>:1:27: unexpected 'in'
1: response ~ X1+X2+X3+X4+X5+in
                              ^
> f <- reformulate(c( paste(sep="","X",1:5), "TRUE", paste(sep="","X",1:5)), quote(Y))
#  no error, so maybe "TRUE" is not reserved and quote(TRUE) is?

因此,提出一个术语是否可以与函数共享名称的问题是正确的。答案并不完全符合我的预期。如果有人想提供更仔细的计算机科学解释,我很乐意核对他们的努力。

另一个出现这个问题的背景是使用前缀-?运算符调用帮助页面。尝试使用?for获取帮助。你只会得到一个行继续+提示。解析器正在等待左括号。


1

摘要:

  • 问题: reformulate(c( paste(sep="","X",1:5), "for", paste(sep="","X",1:5) ), quote(Y))
  • 解决方案: deparse(quote(`for`), backtick = TRUE)

详细信息:

在调试以下代码后,我也同意您的观点,错误与R语言中保留关键字的评估有关。

reformulate(c( paste(sep="","X",1:5), "for", paste(sep="","X",1:5) ), quote(Y))

实际的错误发生在R解析和评估termtext中的文本时。
Browse[3]> termtext
# [1] "response ~ X1+X2+X3+X4+X5+for+X1+X2+X3+X4+X5"

Browse[3]> n
debug: rval <- eval(parse(text = termtext, keep.source = FALSE)[[1L]])

Browse[3]> n
# Error in parse(text = termtext, keep.source = FALSE) : 
#   <text>:1:30: unexpected '+'
# 1: response ~ X1+X2+X3+X4+X5+for+
#                                  ^

为了重现那个错误,我单独评估了带有加号关键字的 for,结果程序终止。
eval(parse(text = "for+", keep.source = FALSE))
# Error in parse(text = "for+", keep.source = FALSE) : 
#   <text>:1:4: unexpected '+'
# 1: for+
#       ^

完整的调试跟踪:

Browse[3]> n
debug: if (!is.character(termlabels) || !length(termlabels)) stop("'termlabels' must be a character vector of length at least one")
Browse[3]> n
debug: has.resp <- !is.null(response)
Browse[3]> n
debug: termtext <- paste(if (has.resp) "response", "~", paste(termlabels, 
                                                              collapse = "+"), collapse = "")
Browse[3]> ls()
# [1] "has.resp"   "intercept"  "response"   "termlabels"
Browse[3]> has.resp
# [1] TRUE
Browse[3]> intercept
# [1] TRUE
Browse[3]> response
# Y
Browse[3]> termlabels
# [1] "X1"  "X2"  "X3"  "X4"  "X5"  "for" "X1"  "X2"  "X3"  "X4"  "X5" 

Browse[3]> n
debug: if (!intercept) termtext <- paste(termtext, "- 1")
Browse[3]> termtext
# [1] "response ~ X1+X2+X3+X4+X5+for+X1+X2+X3+X4+X5"

Browse[3]> n
debug: rval <- eval(parse(text = termtext, keep.source = FALSE)[[1L]])

Browse[3]> n
# Error in parse(text = termtext, keep.source = FALSE) : 
#   <text>:1:30: unexpected '+'
# 1: response ~ X1+X2+X3+X4+X5+for+
#                                  ^

编辑:

解决方案: 如果这样的计算是不可避免的,那么可以先识别R语言关键字,然后在其周围使用deparse()函数,这将消除它们在该级别作为关键字的评估,而是将其评估为文本。

reformulate(c( paste(sep="","X",1:5), deparse("for"), paste(sep="","X",1:5) ), quote(Y))
# Y ~ X1 + X2 + X3 + X4 + X5 + "for" + X1 + X2 + X3 + X4 + X5 

但是这样会在模型创建过程中产生“无效模型”的错误。更好的方法是在deparse()函数内引用关键词,然后创建一个公式并应用数据模型。
reformulate(c( paste(sep="","X",1:5), deparse(quote(`for`), backtick = TRUE), paste(sep="","X",1:5) ), quote(Y))

# Y ~ X1 + X2 + X3 + X4 + X5 + `for` + X1 + X2 + X3 + X4 + X5

Here is an example:

  df1 <- data.frame(`for` = 6:10, y = 1:5, stringsAsFactors = FALSE)
  colnames(df1) <- c('for', 'y')
  df1
  #   for y
  # 1   6 1
  # 2   7 2
  # 3   8 3
  # 4   9 4
  # 5  10 5

  my_formula <- reformulate(deparse(quote(`for`), backtick = TRUE), 'y')
  my_formula
  # y ~ `for`

  lm(my_formula, data = df1)
  # Call:
  # lm(formula = my_formula, data = df1)
  # 
  # Coefficients:
  #   (Intercept)        `for`  
  #           -5            1 

browser()设置

要更改浏览器错误的全局设置,输入options(error = browser),然后调试代码,然后将其设置回默认值NULL,方法是设置options(error = NULL)

在我的上述调试过程中,我创建了一个名为myfun的函数,并插入了browser()命令,然后进行了源代码。最后,当我调用该函数时,进入了浏览器模式。完成调试过程后,应将插入到函数代码中的browser()命令删除。注意:我没有使用options()将错误选项从null更改为浏览器错误。

myfun <- function() 
{
  browser()
  reformulate(c( paste(sep="","X",1:5), "for", paste(sep="","X",1:5) ), quote(Y))
}

source( 'myfun.R' )
myfun()

要了解浏览器中使用的命令(csnQ等),请参见?browser


深入的演示。建议您添加所需的代码来更改允许使用浏览器的选项的出厂默认设置。 - IRTFM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接