MLlib支持存储在单机上的局部向量和局部矩阵,也可以支持通过一个或多个RDD(可伸缩数据集)表示的分布式矩阵。局部向量和局部矩阵是用作公共接口的简单数据模型,实际上底层的线性代数运算由Breeze (机器学习和数值运算的Scala库)和 jblas (JAVA线性代数运算库)提供。在有监督机器学习中,MLlib使用标记点(labeled point)来表示单个训练语料。
局部向量存储在单机上,使用整数表示索引,索引从0开始;使用双精度浮点数(double)存储数值。MLlib支持两种类型的局部向量:密集型和稀疏型。密集向量(dense vector)使用double数组表示元素值,而稀疏向量(sparse vector)通过两个并列的数组来表示:一个表示索引,一个表示数值。例如:向量(1.0, 0.0, 3.0)使用密集型可表示为:[1.0, 0.0, 3.0], 而使用稀疏型可以表示为:(3, [0, 2], [1.0, 3.0]], 其中3是向量的长度。
在Python中,MLlib支持以下的方式表示密集向量:
array
)(NumPy是一个第三方Python库,用于科学计算)[1, 2, 3]
使用以下的方式表示稀疏向量:
SparseVector
]csc_matrix
with a single column] (SciPy是第三方Python库,用于数学、科学、工程,SciPy包含多个子库,NumPy是其中的一个)基于性能的考虑,我们建议:使用NumPy数组而不是Python链表来创建密集向量,使用MLlib中的Vectors来创建稀疏向量。
import numpy as np
import scipy.sparse as sps
from pyspark.mllib.linalg import Vectors
# Use a NumPy array as a dense vector.
dv1 = np.array([1.0, 0.0, 3.0])
# Use a Python list as a dense vector.
dv2 = [1.0, 0.0, 3.0]
# Create a SparseVector.
sv1 = Vectors.sparse(3, [0, 2], [1.0, 3.0])
# Use a single-column SciPy csc_matrix as a sparse vector.
sv2 = sps.csc_matrix((np.array([1.0, 3.0]), np.array([0, 2]), np.array([0, 2])), shape = (3, 1))
标记点是局部向量,向量可以是密集型或者稀疏型,每个向量会关联了一个标签(label)。MLlib的标记点用于有监督学习算法。我们使用double来存储标签值,这样标记点既可以用于回归又可以用于分类。在二分类中,标签要么是0要么是1;在多分类中,标签是0, 1, 2, ….
在Python中,标签点使用 LabeledPoint
表示
。
from pyspark.mllib.linalgimportSparseVector
from pyspark.mllib.regressionimportLabeledPoint
# Create a labeled point with a positive label and a dense feature vector.
pos=LabeledPoint(1.0,[1.0,0.0,3.0])
# Create a labeled point with a negative label and a sparse feature vector.
neg=LabeledPoint(0.0,SparseVector(3,[0,2],[1.0,3.0]))
稀疏数据(Sparse data)
在实践中经常用到稀疏训练数据。MLlib支持读取LIBSVM格式的训练语料数据,这个是LIBSVM
和 LIBLINEAR
中用到的默认格式(LIBSVM和LIBLINERAR是台湾林智仁教授开发的的SVM库和线性分类器)。这是一种文本格式,每行表示一个标记的稀疏特征向量,示例如下:
label index1:value1 index2:value2 ...
字符串使用空格分隔,索引从0开始,以递增的训练排列。导入系统后,特征索引自动转为从0开始索引。
MLUtils.loadLibSVMFile
可以读取LIBSVM格式的训练语料。
from pyspark.mllib.utilimportMLUtils
examples=MLUtils.loadLibSVMFile(sc,"data/mllib/sample_libsvm_data.txt")
局部矩阵[Local matrix]
局部矩阵使用整型行列索引和浮点(double)数值,存储在单机上。MLIB支持密集型矩阵,元素值按列优先以double数组的方式存储。例如,下面的矩阵:
会被存储为一维数组[1.0, 3.0, 5.0, 2.0, 4.0, 6.0]
,矩阵的大小是(3, 2)。
注:暂无Python示例。
分布式矩阵以long整型做索引,以double类型为值,以RDD的方式分布式存储。当存储非常大的分布式矩阵的时候,选择正确的存储方式非常重要。因为将分布式矩阵转换为另一种格式可能需要全局shuffle, 这个开销非常大。目前,有三种分布式矩阵已经实现。
基本类型是行矩阵(RowMatrix)。行矩阵按行分布式存储,这个时候行号没有意义。例如,特征向量集就可以表示为行矩阵,通过RDD来支撑矩阵的部分行,每行是一个局部向量。我们认为RowMatrix的列数不是特别巨大,所以单个局部向量可以方便地跟驱动程序交互,并且能够在单个节点上存储和操作。索引行矩阵(IndexedRowMatrix)跟RowMatrix类似,但是IndexedRowMatrix带有行号,从而可以标记行并且执行join操作。坐标矩阵(CoordinateMatrix)是以coordinate list (COO)(COO用于存储稀疏矩阵,以链表的形式(list)存放(rowIndex, colIndex, value)元组)格式存储的分布式矩阵,其底层支撑也是RDD。
注意:分布式矩阵底层的RDD必须是确定的,因为我们缓存了矩阵的大小(size)。通常使用不确定的RDD会导致出错。
分块矩阵(BlockMatrix)是由RDD支撑的分布式矩阵,RDD中的元素为MatrixBlock。MatrixBlock是多个((Int, Int), Matrix)组成的元组,其中(Int, Int)是分块索引, Matriax是指定索引处的子矩阵, 该矩阵的大小为rowsPerBlock
xcolsPerBlock
。BlockMatrix支持跟其他BlockMatrix做add(加)和multiply(乘)操作。BlockMatrix还有一个辅助方法validate,这个方法可以检查BlockMatrix是否设置是否恰当。
注:暂无Python示例。
行矩阵(RowMatrix)按行分布式存储,无行索引,底层支撑结构是多行数据组成的RDD,每行是一个局部向量。正因为每行是局部向量,列数受限于整数的范围,不过在实践中已经够用了。
注:暂无Python示例。
索引行矩阵(IndexedRowMatrix)跟RowMatrix类似,但是有行索引。其底层支撑结构是索引的行组成的RDD,所以每行可以通过索引(long)和局部向量表示。
注:暂无Python示例。
坐标矩阵(CoordinateMatrix
)也是由RDD做底层结构的分布式矩阵。每个RDD元素是由多个(i : long, j : long, value: Double)组成的元组,其中i是行索引,j是列索引,value是元素值。CoordinateMatrix 只应该应用于矩阵纬度高并且稀疏的情况下。
注:暂无Python示例。