给定一个数据集,数据分析师一般会先观察一下数据集的基本情况,称之为汇总统计或者概要性统计。一般的概要性统计用于概括一系列观测值,包括位置或集中趋势(比如算术平均值、中位数、众数和四分位均值),展型(比如四分位间距、绝对偏差和绝对距离偏差、各阶矩等),统计离差,分布的形状,依赖性等。除此之外,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. linux--配置开发环境 --Nginx篇

    安装: 安装好了话,我们的nginx的目录在:  /etc/nginx 启动: sudo service nginx start 然后访问我们的页面就可以看到了我们的界面 然后我们配置我们的域名: 我 ...

  2. php用户量剧增导致cpu100%解决办法

    在php扩展里边开启opcache扩展,此扩展是解析php的缓存机制,每次解析都要消耗cpu,所以有大量的fpm进程去占用cpu,开启此扩展之后cpu就瞬间下来了,只解析第一次,往后的都使用缓存.很好 ...

  3. [Inno Setup] 开机自启动

    [icons] Name: "{userstartup}\My Program"; Filename: "{app}\MyProg.exe"; Tasks:St ...

  4. GDI+ 绘制砂岩含量图版

    图版是在工作中经常会使用到的工具,它能够大大提高我们日常工作效率.地质图版在地质工作中具有举足轻重的作用,不仅可以轻松判断岩性,也可以依据经验图版直接得到结果,十分方便. 本程序目的绘制出一个地质常用 ...

  5. Libra白皮书解读

    文章目录 Libra简介 Libra区块链 Libra货币和存储 Libra协会 Libra简介 Libra是facebook发起的一个区块链项目,其使命是建立一套简单的.无国界的货币和为数十亿人服务 ...

  6. Oracle把表记录恢复到指定时间节点

    可以执行以下命令alter table 表名 enable row movement; --开启表行移动flashback table 表名 to timestamp to_timestamp('20 ...

  7. poj_2393 Yogurt factory 贪心

    Yogurt factory Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16669   Accepted: 8176 D ...

  8. predixy源码学习

    Predixy是一个代理,代理本质上就是用来转发请求的.其主要功能就是接收客户端的请求,然后把客户端请求转发给redis服务端,在redis服务端处理完消息请求后,接收它的响应,并把这个响应返回给客户 ...

  9. Android APK 重签名

    对APK 进行在线 加固后,Apk体积一般会变大,而且Apk会无法直接安装,因为缺少了你的签名.是的,你需要对这个Apk进行重签名. 如何重签名 重签名的方法,一般来说,有两种,第一种是用JDK自带的 ...

  10. 在html中使用vue组件

    最近在维护公司的项目,当我拿到项目时,发现他用了vue. 但是~~仅仅是引用vue.js文件,整体的架构还是html那种,没有用webpack! 当时觉得~哇~原来还可以这样! 然后了解了业务逻辑和代 ...