给定一个数据集,数据分析师一般会先观察一下数据集的基本情况,称之为汇总统计或者概要性统计。一般的概要性统计用于概括一系列观测值,包括位置或集中趋势(比如算术平均值、中位数、众数和四分位均值),展型(比如四分位间距、绝对偏差和绝对距离偏差、各阶矩等),统计离差,分布的形状,依赖性等。除此之外,spark.mllib库也提供了一些其他的基本的统计分析工具,包括相关性、分层抽样、假设检验,随机数生成等。

一、概括统计 summary statistics

我们通过统计学中提供的函数colStats为RDD [Vector]提供列摘要统计信息。我们可以获得每一列的最大值,最小值,均值、方差、总数。

我们用UCI 提供的莺尾花的数据来举例。 数据下载地址:http://archive.ics.uci.edu/ml/machine-learning-databases/iris/。我们将鸢尾花的四个属性,即萼片长度,萼片宽度,花瓣长度和花瓣宽度存储在observations中,类型为RDD[Vector]。

import org.apache.spark.SparkConf;

import org.apache.spark.api.java.JavaSparkContext;

import org.apache.spark.api.java.JavaRDD;

import org.apache.spark.mllib.linalg.Vector;

import org.apache.spark.mllib.linalg.Vectors;

import  org.apache.spark.mllib.stat.MultivariateStatisticalSummary;

import org.apache.spark.mllib.stat.Statistics;

SparkConf conf = new  SparkConf().setAppName("colStatsTest").setMaster("local");

JavaSparkContext  sc = new  JavaSparkContext(conf);

JavaRDD<String> source =  sc.textFile("data/iris.data"); // 读取数据

JavaRDD<Vector> observations = source.map(line  -> {

String[] parts = line.split(",");

return  Vectors.dense(Double.valueOf(parts[0]),  Double.valueOf(parts[1]),

Double.valueOf(parts[2]),  Double.valueOf(parts[3]));//将RDD<String>转化为RDD<Vector>

});

MultivariateStatisticalSummary summary =  Statistics.colStats(observations.rdd());   //计算列摘要统计信息。

System.out.println(summary.count()); //总数(long)

System.out.println(summary.mean());  //  包含每列平均值的密集向量(vector)

System.out.println(summary.variance());   // 列方差(vector)

System.out.println(summary.max());   // 最大值(vector)

System.out.println(summary.min());   // 最小值(vector)

System.out.println(summary.normL1());   //每列的L1范数(vector)

System.out.println(summary.normL2());   //每列的L2范数(vector)

System.out.println(summary.numNonzeros());  //  每列中的非零数(vector)


二、相关性

计算两个数据系列之间的相关性是统计学中的常见操作。 在spark.mllib中,我们提供了计算多个系列之间成对相关性的灵活性。 支持的相关方法目前是Pearson和Spearman的相关性。

相关系数是用以反映变量之间相关关系密切程度的统计指标。简单的来说就是相关系数绝对值越大(值越接近1或者-1),当取值为0表示不相关,取值为(0~-1]表示负相关,取值为(0, 1]表示正相关。

2.1、Pearson相关系数

Pearson相关系数表达的是两个数值变量的线性相关性, 它一般适用于正态分布。其取值范围是[-1, 1], 当取值为0表示不相关,取值为[-1~0)表示负相关,取值为(0, 1]表示正相关。

 
Pearson相关系数

2.2、Spearman相关系数

Spearman相关系数也用来表达两个变量的相关性,但是它没有Pearson相关系数对变量的分布要求那么严格,另外Spearman相关系数可以更好地用于测度变量的排序关系。其计算公式为:

 
Spearman相关系数

统计提供了计算序列之间相关性的方法。 根据输入类型,两个JavaDoubleRDD或JavaRDD <Vector>,输出将分别为Double或相关矩阵。

JavaDoubleRDD seriesX =  source.mapToDouble(x->Double.parseDouble(x.split(",")[0]));

JavaDoubleRDD seriesY =  source.mapToDouble(x->Double.parseDouble(x.split(",")[1]));  //必须具有与seriesX相同数量的分区和基数

Double correlation =  Statistics.corr(seriesX.srdd(), seriesY.srdd(),  "pearson");//使用Pearson方法计算相关性。 为Spearman的方法输入“spearman”。如果未指定方法,默认情况下将使用Pearson的方法。

System.out.println("Correlation is: " +  correlation);

/**控制台输出结果:

----------------------------------------------------

Correlation is: -0.10936924995062468

-----------------------------------------------------

**/

说明数据集的前两列,即花萼长度和花萼宽度具有微小的负相关性。

JavaRDD<Vector> data = source.map(line -> {

String[] parts = line.split(",");

return  Vectors.dense(Double.valueOf(parts[0]),

Double.valueOf(parts[1]));//将RDD<String>转化为RDD<Vector>

}); //请注意,每个Vector都是一行而不是一列

Matrix correlMatrix =  Statistics.corr(data.rdd(), "pearson");

System.out.println(correlMatrix.toString());

/**控制台输出结果:

-----------------------------------------------------

**1.0                   -0.10936924995062468

**-0.10936924995062468  1.0

-------------------------------------------------------

**/


三、分层抽样 Stratified sampling

与spark.mllib中的其他统计函数不同,可以对RDD的键值对执行分层抽样方法sampleByKey和sampleByKeyExact。 对于分层抽样,可以将键视为标签,将值视为特定属性。 例如,密钥可以是人或女人,或文档ID,并且相应的值可以是人口中的人的年龄列表或文档中的单词列表。 sampleByKey方法将翻转硬币以决定是否对样本进行采样,因此需要对数据进行一次传递,并提供预期的样本大小。 sampleByKeyExact比sampleByKey中使用的每层简单随机抽样需要更多的资源,但是会提供99.99%置信度的精确抽样大小。

3.1、sampleByKey 方法

sampleByKeyExact()允许用户准确地采样⌈fk⋅nk⌉∀k∈K项,其中fk是密钥k的期望分数,nk是密钥k的键 - 值对的数量,K是密钥集。 无需更换的采样需要在RDD上额外通过一次以确保样本大小,而更换采样则需要两次额外的通过。

import org.apache.spark.SparkConf;

import org.apache.spark.api.java.JavaSparkContext;

import org.apache.spark.api.java.JavaRDD;

import org.apache.spark.api.java.JavaPairRDD;

import org.spark_project.guava.collect.ImmutableMap;

import scala.Tuple2;

List<Tuple2<String, String>> list =  Arrays.asList(

new Tuple2<>("female","Lily"),

new Tuple2<>("female","Lucy"),

new Tuple2<>("female","Emily"),

new Tuple2<>("female","Kate"),

new Tuple2<>("female","Alice"),

new Tuple2<>("male","Tom"),

new Tuple2<>("male","Roy"),

new Tuple2<>("male","David"),

new Tuple2<>("male","Frank"),

new Tuple2<>("male","Jack"));//创建了一组数据,分成 “female” 和  “male” 两类

JavaPairRDD<String, String> data =  sc.parallelizePairs(list);

ImmutableMap<String, Double> fractions =  new ImmutableMap.Builder<String,Double>()

.put("female",0.6)

.put("male",0.4)

.build();  //从每个键Map <K,Double>中指定所需的精确分数

这里,设置采取60%的female和40%的male,因为数据中female和male各有5个样本,所以理想中的抽样结果应该是有3个female和2个male。接下来用sampleByKey进行抽样:

JavaPairRDD<String, String> approxSample =  data.sampleByKey(false, fractions,1);  //从每个层获取大致样本

approxSample.foreach(x->{

System.out.println(x);   //打印approxSample分层取样的结果;

});

/** *控制台输出结果:

-----------------------

(female,Lily)

(female,Lucy)

(female,Emily)

(female,Kate)

(male,Roy)

(male,Frank)

--------------------

**/

从上面可以看到,本应该抽取3个female和2个male,但结果抽取了5个female和1个male,结果并不够准确,不过在样本数量足够大且要求一定效率的情况下,用sampleByKey进行抽样还是可行的。

3.2、sampleByKeyExact 方法

sampleByKey 和 sampleByKeyExact 的区别在于 sampleByKey 每次都通过给定的概率以一种类似于掷硬币的方式来决定这个观察值是否被放入样本,因此一遍就可以过滤完所有数据,最后得到一个近似大小的样本,但往往不够准确。而 sampleByKeyExtra 会对全量数据做采样计算。对于每个类别,其都会产生 (fk⋅nk)个样本,其中fk是键为k的样本类别采样的比例;nk是键k所拥有的样本数。 sampleByKeyExtra 采样的结果会更准确,有99.99%的置信度,但耗费的计算资源也更多。

JavaPairRDD<String, String> exactSample =  data.sampleByKeyExact(false, fractions,1);

exactSample.foreach(x->{

System.out.println(x);//打印exactSample分层取样的结果;});

/***控制台输出结果:

--------------------

(female,Lily)

(female,Emily)

(female,Kate)

(male,Roy)

(male,Frank)

--------------------

**/

从实验结果可以看出,所得结果和预想一致,但当样本数量比较大时,可能会耗时较久。


四、假设检验 hypothesis testing

假设检验是统计学中一种强有力的工具,用于确定结果是否具有统计显着性,无论该结果是否偶然发生。 spark.mllib目前支持Pearson的卡方(χ2)测试,以确保拟合和独立性。 不同的输入类型决定了是做拟合度检验还是独立性检验。拟合度检验要求输入为Vector, 独立性检验要求输入是Matrix。

import org.apache.spark.SparkConf;

import org.apache.spark.api.java.JavaRDD;

import org.apache.spark.api.java.JavaSparkContext;

import org.apache.spark.mllib.linalg.Matrices;

import org.apache.spark.mllib.linalg.Matrix;

import org.apache.spark.mllib.linalg.Vector;

import org.apache.spark.mllib.linalg.Vectors;

import org.apache.spark.mllib.stat.Statistics;

import org.apache.spark.mllib.stat.test.ChiSqTestResult;

JavaRDD<Vector> vectors1 = source.map(x->{

String[] splits = x.split(",");

return  Vectors.dense(Double.parseDouble(splits[0]),

Double.parseDouble(splits[1]),

Double.parseDouble(splits[2]),

Double.parseDouble(splits[3]));

});

Vector v1 = vectors1.first();//获取  iris数据集中的第1条记录 ,类型为Vector

Vector v2 = vectors1.take(2).get(1);//获取 iris数据集中的第2条记录 ,类型为Vector

4.1、适合度检验 Goodness fo fit

ChiSqTestResult goodnessOfFitTestResult =  Statistics.chiSqTest(v1);

System.out.println("goodnessOfFitTestResult:"+goodnessOfFitTestResult);

/***控制台输出结果:

------------------------------------------------------------------------------------------------------------------------

goodnessOfFitTestResult:Chi squared test summary:

method: pearson

degrees of freedom = 3

statistic = 5.588235294117647

pValue = 0.1334553914430291

No presumption against null hypothesis: observed follows the same distribution as  expected..

-----------------------------------------------------------------------------------------------------------------------------

**/

可以看到P值,自由度,检验统计量,所使用的方法,以及零假设等信息。我们先简单介绍下每个输出的意义:

method: 方法。这里采用pearson方法。

statistic: 检验统计量。简单来说就是用来决定是否可以拒绝原假设的证据。检验统计量的值是利用样本数据计算得到的,它代表了样本中的信息。检验统计量的绝对值越大,拒绝原假设的理由越充分,反之,不拒绝原假设的理由越充分。

degrees of freedom:自由度。表示可自由变动的样本观测值的数目,

pValue:统计学根据显著性检验方法所得到的P 值。一般以P < 0.05 为显著, P<0.01 为非常显著,其含义是样本间的差异由抽样误差所致的概率小于0.05 或0.01。

一般来说,假设检验主要看P值就够了。在本例中pValue =0.133,说明两组的差别无显著意义。通过V1的观测值[5.1, 3.5, 1.4, 0.2],无法拒绝其服从于期望分配(这里默认是均匀分配)的假设。

4.2、独立性检验 Indenpendence

卡方独立性检验是用来检验两个属性间是否独立。其中一个属性做为行,另外一个做为列,通过貌似相关的关系考察其是否真实存在相关性。比如天气温变化和肺炎发病率。

Matrix mat = Matrices.dense(2, 2, new  double[]{v1.apply(0), v1.apply(1),v2.apply(0),  v2.apply(1)});

System.out.println("mat:"+mat);

/***

控制台输出结果:

---------------------------

mat:5.1  4.9  3.5  3.0

----------------------------

**/

同样的,键值对也可以进行独立性检验,这里我们取iris的数据组成键值对:

JavaRDD<LabeledPoint> LabeledPoints =  source.map(x->{

String[] splits = x.split(",");

Double label = 0.0;

if(splits[4].equals("Iris-setosa"))  {

label = 0.0;

}else  if(splits[4].equals("Iris-versicolor")) {

label = 1.0;

}else {

label = 2.0;

}

return  new  LabeledPoint(label,Vectors.dense(Double.parseDouble(splits[0]),

Double.parseDouble(splits[1]),

Double.parseDouble(splits[2]),

Double.parseDouble(splits[3])));

});

ChiSqTestResult[] c2 =  Statistics.chiSqTest(LabeledPoints);

for (ChiSqTestResult chiSqTestResult :  c2) {

System.out.println("c2:"+chiSqTestResult);}

/***控制台输出结果:

-----------------------------------------------------------------------------------------------------------------------------------------------------

c2:Chi squared test summary:

method: pearson

degrees of freedom = 68

statistic = 156.26666666666665

pValue = 6.6659873176888595E-9

Very strong presumption against null hypothesis: the occurrence of the outcomes is  statistically independent..

c2:Chi squared test summary:

method: pearson

degrees of freedom = 44

statistic = 88.36446886446883

pValue = 8.303947787857702E-5

Very strong presumption against null hypothesis: the occurrence of the outcomes is  statistically independent..

c2:Chi squared test summary:

method: pearson

degrees of freedom = 84

statistic = 271.79999999999995

pValue = 0.0

Very strong presumption against null hypothesis: the occurrence of the outcomes is  statistically independent..

c2:Chi squared test summary:

method: pearson

degrees of freedom = 42statistic = 271.75

pValue = 0.0

Very strong presumption against null hypothesis: the occurrence of the outcomes is  statistically independent..

---------------------------------------------------------------------------------------------------------------------------------------------------

**/

这里实际上是把特征数据中的每一列都与标签进行独立性检验。可以看出,P值都非常小,说明可以拒绝“某列与标签列无关”的假设。也就是说,可以认为每一列的数据都与最后的标签有相关性。


五、随机数生成 random data generation

RandomRDDs 是一个工具集,用来生成含有随机数的RDD,可以按各种给定的分布模式生成数据集,Random RDDs包下现支持正态分布、泊松分布和均匀分布三种分布方式。RandomRDDs提供随机double RDDS或vector RDDS。

import org.apache.spark.SparkConf;

import org.apache.spark.api.java.JavaDoubleRDD;

import org.apache.spark.api.java.JavaRDD;

import  org.apache.spark.api.java.JavaSparkContext;

import org.apache.spark.mllib.random.RandomRDDs;

JavaDoubleRDD u = RandomRDDs.normalJavaRDD(sc,  1000000L, 10);  //生成1000000个服从正态分配N(0,1)的RDD[Double],并且分布在 10 个分区中:

JavaDoubleRDD v = u.mapToDouble(x->1.0+2.0*x);    //把生成的随机数转化成N(1,4) 正态分布:


六、核密度估计 Kernel density estimation

Spark ML 提供了一个工具类 KernelDensity 用于核密度估算,核密度估算的意思是根据已知的样本估计未知的密度,属於非参数检验方法之一。核密度估计的原理是。观察某一事物的已知分布,如果某一个数在观察中出现了,可认为这个数的概率密度很大,和这个数比较近的数的概率密度也会比较大,而那些离这个数远的数的概率密度会比较小。Spark1.6.2版本支持高斯核(Gaussian kernel)。

import org.apache.spark.SparkConf;

import org.apache.spark.api.java.JavaRDD;

import  org.apache.spark.api.java.JavaSparkContext;

import  org.apache.spark.mllib.stat.KernelDensity;

JavaRDD<Double> d = source.map(t ->  Double.parseDouble(t.split(",")[0]));   //用样本数据构建核函数,这里用假设检验中得到的iris的第一个属性的数据作为样本数据进行估计:

KernelDensity kd = new  KernelDensity().setBandwidth(3.0).setSample(d);  //其中setBandwidth表示高斯核的宽度,为一个平滑参数,可以看做是高斯核的标准差。

double[] densities = kd.estimate(new double[]  {-1.0, 2.0, 5.0, 5.8});

System.out.println(Arrays.toString(densities));

/***

控制台输出结果:

------------------------------------------------------------------------------------------------------------------------------------

[0.011372003554433527, 0.05992591135719891, 0.12365409462424529,  0.12816280708978112]

-------------------------------------------------------------------------------------------------------------------------------------

**/

spark机器学习从0到1基本的统计工具之(三)的更多相关文章

  1. spark机器学习从0到1介绍入门之(一)

      一.什么是机器学习 机器学习(Machine Learning, ML)是一门多领域交叉学科,涉及概率论.统计学.逼近论.凸分析.算法复杂度理论等多门学科.专门研究计算机怎样模拟或实现人类的学习行 ...

  2. spark机器学习从0到1特征提取 TF-IDF(十二)

        一.概念 “词频-逆向文件频率”(TF-IDF)是一种在文本挖掘中广泛使用的特征向量化方法,它可以体现一个文档中词语在语料库中的重要程度. 词语由t表示,文档由d表示,语料库由D表示.词频TF ...

  3. spark机器学习从0到1特征变换-标签和索引的转化(十六)

      一.原理 在机器学习处理过程中,为了方便相关算法的实现,经常需要把标签数据(一般是字符串)转化成整数索引,或是在计算结束后将整数索引还原为相应的标签. Spark ML 包中提供了几个相关的转换器 ...

  4. spark机器学习从0到1特征选择-卡方选择器(十五)

      一.公式 卡方检验的基本公式,也就是χ2的计算公式,即观察值和理论值之间的偏差   卡方检验公式 其中:A 为观察值,E为理论值,k为观察值的个数,最后一个式子实际上就是具体计算的方法了 n 为总 ...

  5. spark机器学习从0到1机器学习工作流 (十一)

        一.概念 一个典型的机器学习过程从数据收集开始,要经历多个步骤,才能得到需要的输出.这非常类似于流水线式工作,即通常会包含源数据ETL(抽取.转化.加载),数据预处理,指标提取,模型训练与交叉 ...

  6. spark机器学习从0到1奇异值分解-SVD (七)

      降维(Dimensionality Reduction) 是机器学习中的一种重要的特征处理手段,它可以减少计算过程中考虑到的随机变量(即特征)的个数,其被广泛应用于各种机器学习问题中,用于消除噪声 ...

  7. spark机器学习从0到1决策树(六)

      一.概念 决策树及其集合是分类和回归的机器学习任务的流行方法. 决策树被广泛使用,因为它们易于解释,处理分类特征,扩展到多类分类设置,不需要特征缩放,并且能够捕获非线性和特征交互. 诸如随机森林和 ...

  8. spark机器学习从0到1基本数据类型之(二)

        MLlib支持存储在单个机器上的局部向量和矩阵,以及由一个或多个RDD支持的分布式矩阵. 局部向量和局部矩阵是用作公共接口的简单数据模型. 底层线性代数操作由Breeze提供. 在监督学习中使 ...

  9. spark机器学习从0到1特征抽取–Word2Vec(十四)

      一.概念 Word2vec是一个Estimator,它采用一系列代表文档的词语来训练word2vecmodel.该模型将每个词语映射到一个固定大小的向量.word2vecmodel使用文档中每个词 ...

随机推荐

  1. python正则表达式详解之Match类及其方法

    1.Match对象简介 match对象通常是由正则表达式对象的match 方法,search 方法等经过匹配之后而产生.可以直接当做bool值使用,如果匹配则相当于True, 如果不匹配,则返回Non ...

  2. tp5--路由的使用方法(深入)

    懒得写注释,直接上代码 配置文件Route: <?php use think\Route; //tp5路由测试 //动态注册 //Route::rule('路由表达式','路由地址','请求类型 ...

  3. 2019-2020-1 20199329《Linux内核原理与分析》第一周作业

    Linux学习随笔 Linux 是一个操作系统,我们的 Linux 主要是系统调用和内核那两层. UNIX前身是Multics,但 UNIX 的商业版本非常昂贵,于是Linus Torvalds(Li ...

  4. Linux C语言 检测文件是否存在

    头文件 unistd.h ) { // file exists } else { // file doesn't exist } You can also use R_OK, W_OK, and X_ ...

  5. SpringBoot 集成Swagger2自动生成文档和导出成静态文件

    目录 1. 简介 2. 集成Swagger2 2.1 导入Swagger库 2.2 配置Swagger基本信息 2.3 使用Swagger注解 2.4 文档效果图 3. 常用注解介绍 4. Swagg ...

  6. 【JAVA基础】06 面向对象

    1. 面向对象思想概述 面向过程思想概述 第一步 第二步 面向对象思想概述 找对象(第一步,第二步) 举例 买煎饼果子 洗衣服 面向对象思想特点 是一种更符合我们思想习惯的思想 可以将复杂的事情简单化 ...

  7. Linux 软链接和硬链接

    系统链接文件 文件有文件名和数据,在Linux上被分成两个部分:用户数据(user data)与元数据(metadata) 用户数据:文件数据块(data block),数据块是记录文件真实内容的地方 ...

  8. CSS开发技巧(二):表格合并边框后的单元格宽度计算

    前言: 分离边框模型和合并边框模型是表格的两种模型,它通过以下属性确定: border-collapse:separate(默认值) | collapse | inherit 当采用分离边框模型时,表 ...

  9. 搭建Springboot+mybatis+redis+druid

    2019独角兽企业重金招聘Python工程师标准>>> 准备工作 JDK:1.8 使用技术:SpringBoot.Dubbo.Mybatis.Druid 开发工具:Intelj ID ...

  10. POJ 1845-Sumdiv(厉害了这个题)

    Description Consider two natural numbers A and B. Let S be the sum of all natural divisors of A^B. D ...