基于NaiveBayes的文本分类之Spark实现

本文介绍如何利用Spark实现基于朴素贝叶斯的文本分类。在Python的sklearn实现之后,通过Spark在集群环境下进行文本分类,提供了一种更高效的解决方案。

  在尝试了python下面用sklearn进行文本分类(http://blog.youkuaiyun.com/a_step_further/article/details/50189727)后,我们再来看下用spark如何实现文本分类的工作,采用的算法同样是朴素贝叶斯。

    此前,我们已经实现了hadoop集群环境下使用mapreduce进行中文分词(http://blog.youkuaiyun.com/a_step_further/article/details/50333961),那么文本分类的过程也使用集群环境操作,相对于python的单机版本实现,无疑更方便一些。

上代码:

import org.apache.spark.mllib.classification.NaiveBayes
import org.apache.spark.mllib.feature.{IDFModel, HashingTF, IDF}
import org.apache.spark.mllib.linalg.Vector
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkContext, SparkConf}

object textClassify {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("text_classify").set("spark.akka.frameSize","20")
    val sc = new SparkContext(conf)
        if(args.length != 2){
           println("Usage: textClassify <inputLoc> <idfSaveLoc> <modelSaveLoc> ")
           System.exit(-1)
        }

    val inputLoc = args(0)
    val inputData = sc.textFile(inputLoc).map(line => line.split("\t")).filter(_.length == 2).cache()
    val features = inputData.map(x => x(1).split(" ").toSeq).cache()

    val hashingTF = new HashingTF()
    val tf = hashingTF.transform(features)
    val idf: IDFModel = new IDF(minDocFreq = 2).fit(tf)
    val tfIdf = idf.transform(tf)

    val zippedData = inputData.map(x => x(0)).zip(tfIdf).map{case (label, tfIdf) =>
       LabeledPoint(label.toDouble, tfIdf)
    }.cache()

    val randomSplitData = zippedData.randomSplit(Array(0.6, 0.4), seed=10L)
    zippedData.unpersist()
    val trainData = randomSplitData(0).cache()
    val testData = randomSplitData(1)

    val model = NaiveBayes.train(trainData, lambda = 0.1)
    trainData.unpersist()

    //预测
    val predictTestData = testData.map{case x => (model.predict(x.features), x.label)}
    val totalTrueNum = predictTestData.filter(x => x._2 == 1.0).count()
    val predictTrueNum = predictTestData.filter(x => x._1 == 1.0).count()
    val predictRealTrue = predictTestData.filter(x => x._1 == x._2 && x._2 == 1.0).count()


    println("results------------------------------------------------")
    println("准确率:", 1.0*predictRealTrue/predictTrueNum)
    println("召回率:",1.0*predictRealTrue/totalTrueNum)
    println("------------------------------------------------")

    val modelSaveLoc = args(1)
    model.save(sc,modelSaveLoc)


    sc.stop()

  }


}



在使用 AWS Glue 和 Apache Spark 进行文本分类任务时,可以利用 Glue 的无服务器 ETL 能力以及 Spark 强大的分布式计算框架来完成数据预处理、特征提取和模型训练等步骤。以下是实现文本分类的基本流程: ### 数据准备与加载 首先,需要将原始文本数据存储在 AWS S3 中,这是 Glue 的标准数据源之一。使用 Glue Crawler 可以自动发现 S3 中的数据结构,并将其注册到 Glue Data Catalog 中。注册完成后,可以通过 Glue ETL 作业读取这些数据,并进行清洗和预处理。 ### 数据预处理 在 Glue ETL 作业中,可以使用 PySpark 或 Scala 编写转换逻辑。对于文本分类任务,常见的预处理步骤包括: - **文本清洗**:去除特殊字符、HTML 标签、数字等非文本内容。 - **分词**:将文本拆分为单词或短语。 - **停用词过滤**:移除常见但无实际意义的词汇。 - **词干提取或词形还原**:将词语归一化为基本形式。 ```python from pyspark.sql.functions import col, lower, regexp_replace from pyspark.ml.feature import Tokenizer, StopWordsRemover # 假设 df 是从 Glue Catalog 中读取的 DataFrame df = spark.read.format("parquet").load("s3a://your-bucket/path/to/data") # 文本清洗 cleaned_df = df.withColumn("text", regexp_replace(col("text"), "[^a-zA-Z\\s]", "")).withColumn("text", lower(col("text"))) # 分词 tokenizer = Tokenizer(inputCol="text", outputCol="words") tokenized_df = tokenizer.transform(cleaned_df) # 去除停用词 remover = StopWordsRemover(inputCol="words", outputCol="filtered_words") processed_df = remover.transform(tokenized_df) ``` ### 特征提取 预处理后的文本数据需要转换为数值向量,以便机器学习模型能够处理。常用的方法包括 TF-IDF(Term Frequency-Inverse Document Frequency)或 Word2Vec 等。 ```python from pyspark.ml.feature import HashingTF, IDF hashingTF = HashingTF(inputCol="filtered_words", outputCol="raw_features", numFeatures=10000) featurized_df = hashingTF.transform(processed_df) idf = IDF(inputCol="raw_features", outputCol="features") idf_model = idf.fit(featurized_df) final_df = idf_model.transform(featurized_df) ``` ### 模型训练与评估 在完成特征提取后,可以使用 Spark MLlib 提供的分算法(如 Logistic Regression、Random Forest、Naive Bayes 等)来训练文本分类模型。 ```python from pyspark.ml.classification import LogisticRegression from pyspark.ml.evaluation import MulticlassClassificationEvaluator from pyspark.ml.tuning import TrainValidationSplit, ParamGridBuilder # 划分训练集和测试集 train_df, test_df = final_df.randomSplit([0.8, 0.2], seed=42) # 初始化逻辑回归模型 lr = LogisticRegression(featuresCol="features", labelCol="label") # 定义参数网格 param_grid = ParamGridBuilder().addGrid(lr.regParam, [0.1, 0.01]).build() # 设置评估器 evaluator = MulticlassClassificationEvaluator(labelCol="label", predictionCol="prediction", metricName="accuracy") # 使用 TrainValidationSplit 进行超参数调优 tvs = TrainValidationSplit(estimator=lr, estimatorParamMaps=param_grid, evaluator=evaluator, trainRatio=0.8) model = tvs.fit(train_df) # 在测试集上进行预测 predictions = model.transform(test_df) # 计算准确率 accuracy = evaluator.evaluate(predictions) print(f"Test Accuracy: {accuracy}") ``` ### 部署与推理 训练完成后,可以将模型保存到 S3,并通过 AWS Lambda 或 Amazon SageMaker 部署为 API 服务,用于实时或批量推理。 ```python model.write().overwrite().save("s3a://your-bucket/path/to/model") ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值