Spark 2.3中SparkNLP与MLlib联合Pipeline执行fit报错求助
解决SparkNLP与MLlib联合Pipeline的fit报错问题
这个报错太典型了,本质就是SparkNLP的输出类型和MLlib组件的输入类型不兼容——你把SparkNLP生成的Annotation数组直接传给了MLlib的Estimator,但MLlib组件只认字符串、数组这类原始数据类型,根本看不懂Annotation结构体。
问题根源拆解
报错里的ArrayType(StructType(...))就是SparkNLP的Annotation类型数组,比如分词器、词性标注器这类组件输出的都是这种格式。而MLlib的TF-IDF、逻辑回归这些组件,期望的输入是字符串或者字符串数组,自然会抛出类型不匹配的错误。
快速解决方案:用Finisher做类型转换
SparkNLP专门提供了Finisher组件,用来把Annotation数组里的核心内容(也就是result字段的文本值)提取出来,转换成MLlib能识别的格式。给你举个修正后的Pipeline示例:
import com.johnsnowlabs.nlp.base._ import com.johnsnowlabs.nlp.annotators._ import org.apache.spark.ml.feature._ import org.apache.spark.ml.Pipeline // 1. 先把原始字符串转成SparkNLP能处理的Document Annotation val documentAssembler = new DocumentAssembler() .setInputCol("your_text_column") .setOutputCol("document") // 2. 比如做分词,输出Token类型的Annotation数组 val tokenizer = new Tokenizer() .setInputCols(Array("document")) .setOutputCol("token") // 3. 关键步骤:用Finisher提取Token里的文本内容,转成字符串数组 val finisher = new Finisher() .setInputCols(Array("token")) // 接收前一步的Annotation数组 .setOutputCols(Array("tokenized_text")) // 输出MLlib能处理的字符串数组 .setOutputAsArray(true) // 确保输出是数组格式 // 4. 接下来就可以接MLlib的组件了,比如TF-IDF val hashingTF = new HashingTF() .setInputCol("tokenized_text") .setOutputCol("raw_features") val idf = new IDF() .setInputCol("raw_features") .setOutputCol("final_features") // 5. 重新构建Pipeline val pipeline = new Pipeline() .setStages(Array(documentAssembler, tokenizer, finisher, hashingTF, idf)) // 现在再执行fit就不会报错了 val pipelineModel = pipeline.fit(descfeature)
通用排查思路
- 先梳理你的Pipeline组件顺序,找到哪一步把Annotation数组传给了MLlib组件——就是这一步之前需要加转换。
- 如果用的是其他SparkNLP Annotator(比如NER、情感分析),同样用
Finisher提取对应的result字段就行,只需要调整inputCols为对应Annotator的输出列。 - 永远记住:SparkNLP的Annotator输出是Annotation结构体,必须转换为原始类型才能和MLlib组件配合使用。
内容的提问来源于stack exchange,提问作者Hussain Asghar
相关产品推荐
相关产品推荐

