寒假学习16——Spark—Mlib
1. 构建训练数据集。
train.csv
id,text,label
0L,"a b c d e spark",1.0
1L,"b d",0.0
2L,"spark f g h",1.0
3L,"hadoop mr",0.0
import org.apache.spark.sql.SparkSession
import org.apache.spark.ml.classification.LogisticRegression
import org.apache.spark.ml.Pipeline
import org.apache.spark.ml.PredictionModel
import org.apache.spark.ml.linalg.Vector
import org.apache.spark.ml.feature._
import org.apache.spark.sql.Row
object Test {
def main(args: Array[String]): Unit = {
val spark = SparkSession
.builder()
.appName("wc")
.master("local")
.getOrCreate()
val train_data = spark.createDataFrame(Seq(
(0L, "a b c d e spark", 1.0),
(1L, "b d", 0.0),
(2L, "spark f g h", 1.0),
(3L, "hadoop mr", 0.0)
)).toDF("id", "text", "label")
train_data.show(4)
// 或从csv文件读取
val trainDataPath = "/Users/zz/Desktop/train.csv"
val train_data = spark.read
.option("inferSchema", "true") // 推断数据类型
.option("delimiter",",") // 可设置分隔符,默认,
.option("nullValue", "?") // 设置空值
.option("header", true) // 表示有表头,若没有则为false
.csv(trainDataPath)
train_data.printSchema()
train_data.show(false)
spark.stop()
}
}
输出:
2. 定义各个PipelineStage
val tokenizer = new Tokenizer()
.setInputCol("text")
.setOutputCol("words")
val hashingTF = new HashingTF()
.setNumFeatures(1000)
.setInputCol(tokenizer.getOutputCol)
.setOutputCol("features")
val lr = new LogisticRegression()
.setMaxIter(10)
.setRegParam(0.01)
3. 创建Pipeline
val pipeline = new Pipeline()
.setStages(Array(tokenizer, hashingTF, lr))
val model = pipeline.fit(train_data)
4. 构建测试数据
test.csv
id,text
4L,"spark i j k"
5L,"l m n"
6L,"spark a"
7L,"apache hadoop"
val testDataPath = "/Users/zenmen/Desktop/test.csv"
val test_data = spark.read
.option("inferSchema", "true") // 推断数据类型
.option("delimiter",",") // 可设置分隔符,默认,
.option("nullValue", "?") // 设置空值
.option("header", true) // 表示有表头,若没有则为false
.csv(testDataPath)
5. 数据预测
model.transform(test_data)
.select("id", "text", "probability", "prediction")
.collect()
.foreach{
case Row(id:String, text:String, prob:Vector, prediction:Double)
=> println(s"($id,$text) --> prob=$prob, prediction=$prediction")
}
3. 特征抽取、转化和选择
3.1 特征抽取TF-IDF
TF-IDF “词频-逆向文件概率” 是一种在文本挖掘中广泛使用的特征向量化方法,它可以体现一个文档中词语在语料库中的重要度。t:词语、d:文档、D:语料库。词频TF(t,d)是词语t在文档d中出现的次数。文件频率DF(t,D)是包含词语的文档的个数。
TF-IDF就是在数值化文档信息,衡量词语能提供多少信息以区分文档。
TF-IDF 度量值表示如下:
在Spark ML库中,TF-IDF1被分成两部分
1. TF(+hashing)
HashingTF 是一个Transformer,接收词条的集合,然后把这些集合转化成固定长度的特征向量,该算法在哈希的同时会统计各个词条的词频。
2. IDF
是一个Estimator,在一个数据集上,调用其fit(),产生一个IDFModel,该模型接收HashingTF产生的特征向量,然后计算每一个词在文档中出现的频次。IDF会减少那些在语料库中出现频率较高的词的权重。
过程描述:
1. 使用分解器Tokenizer把句子划分为单个词语;
2. 对每一个句子(词袋),使用HashingTF将句子转换为特征向量;
3.使用IDF重新调整特征向量,这种转换通常可以提高使用文本特征的性能。
1. 语料准备
train.csv 每一个句子代表一个文档
label,sentence
0,"I heard about Spark and I love Spark"
0,"I wish Java could use case classes"
1,"Logistic regression models are neat"
2. 用tokenizer对句子进行分词
import org.apache.spark.ml.feature.HashingTF
import org.apache.spark.ml.feature.IDF
import org.apache.spark.ml.feature.Tokenizer
val spark = SparkSession.builder().master("local").getOrCreate()
import spark.implicits._
val tokenizer = new Tokenizer()
.setInputCol("sentence")
.setOutputCol("words")
val wordsData = tokenizer.transform(train_data)
wordsData.show(false)
3. 生成特征向量
设置分桶数为2000
val hashingTF = new HashingTF()
.setNumFeatures(2000)
.setInputCol("words")
.setOutputCol("rawFeatures")
val featurizedData = hashingTF.transform(wordsData)
featurizedData.select("rawFeatures").show(false)
4. 使用IDF对单纯的词频特征向量进行修正,使其更能体现不同词汇对文本的区别能力。
val idf = new IDF()
.setInputCol("rawFeatures")
.setOutputCol("features")
val idfModel = idf.fit(featurizedData)
5. 数据预测
得到每一个单词对应的TF-IDF度量值
val rescaledData = idfModel.transform(featurizedData)
rescaledData.select("features", "label")
.take(3)
.foreach(println)
[(2000,[240,333,1105,1329,1357,1777],[0.6931471805599453,0.6931471805599453,1.3862943611198906,0.5753641449035617,0.6931471805599453,0.6931471805599453]),0]
[(2000,[213,342,489,495,1329,1809,1967],[0.6931471805599453,0.6931471805599453,0.6931471805599453,0.6931471805599453,0.28768207245178085,0.6931471805599453,0.6931471805599453]),0]
[(2000,[286,695,1138,1193,1604],[0.6931471805599453,0.6931471805599453,0.6931471805599453,0.6931471805599453,0.6931471805599453]),1]
3.2 特征抽取 Word2Vec
是一种词嵌入(Word Embedding)方法,可以计算每个单词在其给定语料库环境下的分布式词向量。其中,词向量表示可以在一定程度上刻画每个单词的语义,如果语义相近,那么它们的词向量在向量空间中也相互接近。
Word2vec是一个Estimator,采用一系列代表文档的词语来训练word2vecmodel,该模型将每个词语映射到一个固定大小的向量,word2vecmodel使用文档中每个词语的平均数来将文档转换为向量,然后这个向量可以作为预测的特征,来计算文档相似度等。
一个实例:一组文档,其中一个词语序列代表一个文档,对于每一个文档,我们将其转换为一个特征向量。
1. 创建语料
val seq = Seq(
"I heard about Spark and I love Spark".split(" "),
"I wish Java could use case classes".split(" "),
"Logistic regression models are neat".split(" ")
)
val documentDF = spark.createDataFrame(seq.map(Tuple1.apply))
.toDF("text")
2. 创建Word2Vec,设置特征向量维度为3
val word2Vec = new Word2Vec()
.setInputCol("text")
.setOutputCol("result")
.setVectorSize(3)
.setMinCount(0)
3. 模型训练及预测
生成Word2VecModel,并进行特征向量转换
val model = word2Vec.fit(documentDF)
val result = model.transform(documentDF)
result.select("result").take(3).foreach(println)
3.3 特征抽取:CountVectorizer
旨在通过计数来将一个文档转换为向量,当不存在先验字典时,CountVectorizer作为Estimator提取词汇进行训练并生成一个CountVectorizerModel用于存储相应的词汇向量空间。
该模型产生文档关于词语的稀疏表示,其表示可以传递给其他算法,例如LDA;在CountVectorizerModel的训练过程中,CountVectorizer将根据语料库中的词频排序从高到低进行选择,词汇表的最大含量由vocabsize超参数来指定;超参数minDF,则指定词汇表中词语至少要在多个不同文档中出现。
1. 创造语料库,每行看作一个文档
val seq = Seq(
(0, Array("a", "b", "c")),
(1, Array("a", "b", "b", "c", "a"))
)
val df = spark.createDataFrame(seq)
.toDF("id", "words")
2. 训练一个CountVectorizerModel,设定词汇表中的词至少要在2个文档中出现过,以过滤那些偶然出现的词汇。
val model = new CountVectorizer()
.setInputCol("words")
.setOutputCol("features")
.setVocabSize(3)
.setMinDF(2)
.fit(df)
// 获得模型的词汇表
model.vocabulary.foreach(println)
// b a c
4. 模型预测,得到文档的向量化表示
model.transform(df).show(false)
5. 使用先验词汇表构建模型
和其他Transformer不同,CountVectorizerModel可以通过制定一个先验词汇表来直接生成。
val vocabulary_arr = Array("a", "b", "c")
val cvm = new CountVectorizerModel(vocabulary_arr)
.setInputCol("words")
.setOutputCol("features")
cvm.transform(df).select("features").show(false)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
2023-02-13 开学考试