基本数据类型
1 本地向量
本地向量:稠密向量和稀疏向量
稠密向量使用双精度浮点型数组来表示每一维的元素,稀疏向量则是基于一个整数索引数组和一个双精度浮点型的值数组。
def main(args: Array[String]): Unit = {
//创建本地稠密向量
val dv:linalg.Vector = Vectors.dense(2.0,0.0,8.0)
println(dv)
//创建本地稀疏向量 第一个参数指定size,第二个参数指定下标,第三个参数指定下标位置上的值
val svl:linalg.Vector= Vectors.sparse(3,Array(0,2),Array(2.0,8.0))
println(svl)
//使用Seq方式创建稀疏向量
val sv2:linalg.Vector = Vectors.sparse(3,Seq((0,2.0),(2,8.0)))
println(sv2)
}
输出:
标注点(Labeled Point):
标注点是一种带有标签的本地向量,通常用在监督学习算法中,它可以是稠密的或者稀疏的。由于标签是用双精度浮点型来存储的,因此标注点类型在回归和分类问题上均可使用。
//标注点 第一个参数为标注点标签
def main(args: Array[String]): Unit = {
//稠密向量标注点
val pos = LabeledPoint(1.0,Vectors.dense(0.0,2.0,8.0))
println(pos)
// 稀疏向量标注点
val pos2 = LabeledPoint(0.0,Vectors.sparse(3,Seq((0,2.0),(2,8.0))))
println(pos2)
}
输出:
本地矩阵Matrix :
本地矩阵具有整型的行、列索引值和双精度浮点型的元素值,它存储在单机上。MLlib支持稠密矩阵DenseMatrix和稀疏矩阵SparseMatrix两种本地矩阵。稠密矩阵将所有元素的值存储在一个列优先的双精度数组中,而稀疏矩阵则将非零元素以列优先的CSC模式进行存储。
稠密矩阵创建
//创建稠密矩阵
val matrix:Matrix = Matrices.dense(3,2,Array(1,2,3,4,5,6))
println(matrix)
稀疏矩阵创建
创建 ((0,1,0),(0,0,2),(0,3,0))的矩阵
val s:Matrix = Matrices.sparse(3,3,Array(0,0,2,4),Array(0,2,1,0),Array(1,3,2,0))
println(s)
Array(0,0,2,4)表示第一个0表示迭代开始,第二个0表示第一列有0个非零值,2表示第一列和第二列的非零值,4表示所有的非零值数。
Array(0,2,1,0)为矩阵中非零值的下标,Array(1,3,2,0)中的0作为非零值处理。
分布式矩阵Distributed Matrix:
RowMatrix 分布在集群上的矩阵,每行是一个本地向量
IndexedRowMatrix 与RowMatrix类似,具有long类型的列索引,每行都是一个Indexed Row类型,它是一个二元组(Long,Vector) 。
CoordinateMatrix 与IndexedRowMatrix类似,在后台,它是MatrixEntry的RDD,其中,MatrixEntry是(Long,Long,Vector)的三元组,这对于存储高维稀疏数据是有用的。
BlockMatrix 将矩阵排列为MatrixBlock类型的RDD,每个MatrixBlock是一个子矩阵,子矩阵有行和列索引以及子矩阵本身的内容,它可以通过直接从IndexedRowMatrix或CoordinateMatrix转换来创建。
机器学习流水线
Pipeline
特征提取(feature extration):是指利用已有的特征计算出一个抽象更高的特征集,也指计算得到某个特征的算法。
特征提取器:
TF-IDF(词频-逆向文件频率):它是文本挖掘领域常用的特征提取方法。给定一个语料库,TF-IDF通过词汇在语料库中出现的次数和在文档中出现的次数,来衡量每一个词汇对于文档的重要性,进而构建基于语料库的向量化表达。
词语由t表示,文档由d表示,语料库由D表示。TF(t,d)表示词语t在文档d中出现的次数。DF(t,D)表示包含词语的文档的个数。如果只是用词频来衡量重要性,很容易过度强调在文档中经常出现却没有太多实际信息的词语,如‘a’、‘of’、‘the’等。如果一个词语经常出现在语料库中,意味着它并不能很好的对文档进行区分。TF-IDF就是对文档进行数值化,从而衡量词语能提供多少信息来区分文档。
|D|表示语料库中总的文档数。公式中使用了log函数,当词出现在所有文档中时,它的IDF值变为0。DF(t,D)+1是为了避免分母为0的情况。TF-IDF度量值表示如下:
在spark.ml中,TF-IDF被分成两部分:TF和IDF。
(1)TF:HashingTF是一个转换器,在文本处理中,接收词条的集合,然后把这些集合转化成固定长度的特征向量。这个算法在哈希的同时会统计各个词条的词频。
(2)IDF:IDF是一个评估器,在一个数据集上应用它的fit()方法,产生一个IDFModel。该IDFModel接收特征向量(由hashingTF产生),然后计算每一个词在文档中出现的频次,IDF会减少那些在语料库中出现频率较高的词的权重。
CountVectorizer找出文档中同时出现的词语。
Word2Vec是将词语向量化表示,词语相近的向量表示也相近。
TF-IDF是文本挖掘中特征向量化方法
特征转换器:
Tokenizer分词器
RegixTokenizer通过正则分词
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().config("spark.testing.memory", "2147480000")
.master("local[*]").appName("dasdas").getOrCreate()
val df = spark.createDataFrame(Seq(
(0, "Hi i heard about spark"),
(1, "I wish Java could use case classes"),
(2, "Logistic regression models are neat")
)).toDF("id","sentence")
val tokenizer = new Tokenizer().setInputCol("sentence").setOutputCol("words")
val regixToken = new RegexTokenizer().setInputCol("sentence").setOutputCol("words").setPattern("\\W")
val count = udf {(words:Seq[String])=>words.length}
val tkModel = tokenizer.transform(df)
val regixModel = regixToken.transform(df)
tkModel.select("sentence","words").withColumn("tokens",count(col("words"))).show(false)
regixModel.select("sentence","words").withColumn("tokens",count(col("words"))).show(false)
}
输出:
StopWordsRemover
过滤掉停用词 像 a of the are all等为停用词
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().config("spark.testing.memory", "2147480000")
.master("local[*]").appName("StopRemove").getOrCreate()
val df = spark.createDataFrame(Seq(
(0,"I have a the people".split(" ").toSeq),
(1,"a sad dfdsfdsoi dsaoas".split(" ").toSeq),
(2, "you are not a man".split(" ").toSeq),
(3,"we all are a super man".split(" ").toSeq)
)).toDF("id","sentence")
val stopR = new StopWordsRemover().setInputCol("sentence").setOutputCol("filter")
stopR.transform(df).show(false)
}
输出:
n-gram
一个n-gram是一个包含n个tokens(如词)的序列。NGram可以将输入特征 转换为n-grams。NGram输入一系列的序列,参数n用来决定每个n-gram的词个数。输出包含一个n-grams序列,每个n-gram表示一个划定空间的连续词序列。 如果输入序列包含的词少于n,将不会有输出。 N-Gram认为语言中每个单词只与其前面长度 N-1 的上下文有关。主要分为bigram和trigram,bigram假设下一个词的出现依赖它前面的一个词,trigram假设下一个词的出现依赖它前面的两个词。在SparkML中用NGram类实现,setN(2)为bigram,setN(3)为trigram。
def main(args: Array[String]): Unit = {
// N-Gram认为语言中每个单词只与其前面长度 N-1 的上下文有关。主要分为bigram和trigram,
// bigram假设下一个词的出现依赖它前面的一个词,trigram假设下一个词的出现依赖它前面的两个词。
// 在SparkML中用NGram类实现,setN(2)为bigram,setN(3)为trigram。
val spark = SparkSession.builder().appName("sada")
.master("local[*]")
.config("spark.testing.memory", "2147480000")
.getOrCreate()
val df = spark.createDataFrame(Seq(
(0,Array("Hi","I","heard","about","Spark")),
(1,Array("I","wish","java","could","use","case","classes")),
(2,Array("Logistic","regression","models","are","neat"))
)).toDF("id","words")
val ng = new NGram().setInputCol("words").setOutputCol("ngram").setN(3)
val model = ng.transform(df)
model.show(false)
}
输出:
Binarizer
二值化
二值化是将数值特征阈值化为二进制(0/1)特征的过程。Binarizer
取共同参数inputCol
和outputCol
,以及所述threshold
二值化。大于阈值的特征值被二进制化为1.0; 等于或小于阈值的值被二值化为0.0。支持Vector和Double类型inputCol
。
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().appName("sada")
.master("local[*]")
.config("spark.testing.memory", "2147480000")
.getOrCreate()
val df = spark.createDataFrame(Array((0,0.1),(1,0.8),(2,0.2))).toDF("id","features")
val br = new Binarizer().setInputCol("features").setOutputCol("binarizer").setThreshold(0.5)
val brModel = br.transform(df)
println(br.getThreshold)
brModel.show(false)
}
输出:
PCA
PCA是一种统计过程,它使用正交变换将可能相关变量的一组观察值转换为称为主成分的线性不相关变量的一组值。PCA类使用PCA训练模型以将向量投影到低维空间。下面的示例显示了如何将5维特征向量投影到3维主成分中。
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().appName("sada")
.master("local[*]")
.config("spark.testing.memory", "2147480000")
.getOrCreate()
val data = Array(
Vectors.sparse(5,Seq((1,1.0),(3,7.0))),
Vectors.dense(2.0,0.0,3.0,4.0,5.0),
Vectors.dense(4.0,0.0,0.0,6.0,7.0)
)
val df = spark.createDataFrame(data.map(Tuple1.apply)).toDF("features")
val pca = new PCA().setInputCol("features").setOutputCol("pcaFeatures").setK(3)
val pcaModel = pca.fit(df)
val result = pcaModel.transform(df)
result.show(false)
}
输出:
PolynomialExpansion
多项式展开是将要素扩展为多项式空间的过程,该多项式空间由原始维度的n度组合制定。一个PolynomialExpansion类提供此功能。以下示例显示如何将要素扩展为3度多项式空间。
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().appName("sada")
.master("local[*]")
.config("spark.testing.memory", "2147480000")
.getOrCreate()
val data = Array(
Vectors.dense(2.0,1.0),
Vectors.dense(0.0,0.0),
Vectors.dense(3.0,-1.0)
)
val df = spark.createDataFrame(data.map(Tuple1.apply)).toDF("features")
val poly = new PolynomialExpansion().setInputCol("features").setOutputCol("polyFeatures").setDegree(3)
val polyDF = poly.transform(df)
polyDF.show(false)
}
输出:
DCT
离散余弦变换将时域长度为N的实值序列变换为频域长度为N的实值序列。DCT类提供了这一功能,实现了DCT- ii并将结果缩放
1/,从而使转换的表示矩阵是单一的。变换后的序列不发生位移(例如,变换序列的第0个元素是第0个DCT系数,而不是N/2)。
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().appName("sada")
.master("local[*]")
.config("spark.testing.memory", "2147480000")
.getOrCreate()
val data = Seq(
Vectors.dense(0.0, 1.0, -2.0, 3.0),
Vectors.dense(-1.0, 2.0, 4.0, -7.0),
Vectors.dense(14.0, -2.0, -5.0, 1.0))
val df = spark.createDataFrame(data.map(Tuple1.apply)).toDF("features")
val dct = new DCT()
.setInputCol("features")
.setOutputCol("featuresDCT")
.setInverse(false)
val dctDf = dct.transform(df)
dctDf.select("featuresDCT").show(false)
}
输出:
StringIndexer
StringIndexer
将标签的字符串列编码到标签索引列。索引是[0, numLabels)
,并且支持四个排序选项:“frequencyDesc”:按标签频率降序(最频繁标签分配0),“frequencyAsc”:按标签频率升序(最不频繁的标签分配0),“alphabetDesc”:降序字母顺序和“alphabetAsc”:升序字母顺序(默认=“frequencyDesc”)。如果用户选择保留它们,那么看不见的标签将被放在索引numLabels上。如果输入列是数字,我们将其转换为字符串并索引字符串值。当下游管道组件(例如Estimator
或 Transformer
使用此字符串索引标签)时,必须将组件的输入列设置为此字符串索引列名称。在许多情况下,您可以使用设置输入列setInputCol
。
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().appName("sada")
.master("local[*]")
.config("spark.testing.memory", "2147480000")
.getOrCreate()
val df = spark.createDataFrame(
Seq((0, "a"), (1, "b"), (2, "c"), (3, "a"), (4, "c"))
).toDF("id", "category")
val indexer = new StringIndexer()
.setInputCol("category")
.setOutputCol("categoryIndex")
val indexed = indexer.fit(df).transform(df)
indexed.show()
}
输出:
IndexToString
对称地StringIndexer
,IndexToString
将一列标签索引映射回包含原始标签作为字符串的列。一个常见的用例是从标签生成索引StringIndexer
,使用这些索引训练模型,并从预测索引列中检索原始标签IndexToString
。但是,您可以自由提供自己的标签。
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().appName("sada")
.master("local[*]")
.config("spark.testing.memory", "2147480000")
.getOrCreate()
val df = spark.createDataFrame(Seq(
(0, "a"),
(1, "b"),
(2, "c"),
(3, "a"),
(4, "a"),
(5, "c")
)).toDF("id", "category")
val indexer = new StringIndexer()
.setInputCol("category")
.setOutputCol("categoryIndex")
.fit(df)
val indexed = indexer.transform(df)
println(s"Transformed string column '${indexer.getInputCol}' " +
s"to indexed column '${indexer.getOutputCol}'")
indexed.show()
val inputColSchema = indexed.schema(indexer.getOutputCol)
println(s"StringIndexer will store labels in output column metadata: " +
s"${Attribute.fromStructField(inputColSchema).toString}\n")
val converter = new IndexToString()
.setInputCol("categoryIndex")
.setOutputCol("originalCategory")
val converted = converter.transform(indexed)
println(s"Transformed indexed column '${converter.getInputCol}' back to original string " +
s"column '${converter.getOutputCol}' using labels in metadata")
converted.select("id", "categoryIndex", "originalCategory").show()
}
输出:
特征选择器:
VectorSlicer、RFormlar、ChiSqSelector
分类和聚类算法