目录
- 本地向量(local vector)
- 标记点(Labeled point)
- 本地矩阵(Local matrix)
- 分布式矩阵(Distributed matrix)
- 行矩阵(RowMatrix)
- 标签行矩阵(IndexedRowMatrix)
- 坐标矩阵(CoordinateMatrix)
- 块矩阵(BlockMatrix)
本地向量(local vector)
本地向量(Local Vector)存储在单台机器上,索引采用0开始的整型表示,值采用Double类型的值表示。Spark MLlib中支持两种类型的矩阵,分别是密度向量(Dense Vector)和稀疏向量(Spasre Vector),密度向量会存储所有的值包括零值,而稀疏向量存储的是索引位置及值,不存储零值,在数据量比较大时,稀疏向量才能体现它的优势和价值。下面给出其应用示例:
import org.apache.spark.mllib.linalg.{Vector, Vectors}
// 密度矩阵,零值也存储
val dv: Vector = Vectors.dense(1.0, 0.0, 3.0)
// 创建稀疏矩阵,指定元素的个数、索引及非零值,数组方式
val sv1: Vector = Vectors.sparse(3, Array(0, 2), Array(1.0, 3.0))
// 创建稀疏矩阵,指定元素的个数、索引及非零值,采用序列方式
val sv2: Vector = Vectors.sparse(3, Seq((0, 1.0), (2, 3.0)))
分析:一个稠密矩阵是double类型的数组;而稠密矩阵的形式是(size ,Array1,Array2)size是矩阵的大小。
平行矩阵Array1和Array2中Array1是标记,而Array2是对应的数值,当然也可以用seq((index,value),(index,value),....)的形式
带类标签的特征向量(Labeled point)
Labeled point是Spark MLlib中最重要的数据结构之一,它在无监督学习算法中使用十分广泛,它也是一种本地向量,只不过它提供了类的标签,对于二元分类,它的标签数据为0和1,而对于多类分类,它的标签数据为0,1,2,…。它同本地向量一样,同时具有Sparse和Dense两种实现方式,例如:
Labeled point由case类LabeledPoint表示。
有关API的详细信息,请参阅LabeledPoint Scala文档。
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.regression.LabeledPoint
// LabeledPoint第一个参数是类标签数据,第二参数是对应的特征数据
// 下面给出的是其密度向量实现方式
val pos = LabeledPoint(1.0, Vectors.dense(1.0, 0.0, 3.0))
// LabeledPoint的稀疏向量实现方式
val neg = LabeledPoint(0.0, Vectors.sparse(3, Array(0, 2), Array(1.0, 3.0)))
稀疏数据(Sparse data)
LabeledPoint的稀疏向量实现方式在实际中应用最为广泛,这是因为某一特征的维度可能达到上千,而这其中又存在大量对后期训练无益的零值特征信息,如果对所有的零值特征都进行存储的话,会浪费大量的存储空间,因此实际中常常使用稀疏的实现方式,使用的是LIBSVM格式:label index1:value1 index2:value2 …进行特征标签及特征的存储与读取。
MLUtils.loadLibSVMFile读取以LIBSVM格式存储的训练示例。
有关API的详细信息,请参阅MLUtils Scala文档。
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.util.MLUtils
import org.apache.spark.rdd.RDD
val examples: RDD[LabeledPoint] = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")
本地矩阵(Local matrix)
本地向量是由从0开始的整数下标和Double类型的数值组成。它有稠密向量(dense vector)和稀疏向量(sparse vertor)两种。在列的主要顺序中,它的非零输入值存储在压缩的稀疏列(CSC)格式中。
例如,下面的密集矩阵:
在一维数组[1.0、3.0、5.0、2.0、4.0、6.0]中,对应的矩阵大小(3、2)。
本地矩阵的基类是Matrix,提供了两种实现 DenseMatrix和SparseMatrix. 推荐使用工厂方法实现的Matrices来创建本地矩阵.
import org.apache.spark.mllib.linalg.{Matrix, Matrices}
// Create a dense matrix ((1.0, 2.0), (3.0, 4.0), (5.0, 6.0))
val dm: Matrix = Matrices.dense(3, 2, Array(1.0, 3.0, 5.0, 2.0, 4.0, 6.0))
// Create a sparse matrix ((9.0, 0.0), (0.0, 8.0), (0.0, 6.0))
val sm: Matrix = Matrices.sparse(3, 2, Array(0, 1, 3), Array(0, 2, 1), Array(9, 6, 8))
分布式矩阵(Distributed matrix)
分布式矩阵有Long类型的行列数据和Double类型值,存储在一个或多个RDDs中。
1. 行矩阵(RowMatrix)
行矩阵是一个没有行索引的,以行为导向(row-oriented )的分布式矩阵,它的行只支持RDD格式,每一行都是一个本地向量。由于每一行都由一个局部向量表示,所以列的数量是由整数范围所限制的,但是在实际操作中应该要小得多。
可以通过RDD[Vector]实例来创建一个RowMatrix行矩阵。
import org.apache.spark.mllib.linalg.Vector
import org.apache.spark.mllib.linalg.distributed.RowMatrix
val rows: RDD[Vector] = ... // an RDD of local vectors
// Create a RowMatrix from an RDD[Vector].
val mat: RowMatrix = new RowMatrix(rows)
// Get its size.
val m = mat.numRows()
val n = mat.numCols()
// QR decomposition
val qrResult = mat.tallSkinnyQR(true)
标签行矩阵(IndexedRowMatrix)
IndexedRowMatrix与RowMatrix类似,但具有行索引,它支持有索引行的RDD。因此,每一行数据都由索引(Long类型)和一个本地向量表示。可以通过RDD[IndexedRow]实例来创建一个IndexedRowMatrix矩阵。IndexedRow是一个包装器(Long, Vector)。通过删除行索引,可以将一个IndexedRowMatrix矩阵转换为RowMatrix矩阵。
import org.apache.spark.mllib.linalg.distributed.{IndexedRow, IndexedRowMatrix, RowMatrix}
val rows: RDD[IndexedRow] = ... // an RDD of indexed rows
// Create an IndexedRowMatrix from an RDD[IndexedRow].
val mat: IndexedRowMatrix = new IndexedRowMatrix(rows)
// Get its size.
val m = mat.numRows()
val n = mat.numCols()
// Drop its row indices.
val rowMat: RowMatrix = mat.toRowMatrix()
坐标矩阵(CoordinateMatrix)
CoordinateMatrix是一个分布式矩阵,每行数据格式为三元组(i: Long, j: Long, value: Double), i表示行索引,j表示列索引,value表示数值。只有当矩阵的两个维度都很大且矩阵非常稀疏时,才应该使用坐标矩阵。可以通过RDD[MatrixEntry]实例来创建一个CoordinateMatrix。MatrixEntry包装类型(Long, Long, Double),CoordinateMatrix矩阵通过调用toIndexedRowMatrix()API可以转换为IndexedRowMatrix 。
import org.apache.spark.mllib.linalg.distributed.{CoordinateMatrix, MatrixEntry}
val entries: RDD[MatrixEntry] = ... // an RDD of matrix entries
// Create a CoordinateMatrix from an RDD[MatrixEntry].
val mat: CoordinateMatrix = new CoordinateMatrix(entries)
// Get its size.
val m = mat.numRows()
val n = mat.numCols()
// Convert it to an IndexRowMatrix whose rows are sparse vectors.
val indexedRowMatrix = mat.toIndexedRowMatrix()