MapReduce实例伪代码


针对于大数据管理与分析课程期末复习整理。大多为本人根据文字描述写的伪代码,如有不对,请指出 :->

1.词频统计
Class Mapper
	method Map(string key,string value)
		for each word w in value
			emit(w,"1");
Class Reducer
	method reduce(string key,Iterator:string values)
		int result=0;
		for each v in values
			result+=int(v);
		emit(key,result);

Spark-Scala代码:

var counts=file.flatMap(line=>line.split(" "))
				.map(word=>(word,1))  //对应mapper
				.reduceByKey(_+_)     //相同的key之间进行加法
2.单词同现矩阵算法
Class Mapper
	method Map(docid a,doc d)
		for each word w in d
			for each word u in Neighbor(w)
				emit(pair(w,u),"1");
Class Reducer
	method Reduce(pair p,Iterator:string values)
		int result=0;
		for each v in values
			result+=int(v)
		emit(p,result);
3.child-parent:父子->祖辈
Class Mapper
	method Map(string offset, string line)
		lines=line.spilt(" ");
		child=lines[0];
		parent=lines[1];
		emit(parent,"0"+child);
		emit(child,"1"+parent);
Class Reducer
	method Reduce(string key,Iterator:string values)
		List<string> grandpa=null;
		List<string> children=null;
		for each v in values
			if v[0]="0"
				children.push(v);
			if v[0]="1"
				grandpa.push(v);
		for each i in grandpa
			for each j in children
				emit(i,j);
3.文档倒排索引算法(含词频统计和Stopwords)
Class Maper
	method setup()//每个集群节点都会启动一次
		Set<string> Stop_words;
		Stop_words=read(stopwords);
	method map(docid a,doc d)
		Array F=null;
		for each word w in d
			F[w]++;
		for each word w in F
			emit(pair<w,d>,F[w]);
Class Partitioner
	method partitioner(K key,V value,int numReduceTasks)
		string w=key.toString().split(",")[0];
		super.partitioner(w,value,numReduceTasks);
Class Reducer
	method setup()
		t_prev=null;
		List<pair> P=null;
	method reduce(pair key,Iterator:int values)
		w=key.first;
		d=key.second;
		if(t_prev!=w&&t_prev!=null)
			Emit(t_prev,P);
			P.clear();
		int result=0;
		for each v in values
			result+=v;
		P.push(pair<d,result>);
		t_prev=w;
	method close()
		Emit(t_prev,P);
4.专利文献数据分析

(1)专利被引列表:

Map:--> key:cited value:citing
Reduce:--> key:cited value:citing1,citing2,...

(2)专利被引次数统计:

Map:--> key:cited value:1
Reduce:--> key:cited value=1+1+1..

(3)专利被引直方图统计:(被引次数的次数统计)

专利被引次数统计
+
Map:--> key:num=value value:1
Reduce:--> key:num value=1+1+1..

(4)结构化数据:年份或国家专利数统计

(5)每年申请美国专利的国家数统计

Map:-->key:<year,country> value:1
Partitioner:super.getPartitioner(year,value,numTask)
Reduce:-->key:year value:the num of country

(6)如何统计一个国家占全球的专利申请比例:

Map:-->key:country value:1
Reduce:-->key:country value:sum
扫描生成的文档,统计总共申请专利数据N
用该国家的数据/N

(7)如何统计一个国家的专利引用率

统计这个国家总共被引过的专利数目:
Map:-->key:<country,cited> value:1
Partitioner:super.getPartitioner(country,value,numTask)
Reduce:-->key:country value:the num of cited
再用该数据除以之前的申请专利数据
5.PageRank

P R ( p i ) = 1 − d N + d ∑ P j ∈ M ( p i ) P R ( p j ) L ( p j ) d = 0.85 PR(p_i)=\frac{1-d}{N}+d\sum_{P_j\in M(p_i)}\frac{PR(p_j)}{L(p_j)}\\ d=0.85 PR(pi)=N1d+dPjM(pi)L(pj)PR(pj)d=0.85

其中M为入边,L为出边

MapReduce

GraphBuilder:
	map:<URL,(PR_init,link_list)>  link_list:为出度边的集合
	reduce:<URL,(PR_init,link_list)>
PageRankIter:
	map:for each u in link_list:<u,PR_init/link_list.count()>
		<URL,link_list>
	reduce:<URL,<new_rank,link_list>>
Rankviewer:
	map:<rank,URL>
	重载sort,rank由大到小
	reduce:<rank,URL>

Spark

val lines=sc.textFile("..data"); //url url1,url2,...
val lines=lines.map{
	s=>val parts=s.plit("\t")(parts(0),parts(1).split(","))
}.cache()
var ranks=links.mapValues(v=>1.0)
var N=links.size
for(i<-0 until iterCnt){
	val contributions=links.join(ranks).flatMap{
		case(pageID,(links,rank))=>links.map(dest=>(dest,rank/links.size))
	}
	ranks=contribution.reduceBykey((x,y)=>x+y).mapValues(v=>((1-damping)*N+damping*v))
}
ranks.sortBy(_._2,false)
	 .mapValues(v=>v.formatted("%.10f").toString())
	 .coalesce(1,true)
	 .saveAsTextFile("..")
6.k-means

MapReduce:

Class Mapper
	method setup()
		kPoints=read(全局的聚类中心信息)
	method map(offset,Point p)
		int clusterID=closestPoint(p,kPoints);
		Emit(clusterID,pair<p,1>)
Class Combiner
    method reduce(int key,Iterator:pair values)
        Point p'=null;
        int n=0;
        for each v in values
            p'+=v.first;
            n+=v.second;
        p'/=n;
        Emit(key,pair<p',n>)
Class Reducer
	method reduce(int key,Iterator:pair values)
		Point p'=null;
		int n=0;
		for each v in values
			p'+=v.first*v.second;
			n+=v.second;
		p'/=n;
		Emit(key,<p',n>); //p'是新的聚类中心

hadoop运行k-means,job的最大数量

如何保证维护的数据信息被所有作业获取:全局文件

不足:

(1)每次迭代操作都需要作为独立作业重新进行处理,磁盘IO开销大

(2)需要一个额外的MapReduceJob用来检测迭代终止条件

Spark:

1.从HDFS上读取数据转换为RDD,将RDD中的每个数据转换为向量形成新的RDD存入缓存,随机抽样K个向量作为初始聚类中心

2.计算RDD中每个向量p到聚类中心的距离,并且划分到最近的聚类中心,生成<ClusterID,(p,1)>为元素的新的RDD

3.聚合新生成的RDD中key值相同的<ClusterID,(p,1)>键值对,将相同的ClusterID下的所有向量相加并求取向量个数n,形成新的RDD。

4.对生成的RDD,计算新的聚类中心,生成<ClusterID,kp>的新的RDD

5.判断是否可以终止

优点:

(1)内存 (2)一个Job (3)任务结束直接退出,不需要另外的job来检测

读取数据和初始化聚类中心
val lines=sc.textfile("..data")
val data=lines.map(s=>s.split(" ").map(_.toDouble))
			  .cache()
val kPoints=data.takeSample(false,K,seed)
				.map(s=>spark.util.Vector(s))
while(未到达最大迭代次数或者未收敛){
    划分数据给聚类中心
    val closest=data.map(p=>(closestPoint(spark.util.Vector(p),kPoints)))
    聚合形成新的聚类中心
    val pointStats=closest.reduceByKey{
        case((x1,y1),(x2,y2))=>(x1+x2,y1+y2) //同一key下 value<p,1>的操作
    }
    计算生成新的聚类中心
    val newPoints=pointStats.map{ 
        pair=>(pair._1,pair._2._1/pair._2._2)
    }.collectAsMap()  //pair._1:key, pair._2._1:points, pair._2._2:n
}
7.分类算法:KNN
map:ts(trid,A',y')
	求最相似的K个TR,计算y'
	emit(trid,y')
reduce:直接输出(trid,y')
8.分类算法:朴素贝叶斯算法

对于未知样本X,计算P(X|Yi)P(Yi),选择概率最大的Yi

统计Yi和xj在Yi中出现的频度

第一部分统计信息:

map:tr(trid,A,y)
	 emit(y,1)
	 for each x in A
	 	emit(<y,xni,xvi>,1) //xni:属性名 xvi:属性值
reduce:(key,value_list)
		emit(key,sum)

第二部分分类:

Class Mapper
	method setup()
		读取训练数据集得到的频度数据
		FY={(Yi,FYi)}
		FxY={(<Yi,xnj,xvj>,FxYij)}
	method map(key,ts(tsid,A))
		for each Yi in FY
			FXYi=1.0
			for each xj in ts.A
				FXYi*=(FxYij/FYi)
			if FXYi*FYi>maxF
				MaxF=FXYi*FYi
				idx=i
		emit(tsid,FY[idx].Yi)
9.分类算法:SVM短文本多分类

训练:对每一个类做2-class分类器

map:emit(classID,<1/0,特征向量>)
reduce:训练分类器

预测:用all分类器对样本打分,取最高分

map:emit(SampleID,<lableID,score>)
reduce:emit(sampleID,maxscore)
10.频繁项集挖掘算法(apriori,son,Pson)

apriori:从k=1开始,scanDB,去除sup=1的,组合成为k+1…

son:局部频繁–>全局频繁

Pson:并行化son

第一阶段:

map:emit(<F,1>):F是local frequent
reduce:emit(<F,sum>)

第二阶段:

map:emit(<C,v>):C是global condidate v是count
reduce:emit(<C,sum>)
11.实际应用中大数据处理

(1)复杂的批量数据处理(数十分钟~数小时):Mapreduce

(2)基于历史数据的交互式查询(数十秒~数分钟):Cloudera Impala

(3)基于实时数据流的数据处理(数百毫秒~数秒):Storm

12.大数据处理流程及每个步骤的任务和存在的挑战

流程:数据抽取与集成、数据分析以及数据解释

要想处理大数据,首先必须对所需数据源的数据进行抽取和集成,从中提取出关系和实体,经过关联和聚合之后采用统一定义的结构来存储这些数据

在数据集成和提取时需要对数据进行清洗,保证数据质量及可信性

数据量大并不一定意味着数据价值的增加,相反这往往意味着数据噪音的增多

传统的分析技术如数据挖掘、机器学习、统计分析等在大数据时代需要做出调整

数据分析是大数据处理的核心,但是用户往往更关心结果的展示。如果分析的结果正确但是没有采用适当的解释方法,则所得到的结果很可能让用户难以理解,极端情况下甚至会误导用户。

大数据时代的数据分析结果往往也是海量的,同时结果之间的关联关系极其复杂,采用传统的解释方法基本不可行

可以考虑从两个方面提升数据解释能力:引入可视化技术、让用户能够在一定程度上了解和参与具体的分析过程

13.HDFS系统的体系结构及其在数据管理方面的特征优势

Hadoop文件系统采用主从架构对文件系统进行管理,一个HDFS集群由唯一一个目录节点(NameNode)和若干数据节点(DataNodes)组成

HDFS对外表现为一个普通的文件系统,用户可以用文件名去存储和访问文件,而实际上文件是被分成不同的数据块,这些数据块就是存储在数据节点上面。一个典型的Hadoop文件系统集群部署,是由一台性能较好的机器运行目录节点,而集群里面的其它机器每台上面运行一个数据节点。

唯一的目录节点的设计大大简化了整个体系结构,目录节点负责Hadoop文件系统里面所有元数据的管理,这样的设计使数据不会脱离目录节点的控制

目录节点保存文件系统的三种元数据:命名空间、数据块与文件名的映射表、每个数据块副本的位置信息(包括副本因子)

目录节点(NameNode)是集群里面的主节点,负责管理整个HDFS系统的命名空间和元数据,也是客户端访问HDFS系统的入口

数据节点(DataNode)一般就是集群里面的一台机器,负责数据的存储和读取

特征优势:

透明性

并发控制

文件复制功能

硬件和操作系统的异构性

容错能力

安全性问题

14.HBase数据记录的查询定位方法,如何利用子表、元数据子表、根子表来定位数据记录

一个分布式多维表,表中的数据通过:

一个行关键字(row key)

一个列关键字(column family + column name)

一个时间戳(time stamp)

进行索引和查询定位的。

描述所有子表和子表中数据块的元数据都存放在专门的元数据表中,并存储在特殊的子表中。子表元数据会不断增长,因此会使用多个子表来保存

所有元数据子表的元数据都保存在根子表中。主服务器会扫描根子表,从而得到所有的元数据子表位置,再进一步扫描这些元数据子表即可获得所寻找子表的位置

15.说明什么是大数据的四个V,特别解释一些该应用背景下的大数据的value是什么。

Volume—数量大,数据一直都在以每年50%的速度增长,也就是说每两年就增长一倍(大数据摩尔定律)

Velocity—速度快,从数据的生成到消耗,时间窗口非常小,可用于生成决策的时间非常少

Variety—多样化,大数据是由结构化和非结构化数据组成的

Value—价值,价值密度低,商业价值高。以视频为例,连续不间断监控过程中,可能有用的数据仅仅有一两秒,但是具有很高的商业价值

另:大数据分析具有三个特征:全样而非抽样、效率而非精确、相关而非因果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值