【导读】近日,多伦多数据科学家Susan Li发表一篇博文,讲解利用PySpark处理文本多分类问题的详情。我们知道,Apache Spark在处理实时数据方面的能力非常出色,目前也在工业界广泛使用。本文通过使用Spark Machine Learning Library和PySpark来解决一个文本多分类问题,内容包括:数据提取、Model Pipeline、训练/测试数据集划分、模型训练和评价等,具体细节可以参考下面全文。

Multi-Class Text Classification with PySpark

Apache Spark受到越来越多的关注,主要是因为它处理实时数据的能力。每天都有大量的数据需要被处理,如何实时地分析这些数据变得极其重要。另外,Apache Spark可以再不采样的情况下快速处理大量的数据。许多工业界的专家提供了理由: why you should use Spark for Machine Learning?[1]

现在我们来用Spark Machine Learning Library[2]和PySpark来解决一个文本多分类问题。

如果你想看一个scikit-learn版本的实现,可以读上一篇文章: previous article[3]。

数据



我们的任务,是将旧金山犯罪记录(San Francisco Crime Description)分类到33个类目中。数据可以从Kaggle中下载:

https://www.kaggle.com/c/sf-crime/data。

给定一个犯罪描述,我们想知道它属于33类犯罪中的哪一类。分类器假设每个犯罪一定属于且仅属于33类中的一类。这是一个多分类的问题。

输入:犯罪描述。例如:“ STOLEN AUTOMOBILE”

输出:类别。例如:VEHICLE THEFT

为了解决这个问题,我们在Spark的有监督学习算法中用了一些特征提取技术。

数据提取



利用Spark的csv库直接载入CSV格式的数据:

from pyspark.sql import SQLContext
from pyspark import SparkContext
sc =SparkContext()
sqlContext = SQLContext(sc)
data = sqlContext.read.format('com.databricks.spark.csv').options(header='true',
inferschema='true').load('train.csv')

除去一些不要的列,并展示前五行:

drop_list = ['Dates', 'DayOfWeek', 'PdDistrict', 'Resolution', 'Address', 'X', 'Y']
data = data.select([column for column in data.columns if column not in drop_list])
data.show(5)

利用printSchema()方法来显示数据的结构:

data.printSchema()

包含数量最多的20类犯罪:

from pyspark.sql.functions import col
data.groupBy("Category") \.count() \.orderBy(col("count").desc()) \.show()

包含犯罪数量最多的20个描述:

data.groupBy("Descript") \.count() \.orderBy(col("count").desc()) \.show()

流水线(Model Pipeline)



我们的流程和scikit-learn版本的很相似,包含3个步骤:

1. regexTokenizer:利用正则切分单词

2. stopwordsRemover:移除停用词

3. countVectors:构建词频向量

from pyspark.ml.feature import RegexTokenizer, StopWordsRemover, CountVectorizer
from pyspark.ml.classification import LogisticRegression
# regular expression tokenizer
regexTokenizer = RegexTokenizer(inputCol="Descript", outputCol="words", pattern="\\W")
# stop words
add_stopwords = ["http","https","amp","rt","t","c","the"]
stopwordsRemover = StopWordsRemover(inputCol="words", outputCol="filtered").
setStopWords(add_stopwords)
# bag of words count
countVectors = CountVectorizer(inputCol="filtered", outputCol="features",
vocabSize=10000, minDF=5)

StringIndexer



StringIndexer将一列字符串label编码为一列索引号(从0到label种类数-1),根据label出现的频率排序,最频繁出现的label的index为0。

在该例子中,label会被编码成从0到32的整数,最频繁的 label(LARCENY/THEFT) 会被编码成0。

from pyspark.ml import Pipeline
from pyspark.ml.feature import OneHotEncoder, StringIndexer, VectorAssembler
label_stringIdx = StringIndexer(inputCol = "Category", outputCol = "label")
pipeline = Pipeline(stages=[regexTokenizer, stopwordsRemover, countVectors,
label_stringIdx])
# Fit the pipeline to training documents.
pipelineFit = pipeline.fit(data)
dataset = pipelineFit.transform(data)
dataset.show(5)

训练/测试数据集划分



# set seed for reproducibility
(trainingData, testData) = dataset.randomSplit([0.7, 0.3], seed = 100)
print("Training Dataset Count: " + str(trainingData.count()))
print("Test Dataset Count: " + str(testData.count()))

训练数据量:5185

测试数据量:2104

模型训练和评价



1.以词频作为特征,利用逻辑回归进行分类

我们的模型在测试集上预测和打分,查看10个预测概率值最高的结果:

lr = LogisticRegression(maxIter=20, regParam=0.3, elasticNetParam=0)
lrModel = lr.fit(trainingData)
predictions = lrModel.transform(testData)
predictions.filter(predictions['prediction'] == 0) \.select("Descript","Category","probability","label","prediction") \.orderBy("probability", ascending=False) \.show(n = 10, truncate = 30)
from pyspark.ml.evaluation import MulticlassClassificationEvaluator
evaluator = MulticlassClassificationEvaluator(predictionCol="prediction")
evaluator.evaluate(predictions)

准确率是0.9610787444388802,非常不错!

2.以TF-IDF作为特征,利用逻辑回归进行分类

from pyspark.ml.feature import HashingTF, IDF
hashingTF = HashingTF(inputCol="filtered", outputCol="rawFeatures", numFeatures=10000)
idf = IDF(inputCol="rawFeatures", outputCol="features", minDocFreq=5)
#minDocFreq: remove sparse terms
pipeline = Pipeline(stages=[regexTokenizer, stopwordsRemover, hashingTF, idf,
label_stringIdx])
pipelineFit = pipeline.fit(data)
dataset = pipelineFit.transform(data)
(trainingData, testData) = dataset.randomSplit([0.7, 0.3], seed = 100)
lr = LogisticRegression(maxIter=20, regParam=0.3, elasticNetParam=0)
lrModel = lr.fit(trainingData)
predictions = lrModel.transform(testData)
predictions.filter(predictions['prediction'] == 0) \.select("Descript","Category","probability","label","prediction") \.orderBy("probability", ascending=False) \.show(n = 10, truncate = 30)
evaluator = MulticlassClassificationEvaluator(predictionCol="prediction")
evaluator.evaluate(predictions)

准确率是0.9616202660247297,和上面结果差不多。

3.交叉验证

用交叉验证来优化参数,这里我们针对基于词频特征的逻辑回归模型进行优化。

pipeline = Pipeline(stages=[regexTokenizer, stopwordsRemover, countVectors, label_stringIdx])
pipelineFit = pipeline.fit(data)
dataset = pipelineFit.transform(data)
(trainingData, testData) = dataset.randomSplit([0.7, 0.3], seed = 100)
lr = LogisticRegression(maxIter=20, regParam=0.3, elasticNetParam=0)
from pyspark.ml.tuning import ParamGridBuilder, CrossValidator
# Create ParamGrid for Cross Validation
paramGrid = (ParamGridBuilder().addGrid(lr.regParam, [0.1, 0.3, 0.5]) # regularization parameter.addGrid(lr.elasticNetParam, [0.0, 0.1, 0.2]) # Elastic Net Parameter (Ridge = 0)
#            .addGrid(model.maxIter, [10, 20, 50]) #Number of iterations
#            .addGrid(idf.numFeatures, [10, 100, 1000]) # Number of features.build())
# Create 5-fold CrossValidator
cv = CrossValidator(estimator=lr, \estimatorParamMaps=paramGrid, \evaluator=evaluator, \numFolds=5)
cvModel = cv.fit(trainingData)

predictions = cvModel.transform(testData)

Evaluate best model

evaluator = MulticlassClassificationEvaluator(predictionCol=“prediction”)
evaluator.evaluate(predictions)

准确率变成了0.9851796929217101,获得了提升。

4.朴素贝叶斯

from pyspark.ml.classification import NaiveBayes
nb = NaiveBayes(smoothing=1)
model = nb.fit(trainingData)
predictions = model.transform(testData)
predictions.filter(predictions[‘prediction’] == 0)
.select(“Descript”,“Category”,“probability”,“label”,“prediction”)
.orderBy(“probability”, ascending=False)
.show(n = 10, truncate = 30)
evaluator = MulticlassClassificationEvaluator(predictionCol=“prediction”)
evaluator.evaluate(predictions)

准确率:0.9625414629888848

4.随机森林

from pyspark.ml.classification import RandomForestClassifier
rf = RandomForestClassifier(labelCol=“label”,
featuresCol=“features”,
numTrees = 100,
maxDepth = 4,
maxBins = 32)

Train model with Training Data

rfModel = rf.fit(trainingData)
predictions = rfModel.transform(testData)
predictions.filter(predictions[‘prediction’] == 0)
.select(“Descript”,“Category”,“probability”,“label”,“prediction”)
.orderBy(“probability”, ascending=False)
.show(n = 10, truncate = 30)

evaluator = MulticlassClassificationEvaluator(predictionCol=“prediction”)
evaluator.evaluate(predictions)

准确率:0.6600326922344301

上面结果可以看出:随机森林是优秀的、鲁棒的通用的模型,但是对于高维稀疏数据来说,它并不是一个很好的选择。

明显,我们会选择使用了交叉验证的逻辑回归。

代码在Github上:https://github.com/susanli2016/Machine-Learning-with-Python/blob/master/SF_Crime_Text_Classification_PySpark.ipynb。

参考文献:

[1] https://www.infoworld.com/article/3031690/analytics/why-you-should-use-spark-for-machine-learning.html

[2] https://spark.apache.org/docs/1.1.0/mllib-guide.html

[3] https://towardsdatascience.com/multi-class-text-classification-with-scikit-learn-12f1e60e0a9f

原文链接:

https://towardsdatascience.com/interpretability-in-machine-learning-70c30694a05f

Python大数据处理库PySpark实战——使用PySpark处理文本多分类问题相关推荐

  1. Python大数据处理库 PySpark实战 总结四

    Python大数据处理库 PySpark实战四 ETL 实战 实验数据来源 数据加载 观察资料 选择.筛选与聚合 机器学习实战 实验数据来源 数据加载 统计描述 清洗与变形 Pipeline 逻辑回归 ...

  2. Python大数据处理,应对海量数据挑战

    Python大数据处理,应对海量数据挑战 Python的特点及在大数据处理中的优势 1 Python语言的特点 2 Python在大数据处理中所具备的优势 二.Python常用的大数据处理工具介绍 1 ...

  3. Python + 大数据 - 数仓实战之智能电商分析平台

    Python + 大数据 - 数仓实战之智能电商分析平台 1. 项目架构 2. 数据仓库维度模型设计-事实表 事实表的特征:表里没有存放实际的内容,他是一堆主键的集合,这些ID分别能对应到维度表中的一 ...

  4. Python+大数据-数仓实战之滴滴出行(一)

    Python+大数据-数仓实战之滴滴出行(一) 1. 项目架构图 1.1 数据流程处理 1.2 数仓分层 1.3 创建数据库 在Hive中创建数据库-- 创建ods库 create database ...

  5. Python+大数据-数仓实战之滴滴出行(二)

    Python+大数据-数仓实战之滴滴出行(二) 1. 数据转移 #验证sqoop是否工作 /export/server/sqoop-1.4.7/bin/sqoop list-databases \ - ...

  6. python通过Tkinter库实现的一个简单的文本编辑器源码

    下边资料是关于python通过Tkinter库实现的一个简单的文本编辑器的内容. from tkSimpleDialog import askstring from tkFileDialog impo ...

  7. Python大数据处理扩展库pySpark用法精要

    Spark是一个开源的.通用的并行计算与分布式计算框架,其活跃度在Apache基金会所有开源项目中排第三位,最大特点是基于内存计算,适合迭代计算,兼容多种应用场景,同时还兼容Hadoop生态系统中的组 ...

  8. python基础代码库-Python基础数据处理库-NumPy

    最近更新:2017-07-19 NumPy是Python做数据处理的底层库,是高性能科学计算和数据分析的基础,比如著名的Python机器学习库SKlearn就需要NumPy的支持.掌握NumPy的基础 ...

  9. Python大数据分析与挖掘实战微课版答案 Python大数据分析与挖掘实战课后答案 例题 课后作业 python题目 python题库 数据分析与挖掘题库 数据分析与挖掘项目

    (在此仅展示题目,所有数据.代码.答案.习题等点我头像,在资源中!!!) 以下关于pandas 数据预处理说法正确的是(). A. pandas没有做哑变量的函数 B. 在不导入其他厍的情况下,仅仅使 ...

最新文章

  1. Linux系统下Oracle11g r1的安装之四: 开始安装Oracle
  2. java 内部类 加载_java内部类及类加载顺序
  3. 卷积神经网络参数计算及卷积层输出尺寸计算
  4. Charles使用1
  5. mac版python安装pandas_Mac OS 安装pandas
  6. mysql8.0.20 64位安装教程_MySQL8.0.20压缩版本安装教程图文详解
  7. 使用SQL存储过程有什么好处 用视图有什么好处
  8. springboot(三)-使用JSP
  9. react-native 学习
  10. 手机电子名片html,利用JavaScript的AngularJS库制作电子名片的方法
  11. size-constrained-clustering
  12. [Qt] 使用LZMA SDK完成C++的7z格式文件压缩和解压缩
  13. 计算机中sumif函数的使用方法,WPS表格的sumif函数用法与模糊条件使用方法
  14. 举个栗子!Tableau技巧(59):学做两个集合的维恩图(文氏图)Venn diagram
  15. 虚拟直播需要哪些设备?如何搭建虚拟直播团队?
  16. <_main__.类名 object at 0x0000000002A7CEB8>
  17. python launcher下载,python launcher是什么 python的launcher用法知识点总结
  18. 【公示】关于举办“元宇宙数字人制作竞赛”的复函
  19. 概率论考研笔记(四)
  20. 2012年博客大赛优秀学生博客的奖品

热门文章

  1. 智慧城市与数字城市、智能城市的关系和区别
  2. 国内已经没有什么安全论坛值得留念了
  3. 怎么使用PluginBase进行Tekla二次开发
  4. 爬取摄图网里的 音乐和视频 摄图网模拟登陆
  5. CSS设置元素隐藏显示透明度
  6. OpenCV学习笔记11_Mask操作与图像叠加
  7. 人工智能最受欢迎的10大TED演讲
  8. 如何开发自己的股票软件202
  9. 三星13位VFD荧光屏驱动方案(最后附部分驱动代码和硬件设计链接)
  10. Drawio使用介绍(画图工具)