数据类型——基于RDD的API

  • 本地矢量
  • 标记点
  • 本地矩阵
  • 分布式矩阵
    • RowMatrix(行矩阵)
    • IndexedRowMatrix(索引行矩阵)
    • CoordinateMatrix(坐标矩阵)
    • BlockMatrix(块矩阵)

  MLlib 支持存储在单台机器上的本地向量和矩阵,以及由一个或多个 RDD 支持的分布式矩阵。本地向量和本地矩阵是用作公共接口的简单数据模型。有监督学习中使用的训练示例在MLlib中称为"标记点"。

一、本地矢量(Local Vector)

MLlib 支持两种类型的局部向量:密集和稀疏。密集向量由表示其条目值的双精度数组支持,而稀疏向量由两个并行数组支持:索引和值。例如:向量(1.0, 0.0, 3.0)

  • 稠密向量的表现形式:[1.0, 0.0, 3.0];
  • 稀疏向量的表现形式:(3,[0,2],[1.0,3.0]),其中3表示向量长度,[0,2]是数组非0向量的索引,而[1.0,3.0]是索引对应的向量值;

本地矢量都以 org.apache.spark.mllib.linalg.Vector 为基类,提供了两个实现:DenseVectorSparseVector,分别对应稠密向量和稀疏向量。

%spark
//使用Vectors工具类下定义的工厂方法来创建本地向量
import org.apache.spark.mllib.linalg.{Vector, Vectors}
//创建一个本地稠密向量
val dv:Vector = Vectors.dense(2.0,0.0,8.0)
//创建一个本地稀疏向量
val sv1:Vector = Vectors.sparse(3,Array(0,2),Array(2.0,8.0))
//另一种创建本地稀疏向量的方法,参数由长度和一个键值对组成(index,elem),每个键值对都是一个非0的向量
val sv2:Vector = Vectors.sparse(3,Seq((0,2.0),(2,8.0)))

注意:Scala会默认引入 scala.collection.immutable.Vector 这个包,所以必须要显示引org.apache.spark.mllib.linalg.Vector来使用MLlib提供的向量类型。

二、标记点(Labeled Point)

  标记点是(Label/Response)的本地向量,可以是稠密或稀疏的。在 MLlib 中,标记点用于监督学习算法。由于标签是使用双精度浮点型来存储的,因此可以在回归和分类问题中使用标记点。对于二元分类问题,标签应为(负/0)或(正/1);对于多类分类,标签应是从零开始的类索引:0,1,2 。。。

标记点的实现类是:org.apache.spark.mllib.regression.LabeledPoint

%spark
//创建一个被标记为1.0的稠密向量标记点,创建一个被标记为0的稀疏向量
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.regression.LabeledPoint
val temp1 = LabeledPoint(1.0,Vectors.dense(2.0,0.0,8.0))
val temp2 = LabeledPoint(0.0,Vectors.sparse(3,Seq((0,2.0),(2,8.0))))

在实践中,稀疏的训练数据非常普遍。MLlib 支持读取以格式存储的训练示例,这是LIBSVM 和LIBLINEAR使用的默认格式。它是一种文本格式,其中每行使用以下格式表示标记的稀疏特征向量:LIBSVM

label index1:value1 index2:value2 ...

其中 label是该样本点的标签值,一系列 index:value对则代表了该样本向量中所有非零元素的索引和元素值。这里需要特别注意的是,index是以1开始并递增的。

MLlib在org.apache.spark.mllib.util.MLUtils工具类中提供了读取LIBSVM格式的方法loadLibSVMFile,示例如下:

%spark
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.util.MLUtils
import org.apache.spark.rdd.RDD
//使用MLUtils类中的loadLibSVMFile方法读取LIBSVM格式的数据
//sample_libsvm_data.txt为spark自带的一个示例
val examples: RDD[LabeledPoint] = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")

三、本地矩阵(Local Matrix)

本地矩阵具有整数类型的行和列索引以及存储在单台计算机上的双精度浮点型值。MLlib 支持稠密矩阵(其条目值按列主序存储在单个双精度数组中)和稀疏矩阵(其非零条目值以压缩稀疏列 (CSC) 格式按列主序存储)。本地矩阵的基类是org.apache.spark.mllib.linalg.MatrixDenseMatrixSparseMatrix均是它的实现类,和本地向量类似,MLlib也为本地矩阵提供了相应的工具类Matrices,调用工厂方法即可创建实例:

%spark
import org.apache.spark.mllib.linalg.{Matrix,Matrices}
//创建一个3行2列的稠密矩阵,注意是列先序的
val dm:Matrix = Matrices.dense(3,2,Array(1.0,3.0,5.0,2.0,4.0,6.0)) 输出:
dm: org.apache.spark.mllib.linalg.Matrix =
1.0 2.0
3.0 4.0
5.0 6.0

同样创建稀疏矩阵:

// 创建一个3行2列的稀疏矩阵[ [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)) 输出:
sm: org.apache.spark.mllib.linalg.Matrix =
3 x 2 CSCMatrix
(0,0) 9.0
(2,1) 6.0
(1,1) 8.0

四、分布式矩阵(Distributed Matrix)

分布式矩阵由长整型的行列索引值和双精度浮点型的元素值组成。它可以分布式地存储在一个或多个RDD上,MLlib提供了三种分布式矩阵的存储方案:行矩阵RowMatrix,索引行矩阵IndexedRowMatrix、坐标矩阵CoordinateMatrix和分块矩阵BlockMatrix。它们都属于org.apache.spark.mllib.linalg.distributed包。

1、行矩阵(RowMatrix)

行矩阵RowMatrix是最基础的分布式矩阵类型。每行是一个本地向量,行索引无实际意义(即无法直接使用)。数据存储在一个由行组成的RDD中,其中每一行都使用一个本地向量来进行存储。由于行是通过本地向量来实现的,故列数(即行的维度)被限制在普通整型(integer)的范围内。在实际使用时,由于单机处理本地向量的存储和通信代价,行维度更是需要被控制在一个更小的范围之内。RowMatrix可通过一个RDD[Vector]的实例来创建,如下代码所示:

%spark
import org.apache.spark.rdd.RDD
import org.apache.spark.mllib.linalg.{Vector,Vectors}
import org.apache.spark.mllib.linalg.distributed.RowMatrix
//首先创建两个本地稠密向量
val dv1:Vector = Vectors.dense(1.0,2.0,3.0)
val dv2:Vector = Vectors.dense(2.0,3.0,4.0)
val rows:RDD[Vector] = sc.parallelize(Array(dv1,dv2))
//通过RDD[Vector]创建一个行矩阵
val mat:RowMatrix = new RowMatrix(rows)
//使用numRows和numCols方法分别输出行矩阵的行、列
mat.numRows()
mat.numCols()
//打印行矩阵
mat.rows.foreach(println)

在获得RowMatrix的实例后,我们可以通过其自带的computeColumnSummaryStatistics()方法获取该矩阵的一些统计摘要信息,并可以对其进行QR分解SVD分解PCA分解。 统计摘要信息的获取如下代码段所示(接上代码段):

//通过computeColumnSummaryStatistics()方法获取统计摘要
val summary = mat.computeColumnSummaryStatistics()
//根据统计信息获取行数
summary.count
//获取最大向量
summary.max
//获取方差向量
summary.variance
//平均向量
summary.mean
//L1范数向量
summary.normL1

2、索引行矩阵(IndexedRowMatrix)

索引行矩阵IndexedRowMatrixRowMatrix相似,但它的每一行都带有一个有意义的行索引值,这个索引值可以被用来识别不同行,或是进行诸如join之类的操作。其数据存储在一个由IndexedRow组成的RDD里,即每一行都是一个带长整型索引的本地向量。IndexedRowMatrix的实例可以通过RDD[IndexedRow]实例来创建。

%spark
import org.apache.spark.rdd.RDD
import org.apache.spark.mllib.linalg.{Vector,Vectors}
import org.apache.spark.mllib.linalg.distributed.{IndexedRow, IndexedRowMatrix}
//1、首先创建两个本地稠密向量
val dv1:Vector = Vectors.dense(1.0,2.0,3.0)
val dv2:Vector = Vectors.dense(2.0,3.0,4.0)
// 2、通过本地向量dv1 dv2来创建对应的IndexedRow
// 在创建时可以给定行的索引值,如这里给dv1的向量赋索引值1,dv2赋索引值2
val idxr1 = IndexedRow(1,dv1)
val idxr2 = IndexedRow(2,dv2)
//3、 通过IndexedRow创建RDD[IndexedRow]
val idxrows = sc.parallelize(Array(idxr1,idxr2))
//4、 通过RDD[IndexedRow]创建一个索引行矩阵
val idxmat: IndexedRowMatrix = new IndexedRowMatrix(idxrows)
//5、 打印输出索引行矩阵
idxmat.rows.foreach(println)

3、坐标矩阵(CoordinateMatrix)

坐标矩阵CoordinateMatrix是一个基于矩阵项构成的RDD的分布式矩阵。每一个矩阵项MatrixEntry都是一个三元组:(i: Long, j: Long, value: Double),其中i是行索引,j是列索引,value是该位置的值。坐标矩阵一般在矩阵的两个维度都很大,且矩阵非常稀疏的时候使用

CoordinateMatrix实例可通过RDD[MatrixEntry]实例来创建,其中每一个矩阵项都是一个(rowIndex, colIndex, elem)的三元组:

%spark
import org.apache.spark.mllib.linalg.distributed.{CoordinateMatrix, MatrixEntry}
//1、创建两个矩阵项,每个矩阵项由索引和值构成三元组
val ent1 = new MatrixEntry(0,1,0.5)
val ent2 = new MatrixEntry(2,2,1.8)
//2、创建RDD[MatrixEntry]
val entries : RDD[MatrixEntry] = sc.parallelize(Array(ent1,ent2))
//3、通过RDD[MatrixEntry]创建一个坐标矩阵
val coordMat: CoordinateMatrix = new CoordinateMatrix(entries)
//4、打印
coordMat.entries.foreach(println)

坐标矩阵可以通过transpose()方法对矩阵进行转置操作,并可以通过自带的toIndexedRowMatrix()方法转换成索引行矩阵IndexedRowMatrix

//5、将coordMat进行转置
val transMat: CoordinateMatrix = coordMat.transpose()
//打印输出
transMat.entries.foreach(println)
//6、将坐标矩阵转换成一个索引行矩阵
val indexedRowMatrix = transMat.toIndexedRowMatrix()
indexedRowMatrix.rows.foreach(println)

4、分块矩阵(BlockMatrix)

分块矩阵是基于矩阵块MatrixBlock构成的RDD的分布式矩阵,其中每一个矩阵块MatrixBlock都是一个元组((Int, Int), Matrix),其中(Int, Int)是块的索引,而Matrix则是在对应位置的子矩阵(sub-matrix),其尺寸由rowsPerBlockcolsPerBlock决定,默认值均为1024。分块矩阵支持和另一个分块矩阵进行加法操作和乘法操作,并提供了一个支持方法validate()来确认分块矩阵是否创建成功。

分块矩阵可由索引行矩阵IndexedRowMatrix或坐标矩阵CoordinateMatrix调用toBlockMatrix()方法来进行转换,该方法将矩阵划分成尺寸默认为1024x1024的分块,可以在调用toBlockMatrix(rowsPerBlock, colsPerBlock)方法时传入参数来调整分块的尺寸。

%spark
import org.apache.spark.rdd.RDD
import org.apache.spark.mllib.linalg.distributed.{CoordinateMatrix, MatrixEntry}
import org.apache.spark.mllib.linalg.distributed.BlockMatrix
//1、 创建8个矩阵项,每一个矩阵项都是由索引和值构成的三元组
val ent1 = new MatrixEntry(0,0,1)
val ent2 = new MatrixEntry(1,1,1)
val ent3 = new MatrixEntry(2,0,-1)
val ent4 = new MatrixEntry(2,1,2)
val ent5 = new MatrixEntry(2,2,1)
val ent6 = new MatrixEntry(3,0,1)
val ent7 = new MatrixEntry(3,1,1)
val ent8 = new MatrixEntry(3,3,1)
//2、 创建RDD[MatrixEntry]
val entries : RDD[MatrixEntry] = sc.parallelize(Array(ent1,ent2,ent3,ent4,ent5,ent6,ent7,ent8))
//3、 通过RDD[MatrixEntry]创建一个坐标矩阵
val coordMat: CoordinateMatrix = new CoordinateMatrix(entries)
//4、 将坐标矩阵转换成2x2的分块矩阵并存储,尺寸通过参数传入
val matA: BlockMatrix = coordMat.toBlockMatrix(2,2).cache()
//5、 可以用validate()方法判断是否分块成功
matA.validate()
//6、构建成功后,可通过toLocalMatrix转换成本地矩阵,并查看其分块情况
matA.toLocalMatrix 输出:
res6: org.apache.spark.mllib.linalg.Matrix =
1.0 0.0 0.0 0.0
0.0 1.0 0.0 0.0
-1.0 2.0 1.0 0.0
1.0 1.0 0.0 1.0
//查看其分块情况
matA.numColBlocks
matA.numRowBlocks
// 计算矩阵A和其转置矩阵的积矩阵
val ata = matA.transpose.multiply(matA)
//转换为本地矩阵查看
ata.toLocalMatrix

输出:
ata: org.apache.spark.mllib.linalg.distributed.BlockMatrix = org.apache.spark.mllib.linalg.distributed.BlockMatrix@37b6f828
res7: org.apache.spark.mllib.linalg.Matrix =
3.0 -1.0 -1.0 1.0
-1.0 6.0 2.0 1.0
-1.0 2.0 1.0 0.0
1.0 1.0 0.0 1.0

分块矩阵BlockMatrix将矩阵分成一系列矩阵块,底层由矩阵块构成的RDD来进行数据存储。值得指出的是,用于生成分布式矩阵的底层RDD必须是已经确定(Deterministic)的,因为矩阵的尺寸将被存储下来,所以使用未确定的RDD将会导致错误。而且,不同类型的分布式矩阵之间的转换需要进行一个全局的shuffle操作,非常耗费资源。所以,根据数据本身的性质和应用需求来选取恰当的分布式矩阵存储类型是非常重要的。

2、标记点

MLlib学习——基本数据类型的更多相关文章

  1. js学习之数据类型

    js学习之数据类型 基础类型:number string boolean null undefined 引用类型:object array function undefined值是派生自null值的( ...

  2. Go语言学习之数据类型

    ### Go语言学习之数据类型 数据类型的转换 1.Go语言不允许隐式类型转换(显示转换才可以) 2.别名和原有类型也不能进行隐式类型转换 例子: func TestImplicit(t *testi ...

  3. python学习6—数据类型之集合与字符串格式化

    python学习6—数据类型之集合与字符串格式化 1. 使用id()可以查看一个变量的内存地址: name = 'alex' id(name) 2. 进制转换 十进制转换为二进制等: a = 10 # ...

  4. MySQL学习笔记--数据类型

    一.数据类型(内容参考<SQL学习指南>)不完整 1.文本类型 文本类型 最大字节数 tinytext 255 text 65535 varchar 65536 mediumtext 16 ...

  5. C语言基础学习基本数据类型-变量的输出与输入

    变量的输出 变量如何输入输出呢?实际上,在这之前你已经使用过输出语句(printf语句)了,我们可以使用printf来执行输出. printf语句的使用方法如下: printf(格式控制字符串, 数据 ...

  6. C语言基础学习基本数据类型-变量和常量

    变量和常量 什么是变量和常量?有些数据在程序运行前就预先设定,并在运行过程中不发生变化,称之为常量:有些数据在程序运行中可能发生变化或被赋值,称之为变量. 使用变量前必须先声明一个变量.变量定义的语法 ...

  7. Redis 学习(二) —— 数据类型及操作

    Redis支持string.list.set.zset.hash等数据类型,这一篇学习redis的数据类型.命令及某些使用场景. 一.String,字符串 字符串是 Redis 最基本的数据类型.一个 ...

  8. MySQL学习4 - 数据类型一

    介绍 一.数值类型 二.浮点型 验证三种类型建表 验证三种类型的精度 三.日期类型 综合练习: 介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选 ...

  9. python学习Day7 数据类型的转换,字符编码演变历程

    一.数据类型的转换 1.1.1.字符转列表:lst1 = str.split(默认空格,也可依据指定字符分界),若无分界字符,就没法拆分,这时可以直接放进list转成列表 ----> s1 = ...

随机推荐

  1. C/C++避免头文件重复包含的方法

    C/C++避免头文件重复包含的方法 1. #ifndef 2. #pragma once 3. 混合使用 在实际的编程过程中,因为会使用多个文件,所以在文件中不可避免的要引入一些头文件,这样就可能会出 ...

  2. Layui table 学习笔记

    templet:'<div>{{createrFormat(d.accounts.name)}}</div>' function createrFormat(o){ retur ...

  3. 异常 finally

    经典面试题:  程序执行结果是100: (一):final和finally和finalize的区别

  4. php伪协议总结

    本篇总结下一些封装协议,涉及的相关协议:file://.php://filter.php://input.zip://.compress.bzip2://.compress.zlib://.data: ...

  5. 【Java常用类】BigDecimal

    BigDecimal 一般的Float类和Double类可以用来做科学计算或工程计算,但在商业计算中, 要求数字精度比较高,故用到java.math.BigDecimal类. BigDecimal类支 ...

  6. ProE许可、PTC许可、Creo许可、许可分析、分析许可

    Pro/Engineer操作软件(又简称ProE)是美国参数技术公司(PTC)旗下的CAD/CAM/CAE一体化的三维软件,Creo是美国PTC公司于2010年10月推出CAD设计软件包,creo是P ...

  7. Git命令中波浪号~与脱字符^的区别

    0.前言 波浪号~,英文名叫 tilde.脱字符^,英文名叫caret. 这两种符号常见于git reset的情景,简单的项目结构和操作一般不会涉及到两者之间的区别,似乎用哪个都可以.如果遇到比较繁杂 ...

  8. java之类的抽取与对象的创建

    Java语言之类的抽取 前言:世界由什么组成?This is a question.有人说是原子.分子,有人说是山川草木. 诚然,一千个人眼中有一千个哈姆雷特.而在程序员眼中,万物皆对象. 定义: 在 ...

  9. 基于 NFS 搭建便捷远程硬盘

    基于 NFS 搭建便捷远程硬盘 知识准备: 一.NFS服务简介 NFS 是Network File System的缩写,即网络文件系统.一种使用于分散式文件系统的协定,由Sun公司开发,于1984年向 ...

  10. 关于3G移动通信网络中用户ip的配置过程的研究(中国电信cdma2000)

    在RP口对ppp过程进行研究 PPP协商过程,如下图所示: 在建立ppp过程中pdsn需要与FAAA.HAAA交互.同时在分组数据业务进行过程中这种交互更加频繁,介绍如下,分为两种情况,简单ip,移动 ...