遇到一个问题,为此熬了夜,如果没遇到这篇文章,很难发现原因。

具体描述一下问题,我的代码如下:

var dataDf = ...  // load from other place
val inDoubleCols = dataDf.dtypes.filter(_._2 != "DoubleType"
).map(_._1).toArray[String]
inDoubleCols.forearch(column => {dataDf = dataDf.withColumn(column, col(column).cast(DoubleType))
})val classifier: LightGBMClassifier = new LightGBMClassifier().setFeaturesCol("features").setLabelCol("label")
val model = classifier.fit(dataDf)

在 fit 那句报错了,如下:

...
21/09/17 11:37:34 INFO SparkContext: Created broadcast 7 from rdd at LightGBMBase.scala:195
21/09/17 11:37:34 INFO FileSourceScanExec: Planning scan with bin packing, max size: 134217728 bytes, open cost is considered as scanning 4194304 bytes.
Exception in thread "main" java.lang.StackOverflowErrorat org.apache.spark.sql.catalyst.trees.TreeNode.$anonfun$foreachUp$1$adapted(TreeNode.scala:126)at scala.collection.immutable.List.foreach(List.scala:431)at org.apache.spark.sql.catalyst.trees.TreeNode.foreachUp(TreeNode.scala:126)at org.apache.spark.sql.catalyst.trees.TreeNode.$anonfun$foreachUp$1(TreeNode.scala:126)at org.apache.spark.sql.catalyst.trees.TreeNode.$anonfun$foreachUp$1$adapted(TreeNode.scala:126)at scala.collection.immutable.List.foreach(List.scala:431)at org.apache.spark.sql.catalyst.trees.TreeNode.foreachUp(TreeNode.scala:126)at org.apache.spark.sql.catalyst.trees.TreeNode.$anonfun$foreachUp$1(TreeNode.scala:126)at org.apache.spark.sql.catalyst.trees.TreeNode.$anonfun$foreachUp$1$adapted(TreeNode.scala:126)at scala.collection.immutable.List.foreach(List.scala:431)at org.apache.spark.sql.catalyst.trees.TreeNode.foreachUp(TreeNode.scala:126)at org.apache.spark.sql.catalyst.trees.TreeNode.$anonfun$foreachUp$1(TreeNode.scala:126)at org.apache.spark.sql.catalyst.trees.TreeNode.$anonfun$foreachUp$1$adapted(TreeNode.scala:126)at scala.collection.immutable.List.foreach(List.scala:431)at org.apache.spark.sql.catalyst.trees.TreeNode.foreachUp(TreeNode.scala:126)at org.apache.spark.sql.catalyst.trees.TreeNode.$anonfun$foreachUp$1(TreeNode.scala:126)at org.apache.spark.sql.catalyst.trees.TreeNode.$anonfun$foreachUp$1$adapted(TreeNode.scala:126)at scala.collection.immutable.List.foreach(List.scala:431)at org.apache.spark.sql.catalyst.trees.TreeNode.foreachUp(TreeNode.scala:126)...

很长很长,实际上就是函数把 stack (栈)给堆满了。我和另外两个前辈没见过这种情况,管这种情况叫“超级树”。

按照一般的思路,在 fit 这行报错,那我们怀疑就是 fit 内部某些机制错了,于是各种更换 scala 版本、 spark 版本、 mmlspark 版本、增加 Xms 等等配置…一直到深夜都没解决“超级树”问题。

当时并不了解 spark 运行机制。那么,问题到底出在哪里呢?

换个思路,其实但凡懂一点计算机原理、思维别太死板也能看出来, 上面的 java.lang.stackoverflow 是因为积攒了太多函数没运行。

为什么到了 fit 这里会积攒太多函数呢?因为 Spark 里面有“懒操作”一说:比如在 数据 dataDf 的 withColumn 这个函数被调用时,不一定要立即去做这件事,而是积攒着,直到 dataDf 需要被缓存、被展示、被计算得到新的值时,之前积攒的一些列操作才开始被调用。 你看我前面 foreach 了那么多 withColumn ,那自然,积攒的函数就很多,就会在 fit 时 java.lang.stackoverflow 。

我当时的解决方案是加入一个 cache()

var dataDf = ...  // load from other place
val inDoubleCols = dataDf.dtypes.filter(_._2 != "DoubleType"
).map(_._1).toArray[String]
inDoubleCols.forearch(column => {dataDf = dataDf.withColumn(column, col(column).cast(DoubleType))
})dataDf.cache()  // 把之前积攒的懒操作做一做val classifier: LightGBMClassifier = new LightGBMClassifier().setFeaturesCol("features").setLabelCol("label")
val model = classifier.fit(dataDf)

现在看来,上面的代码还是太糟糕了。

既然都用函数式编程了,就不要有 cols.forearch(c => { x = x... }) 这么愚蠢的写法。而且对每一列进行 withColumn 来转换类型是极其极其低效率的。

如果给我改,该怎么改?

var dataDf = ...  // load from other place
val doubleCols = dataDf.columns.map(f => col(f).cast(DoubleType)
)dataDf.select(doubleCols: _*)
dataDf.show(1, true)  // 把之前积攒的懒操作做一做val classifier: LightGBMClassifier = new LightGBMClassifier().setFeaturesCol("features").setLabelCol("label")
val model = classifier.fit(dataDf)

注意这里有两个经验,新手必须要越早知道越好:

  • select 进行批量类型转换,效率远高于 withColumn
  • cache 可以用,但是不能乱用;在不需要把数据传入缓存、只想清空懒操作的情况下, show 没准是更高效的选择

归根结底是当时不了解 Spark 原理。可能小厂就是这样,人手不够,需求还贼多,我连 scala 都没听说过,就接手这么庞大个 Spark 项目,也没有时间学习原理、公司里也没人会没人带我…赶鸭子上架了属于是。现在空下来了,先把原理补一补。

Spark 训练机器学习模型莫名报错(java.lang.stackoverflow)相关推荐

  1. java 报错 定位,问题定位分享(2)spark任务一定几率报错java.lang.NoSuchFieldError: HIVE_MOVE_FILES_THREAD_COUNT...

    用yarn cluster方式提交spark任务时,有时会报错,报错几率是40%,报错如下: 18/03/15 21:50:36 116 ERROR ApplicationMaster91: User ...

  2. Spark读取文件,报错java.lang.ArrayIndexOutOfBoundsException

    背景: 在 Spark 解析文件的时候,忽然报错 java.lang.ArrayIndexOutOfBoundsException.排查问题,也没发现有任何的异常.最后发现文件中,有一行数据的最后一个 ...

  3. DRP问题集结(一)-Tomcat无法启动,报错java.lang.NoClassDefFoundError: org/apache/juli/logging/LogFactory...

    问题一:  Tomcat无法启动,报错java.lang.NoClassDefFoundError: org/apache/juli/logging/LogFactory 问题二:[Error]Jav ...

  4. WildFly 报错 java.lang.NoClassDefFoundError

    在eclipse上WildFly部署项目后,启动一直报错java.lang.NoClassDefFoundError,功夫不负有心人,终于解决. 解决方案 查了网上很多资料,有说环境变量配置不对的,有 ...

  5. 首次使用eclipes运行项目报错“Java.lang.ClassNotFoundException”

    首次使用eclipes运行项目报错"Java.lang.ClassNotFoundException" 运行项目时提示: 解决方法: 1.点击菜单-Project-Build Au ...

  6. 解决Tomcat下IntelliJ IDEA报错java.lang.NoClassDefFoundError: javax/servlet/ServletContextListener

    解决Tomcat下IntelliJ IDEA报错java.lang.NoClassDefFoundError: javax/servlet/ServletContextListener   笔者在做代 ...

  7. Spring Boot单元测试报错java.lang.IllegalStateException: Could not load TestContextBootstrapper [null]

    一:运行test类方法时候报错 报错 java.lang.IllegalStateException: Could not load TestContextBootstrapper [null]. S ...

  8. Hive报错java.lang.NoClassDefFoundError: org/codehaus/jackson/JsonFactory

    一 问题 Hive报错java.lang.NoClassDefFoundError:org/codehaus/jackson/JsonFactory 二 原因 Hadoop版本是0.20.2.$HAD ...

  9. SpringBoot+MyBatis启动报错java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal

    2019独角兽企业重金招聘Python工程师标准>>> 如题,在启动SpringBoot时报SpringBoot+MyBatis启动报错java.lang.NoClassDefFou ...

最新文章

  1. linux gstack pstack 进程运行堆栈查看工具
  2. 使用c++进行Windows编程中各种操作文件的方法 【转】
  3. 从运维的角度理解Iaas、Paas、Saas云计算
  4. MySQL 5.6 my.cnf 参数说明(转)
  5. table表格的增删查改、图片的处理、数据的导入导出
  6. 制作个性化gurb菜单背景图片
  7. php ini文件操作类,操作.ini文件的好PHP类
  8. NLP学习03--递归神经网络RNN
  9. Dart教程(一):dart安装
  10. hive编程指南电子版_2020浙江省太阳能利用及节能技术重点实验室开放基金课题申请指南...
  11. python 获得时间戳_Python 获取时间戳
  12. d3 企业图谱 仿天眼查 企查查
  13. 心理测试详解:猴子小鸟蛇包
  14. 大学四年,我做过哪些兼职
  15. *p++、*(p++)、(*p)++、*++p、++*p的区别
  16. 给 FreeBSD 12.1 安装 GNOME3 图形界面
  17. 损失函数focal loss深度理解与简单实现
  18. ChatGPT的各项超能力从哪儿来?万字拆解追溯技术路线图来了!
  19. 只看活动结案报告?营销活动效果你还能做的更好
  20. android怎么链接汽车,3如何将Android与汽车音频连接起来

热门文章

  1. 函数专题:sum、row_number、count、rank\dense_rank over
  2. 【Oracle】ORA-06510: PL/SQL: 用户定义的异常错误未得到处理
  3. Mysql解决死锁的问题,防止阻塞
  4. Java异常与异常处理简单使用
  5. 【火炉炼AI】深度学习008-Keras解决多分类问题
  6. DB2添加数据时主键、唯一键冲突的解决方法
  7. 解决IE浏览器URL乱码的问题
  8. VS 2005部署应用程序提示“应用程序无法正常启动( 0x0150002)” 解决方案
  9. 解决Ajax异步请求中传数组参数,后台无法接收问题
  10. eureka依赖导入失败以及eureka中没有@EnableEurekaServer异常