简介:
MLLib提供了一系列基本数据类型以支持底层的机器学习算法。 主要的数据类型包括标注点Labeled Point)、本地向量(Local Vector)、本地矩阵、分布式矩阵等。单机模式存储的本地向量与矩阵,以及基于一个或多个RDD的分布式矩阵。其中,本地向量与本地矩阵作为公共接口提供简单数据模型,底层的线性代数操作由Breeze库和jblas库提供。标注点类型用来表示监督学习(Supervised Learning)中的一个训练样本。
1.本地向量(Local Vector)
本地向量存储在单机上,其拥有整形,从0开始的索引值以及浮点型的元素值。 MLib提供两种类型的本地向量,稠密向量DenseVector 和稀疏向量SparseVector。 稠密向量使用一个双精度浮点型数组来表示其中每一维元素,而稀疏向量则是基于一个整型索引数组和一个双精度浮点型的值数组。
所有本地向量都以spark.mllib.linalg.Vectors为基类,DenseVector和SparseVector分别是它的两个实现类,故推荐使用Vectors工具类下定义的工厂方法来创建本地向量,请看如下实例(假设在Pyspark中运行,下同):
from pyspark.mllib.linalg import Vectors
// 创建一个稠密本地向量
>>> Vectors.dense(2.0, 0.0, 8.0)
DenseVector([2.0, 0.0, 8.0])
// 创建一个稀疏本地向量
// 方法第二个参数数组指定了Non-zero entries, as a dictionary, list of tuples, or two sorted lists containing indices and values
>>> Vectors.sparse(4, {1: 1.0, 3: 5.5})
SparseVector(4, {1: 1.0, 3: 5.5})
>>> Vectors.sparse(4, [(1, 1.0), (3, 5.5)])
SparseVector(4, {1: 1.0, 3: 5.5})
>>> Vectors.sparse(4, [1, 3], [1.0, 5.5])
SparseVector(4, {1: 1.0, 3: 5.5})
2.标注点(Labeled Point)
标注点LabeledPoint是一种带有标签(Label/Response)的本地向量,它可以是稠密或者是稀疏的。 在MLlib中,标注点在监督学习算法中被使用。由于标签是用双精度浮点型来存储的,故标注点类型在回归(Regression)和分类(Classification)问题上均可使用。 标注点的实现类是pyspark.mllib.regression.LabeledPoint,请注意它与前面介绍的本地向量不同,并不位于linalg包下,标注点的创建如下所示:
>>> from pyspark.mllib.linalg import Vectors
>>> from pyspark.mllib.regression import LabeledPoint
>>> LabeledPoint(1.0,Vectors.dense(4.0,0.0,8.0))
LabeledPoint(1.0, [4.0,0.0,8.0])
>>> LabeledPoint(1.0,Vectors.sparse(3,[0,2],[4.0,8.0]))
LabeledPoint(1.0, (3,[0,2],[4.0,8.0]))
在实际的机器学习问题中,稀疏向量数据是非常常见的,MLlib提供了读取LIBSVM格式数据的支持,该格式被广泛用于LIBSVM、LIBLINEAR等机器学习库。在该格式下,每一个带标注的样本点由以下格式表示: label index1:value1 index2:value2 index3:value3 …
其中label是该样本点的标签值,一系列index:value对则代表了该样本向量中所有非零元素的索引和元素值。这里需要特别注意的是,index是以1开始并递增的。MLlib在Pyspark.mllib.util.MLUtils工具类中提供了读取LIBSVM格式的方法loadLibSVMFile,其使用非常方便。
>>> import pyspark.mllib.util.MLUtils
// 用loadLibSVMFile方法读入LIBSVM格式数据
// sample_libsvm_data.txt为spark自带的一个示例,在以下地址可以找到:
// $SPARK_HOME$/data/mllib/sample_libsvm_data.txt
>>> examples = MLUtils.loadLibSVMFile(sc, "/data/mllib/sample_libsvm_data.txt")
//返回的是组织成RDD的一系列LabeledPoint
examples: org.apache.spark.rdd.RDD[org.apache.spark.mllib.regression.LabeledPoint] = MapPartitionsRDD[6] at map at MLUtils.scala:108
3.本地矩阵(Local Matrix)
本地矩阵具有整型的行,列索引值和双精度浮点型的元素值,它存储在单机上, MLlib支持稠密矩阵DenseMatrix和稀疏矩阵Sparse Matrix两种本地矩阵,稠密矩阵将所有元素的值存储在一个列优先(Column-major)的双精度型数组中,而洗漱矩阵则将非零元素以列优先的CSC(Compressed Sparse Column)模式进行存储。
本地矩阵的基类是org.apache.spark.mllib.linalg.Matrix,DenseMatrix和SparseMatrix均是它的实现类,和本地向量类似,MLlib也为本地矩阵提供了相应的工具类Matrices,调用工厂方法即可创建实例:
scala>import org.apache.spark.mllib.linalg.{Matrix, Matrices}
2. import org.apache.spark.mllib.linalg.{Matrix, Matrices}
3. // 创建一个3行2列的稠密矩阵[ [1.0,2.0], [3.0,4.0], [5.0,6.0] ]
4. // 请注意,这里的数组参数是列先序的!
5. scala> val dm: Matrix = Matrices.dense(3, 2, Array(1.0, 3.0, 5.0, 2.0, 4.0, 6.0))
6. dm: org.apache.spark.mllib.linalg.Matrix =
7. 1.0 2.0
8. 3.0 4.0
9. 5.0 6.0
这里可以看出列优先的排列方式,即按照列的方式从数组中提取元素。也可以创建稀疏矩阵:
// 创建一个3行2列的稀疏矩阵[ [9.0,0.0], [0.0,8.0], [0.0,6.0]]
2. // 第一个数组参数表示列指针,即每一列元素的开始索引值
3. // 第二个数组参数表示行索引,即对应的元素是属于哪一行
4. // 第三个数组即是按列先序排列的所有非零元素,通过列指针和行索引即可判断每个元素所在的位置
5. scala> val sm: Matrix = Matrices.sparse(3, 2, Array(0, 1, 3), Array(0, 2, 1), Array(9, 6, 8))
6. sm: org.apache.spark.mllib.linalg.Matrix =
7. 3 x 2 CSCMatrix
8. (0,0) 9.0
9. (2,1) 6.0
10. (1,1) 8.0
这里,创建一个3行2列的稀疏矩阵[ [9.0,0.0], [0.0,8.0], [0.0,6.0]]。Matrices.sparse的参数中,3表示行数,2表示列数。第1个数组参数表示列指针,即每一列元素的开始索引值, 第二个数组参数表示行索引,即对应的元素是属于哪一行;第三个数组即是按列先序排列的所有非零元素,通过列指针和行索引即可判断每个元素所在的位置。比如取每个数组的第2个元素为2,1,6,表示第2列第1行的元素值是6.0。
分布式矩阵(Distributed matrix)
存储Double类型数据,底层分布式地存储一个或多个RDD,行列号使用Long型
分布式矩阵存储的关键,是采用正确的数据格式。将一个分布式矩阵转换为另一种不同格式的分布式矩阵,可能引发全局shuffle操作,开销很大. 四种分布式矩阵实现
- RowMatrix
- IndexedRowMatrix
- CoordinateMatrix
- BlockMatrix
行矩阵(Rowmatrix)
面向行,底层是一个以本地向量为数据项的RDD.每行都是本地向量,long型为行号,所以会收到类型范围限制。每一行就是一个具有相同格式的向量数据,且每一行的向量内容都可以单独取出来进行操作。要注意的是,此种矩阵不能按照行号访问。(我也不知道为什么这样)
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矩阵的不同之处在于,你可以通过索引值来访问每一行。其他的,没啥区别。
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)
底层实现是使用一个RDD存储的数据线,每个数据项是一个元组(i: Long, j: Long, value: Double) 只适用于,维度很大,矩阵很稀疏的情况
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()
---------------------
块矩阵(BlockMatrix)
底层实现是MatrixBlocks的RDD,这个MatrixBlock是一个元祖((Int, Int), Matrix)
import org.apache.spark.mllib.linalg.distributed.{BlockMatrix, CoordinateMatrix, MatrixEntry}
val entries: RDD[MatrixEntry] = ... // an RDD of (i, j, v) matrix entries
// Create a CoordinateMatrix from an RDD[MatrixEntry].
val coordMat: CoordinateMatrix = new CoordinateMatrix(entries)
// Transform the CoordinateMatrix to a BlockMatrix
val matA: BlockMatrix = coordMat.toBlockMatrix().cache()
// Validate whether the BlockMatrix is set up properly. Throws an Exception when it is not valid.
// Nothing happens if it is valid.
matA.validate()
// Calculate A^T A.
val ata = matA.transpose.multiply(matA)
---------------------
参考: https://www.jianshu.com/p/c6f15063d521