本节书摘来自华章计算机《Scala机器学习》一书中的第1章,第1.2节,作者:[美] 亚历克斯·科兹洛夫(Alex Kozlov),更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1.2 去除分类字段的重复值
请准备好数据集和电脑。为了方便起见,本书已经提供了一些关于点击流(clickstream)数据的样本,它们是经过预处理过的,在https://github.com/alexvk/ml-in-scala.git上可以找到这些数据。chapter01/data/clickstream文件夹中包含了时间戳、会话编号(session ID),以及在调用时的一些额外事件信息(比如URL、类别信息等)。首先要对数据集的各个列做一些变换,以此得到数据的分布情况。
图1-1给出了在命令行中执行gzcat chapter01/data/clickstream/clickstream_sample.tsv.gz | less-U所得到的结果。列之间用tab键(^I)隔开。读者可能会注意到,许多值都空缺了,许多现实应用中的大数据集都是这样。数据的第一列是时间戳,文件包含了复杂的数据(比如数组(array)、结构(struct),以及映射(map)),这也是大数据集的另一个特征。
图1-1 使用Unix的less-U命令后,clickstream文件得到的输出
Unix提供了一些工具来分析数据。less、cut、sort和uniq大概是文本处理中最常用的命令行工具。awk、sed、perl和tr可以做更复杂的转换和提取操作。
幸运的是,Scala允许在REPL中透明地使用命令行工具来做转换:
在Scala REPL环境中,可使用scala.sys.process包来调用熟悉的Unix命令。从输出结果可以立即看到这个网上商店的顾客最关注男鞋和跑步鞋,而且大多数访问者使用的推荐码(referral code)为KW_0611081618。
读者可能会奇怪:究竟什么时候才开始使用复杂的Scala类型和算法。其实许多高度优化的工具在Scala之前就有了,而且在数据挖掘分析中会更高效。在最初的阶段,最大的瓶颈通常只是磁盘I/O和缓慢的交互性。随后才会去研究更多的迭代算法,它们通常都是内存密集型算法。值得注意的是:在现代多核计算机中,隐式地并行执行Unix的管道操作,就像在Spark中并行执行一样(后面的章节会介绍)。
对输入数据使用隐式的或显式的压缩,也可以减少I/O时间。 这对具有重复值和稀疏内容的(大多数)半结构化数据集更有效。也可在多核计算机上隐式地并行执行解压操作,这可以消除计算瓶颈,但在硬件上却不能并行执行压缩操作(比如,在SSD上就不能并行压缩文件)。推荐使用文件夹而不是文件作为数据集的规范(paradigm),这样插入操作就可简化为把数据文件放在文件夹中。这就是Hadoop(比如Hive和Impala)组织数据的原理。