统计科学家使用交互式的统计工具(比如R)来回答数据中的问题,获得全景的认识。与之相比,数据工程师则更像一名程序员,他们在服务器上编写代码,创建和应用机器学习模型,熟悉C++和Java等系统级语言,经常需要和企业级数据中心的某些组件打交道,比如Hadoop。
而有的数据科学家专注于更细的领域,就像精通R但从未听说过Python或者scikit-learn(反之亦然),即便两者都提供了丰富的统计库。(文末附有惊喜!)
如果可以提供一种统一的工具,运行在统一的架构,用统一的语言编程,并可以同时满足统计科学家和数据工程师的需求,那该多好啊。难道为了研究数据,我就必须去学一种像Python或R的语言?我一直使用传统的数据分析工具,难道为了应对大规模计算,就必须去懂MapReduce?正是统计工具的不完美造就了这种局面:
Spark是一个超有潜力的通用数据计算平台,无论是对统计科学家还是数据工程师。大部分人讨论到Spark时,总是注意到将数据驻留内存以提高计算效率的方面(相对MapReduce),Spark 拥有许多的特征,使之真正成为一个融合统计科学和数据工程的交叉点:
在命令行解释器中执行的代码,和编译后运行的效果相同。而且,命令行的输入可以得到实时反馈,你将看到数据透明地在集群间传递与计算。
Spark和MLib还有待完善整个项目有不少bug,效率也还有提升的空间,和YARN的整合也存在问题。Spark还没办法提供像R那样丰富的数据分析函数。但Spark已然是世界上最好的数据平台,足以让来自任何背景的数据科学家侧目。
Stack Overflow是一个著名的软件技术问答平台,在上面提的每个问题有可能被打上若干个短文本的标签,比如java或者sql,我们的目标在于建立一.套系统,使用ALS推荐算法,为新问题的标签提供预测和建议。从推荐系统的角度,你可以把问题想象成user,把标签想象成item。
首先,从Stack Overflow下载官方提供的截至20140120的问答数据
- sta ckoverflow. com-Posts. 7z
这是一个能够直接用于分布式计算的bzip格式文件,但在我们的场景下,必须先解压并拷
贝到HDFS
- bzcat stackover flow. com-Posts.7z| hdfs dfs -put一/user /srowen/ Posts. xml
解压后的文件大约是24.4GB,包含210万个问题,1800 万个回答,总共标注了930万个标签,这些标签排重之后大概是34000个。
确认机器安装了Spark 之后,输入spark-shell即可打开Scala的REPL环境。首先,我们读取一个存储在HDFS的Posts. xm文件:
- val postsXML = sC. textFile("hdfs:/ //user /srowen/Posts. xml")
这时命令行工具会返回:
- postsXML: org. apache. spark.rdd.RDD[String] = MappedRDD[1] at textFile at :12
显示文本文件已转化为一个String型的RDD,你可以通过调用RDD的函数,实现任意的查询运算。比如统计文件的行数:
- postsXML. count
这条指令生成大量的输出,显示Spark正在利用分布式的环境计数,最终打印出18066983。
下一步,将XML文件的每- -行都存入形如(questionID, tag)的元组。得益于Scala的函数式编程的风格,RDD和Scala集合-样可以使用map等方法:
- val postIDTags = postsXML. flatMap { line =>
- // Matches Id=".. ."
- Tags="..." in line
- val idTagRegex = "Id=\"(\\d+)\". +Tags=\"([^\"]+)\"".r
- // // Finds tags like <TAG> value from above
- val tagRegex = "<([^&]+)>".r
- // Yields 0 or 1 matches:
- idTagRegex. findFirstMatchIn(line) match {
- // No match -- not a line
- case None => None
- // Match, and can extract ID and tags from m
- case Some(m) => {
- val postID = m. group(1) . toInt
- val tagsString = m. group(2)
- // Pick out just TAG matching group
- val tags = tagRegex. findAllMatchIn(tagsString)。map(_ . group
- (1)) . toList
- // Keep only question with at least 4 tags, and map to (pos
- t,tag) tuples
- if (tags.size >= 4) tags . map( (postID,_)) else None
- }
- }
- // Because of flatMap,individual lists will concatenate
- // into one collection of tuples
- }
你会发现这条指令的执行是立即返回的,而不像count一样需要等待,因为到目前为止,Spark并未启动任何主机间的数据变换。
ALS的MLib实现必须使用数值ID而非字符串作为惟一标识,而问题的标签数据是字符串格式的,所以需要把字符串哈希成一个非负整数,同时保留非负整数到字符串的映射。这里我们先定义一个哈希函数以便复用。
- def nnHash(tag: String) = tag.hashCode & 0x7FFFFF
- var tagHashes = postIDTags .map(_._2) .distinct. map(tag => (nnHash
- (tag) , tag))
现在把元组转换为ALS计算所需的输入:
- import org. apache. spark. mllib. recommendation._
- // Convert to Rating(Int ,Int,Double) objects
- val alsInput = postIDTags.map(t => Rating(t. _1, nnHash(t._2), 1.
- 0) )
- // Train model with 40 features, 10 iterations of ALS
- val model = ALS. trainImplicit(alsInput, 40,10)
这一步生成特征矩阵,可以被用来预测问题与标签之间的关联。由于目前MLib还处于不完善的状态,没有提供一个recommend的接口来获取建议的标签,我们可以简单定义一个:
- def
- recommend (questionID: Int, howMany: Int = 5): Array[(String ,
- Double)] = {
- // Build list of one question and all items and predict value f
- or all of them
- val predictions = model. predict(tagHashes.map(t => (questionI
- D,t._1)))
- // Get top howMany recommendations ordered by prediction value
- val topN = predictions. top ( howMany) (Ordering . by [Rating,Doub1
- e](_.rating))
- // Translate back to tags from IDs
- topN . map(r => (tagHashes. lookup(r . product)(0),r .rating))
通过上述函数,我们可以获得任意一个问题比如ID为7122697的How to make substring-matching query work fast on a large table?的至少4个标签:
- recommend ( 7122697)。foreach(println)
推荐结果如下所示:
- (sqL,0.17745152481166354)
- (database,0.13526622226672633)
- (oracle , 0.1079428707621154)
- (ruby-on-rails, 0.06067207312463499)
- (postgresql,0.050933613169706474)
注意:
真实的问题标签是postgresql、query-optimi zation、substring 和text-search。不过,预测结果也有一定的合理性(postgresq 经常和ruby-on-rails一起出现)
当然,以上的示例还不够优雅和高效,但是,我希望所有来自R的分析师、鼓捣Python 的黑客和熟悉Hadoop的开发者,都能从中找到你们熟悉的部分,从而找到一条适合你们的路径去探索Spark,并从中获益。
在Python开发过程中,我们难免会遇到多重条件判断的情况的情况,此时除了用很多...
前言 统计科学家使用交互式的统计工具(比如R)来回答数据中的问题,获得全景的认...
基本介绍 给定 n 个权值作为 n 个叶子节点,构造一颗二叉树,若该树的带权路径长...
TIOBE 公布了 2021 年 3 月的编程语言排行榜。 本月 TIOBE 指数没有什么有趣的变...
想了解更多内容,请访问: 51CTO和华为官方战略合作共建的鸿蒙技术社区 https://...
背景 我们知道 如果在Kubernetes中支持GPU设备调度 需要做如下的工作 节点上安装...
本文转载自公众号读芯术(ID:AI_Discovery)。 这一刻你正在应对什么挑战?这位前...
近几年,互联网行业蓬勃发展,在互联网浪潮的冲击下,互联网创业已成为一种比较...
溢价 域名 的续费价格如何?通常来说,因为溢价域名的价值高于普通域名,所以溢...
本文转载自微信公众号「bugstack虫洞栈」,作者小傅哥 。转载本文请联系bugstack...