在非超级计算机上处理海量数据的通用技术
我正在上人工智能课程,学到了一些基本的算法,想要进行一些实验。我通过Kaggle获得了几个数据集,这里有很多很棒的真实数据,Kaggle还举办数据分析比赛。
我尝试参加几个比赛来提高我的机器学习技能,但在代码中访问数据的好方法一直没找到。Kaggle每个比赛提供一个大的数据文件,大小在50到200MB之间,格式是csv。
我该如何在代码中加载和使用这些表格呢?我最初的想法是使用数据库,所以我尝试把csv文件加载到sqlite这个单一数据库中,但这给我的电脑带来了很大的压力,提交数据时,电脑经常崩溃。接着,我又尝试在一个共享主机上使用mysql服务器,但查询的速度慢得让人抓狂,这让我的分析代码变得非常缓慢。而且,我还担心会超出我的带宽限制。
到目前为止,在我的课程中,老师们通常会先清理数据,然后给我们一些可以完全加载到内存中的可管理的数据集。显然,这对我现在的需求来说是不可能的。请建议我该如何进行。我现在使用的是一台四年前的macbook,配备4GB内存和2.1GHz双核CPU。
顺便说一下,我希望大部分分析工作能用Python来完成,因为我对这门语言最熟悉。我希望能找到一个解决方案,让我可以在这个语言中完成所有或几乎所有的编码工作。
5 个回答
你需要用到'Pandas'这个库。我想你现在应该明白了。不过如果还有其他人遇到这个问题,看到这个回答也能有所帮助。
所以你不需要把数据放到任何关系型数据库里,只需把它保存在文件中,然后用简单的Pandas加载和处理数据框。这里是Pandas库的链接--> http://pandas.pydata.org/
如果数据量太大,你就需要一个集群来处理。可以使用Apache Spark或者Mahout,这些都可以在亚马逊的EC2云上运行。你可以在那里购买一些存储空间,这样使用起来会更方便。Spark也有Python的API。
200兆字节的文件对于加载到数据库来说并不算大。你可以尝试把输入文件分成几个小文件。
split -l 50000 your-input-filename
split
这个工具可以把你的输入文件分成多个你想要大小的文件。我上面用了每个文件50000行。这是一个常见的Unix和Linux命令行工具,不知道Mac上有没有自带。
如果你在做的事情上,使用本地安装的PostgreSQL或者MySQL可能比SQLite更合适。
如果你不想把数据加载到数据库里,可以用一些命令行工具,比如grep、awk和sed来提取数据的子集。(或者使用像python、ruby和perl这样的脚本语言。)把这些子集传递给你的程序。
原型——这是处理大数据时最重要的事情。合理地将数据分割,以便能够在内存中加载并通过解释器访问它,比如 Python 或 R。这是以大规模创建和完善分析流程的最佳方法。
换句话说,就是把那些多 GB 大小的数据文件缩减到足够小,以便可以进行 命令行分析。
以下是我用来做到这一点的工作流程——这可能不是最好的方法,但确实是一种可行的方法:
I. 使用懒加载的方法(希望在你选择的编程语言中可以使用)来读取大数据文件,特别是那些超过 1 GB 的文件。然后我建议根据下面讨论的技术处理这个数据流,最后将这个完全预处理的数据存储在数据集市或中间暂存容器中。
以下是一个使用 Python 懒加载大数据文件的示例:
# 'filename' is the full path name for a data file whose size
# exceeds the memory on the box it resides. #
import tokenize
data_reader = open(some_filename, 'r')
tokens = tokenize.generate_tokens(reader)
tokens.next() # returns a single line from the large data file.
II. 标准化和重构:
将存储分类变量(例如,男性/女性)的列重新编码为整数(例如,-1,1)。保持一个查找表(与用于此转换的哈希相同,只是键和值交换)以便在分析流程的最后一步将这些整数转换回人类可读的字符串标签;
对数据进行标准化——也就是“归一化”那些包含连续数据的列。这两个步骤都会显著减少数据集的大小——而不会引入任何噪音。标准化的另一个好处是可以防止因过度加权而导致的分析错误。
III. 抽样:按长度修剪数据。
IV. 降维:这是抽样的正交对应。识别那些对因变量(也就是“结果”或响应变量)没有影响或影响微乎其微的变量(列/字段/特征),并将它们从你的工作数据立方体中删除。
主成分分析(PCA)是一种简单可靠的技术来做到这一点:
import numpy as NP
from scipy import linalg as LA
D = NP.random.randn(8, 5) # a simulated data set
# calculate the covariance matrix: #
R = NP.corrcoef(D, rowvar=1)
# calculate the eigenvalues of the covariance matrix: #
eigval, eigvec = NP.eig(R)
# sort them in descending order: #
egval = NP.sort(egval)[::-1]
# make a value-proportion table #
cs = NP.cumsum(egval)/NP.sum(egval)
print("{0}\t{1}".format('eigenvalue', 'var proportion'))
for i in range(len(egval)) :
print("{0:.2f}\t\t{1:.2f}".format(egval[i], cs[i]))
eigenvalue var proportion
2.22 0.44
1.81 0.81
0.67 0.94
0.23 0.99
0.06 1.00
所以你可以看到,前面三个特征值占原始数据中观察到的方差的 94%。根据你的目的,你通常可以通过删除最后两列来修剪原始数据矩阵 D:
D = D[:,:-2]
V. 数据集市存储:在你的永久存储(数据仓库)和分析流程之间插入一层。换句话说,重度依赖数据集市/数据立方体——这是一个位于数据仓库和分析应用层之间的“暂存区”。这个数据集市是你分析应用的一个更好的输入输出层。R 的“数据框”或“数据表”(来自同名的 CRAN 包)都是不错的选择。我还强烈推荐 redis——快速读取、简洁的语义和零配置,使其成为这个用例的优秀选择。redis 可以轻松处理你在问题中提到的大小的数据集。例如,使用 redis 中的哈希数据结构,你可以拥有与 MySQL 或 SQLite 相同的结构和关系灵活性,而无需繁琐的配置。另一个优点是:与 SQLite 不同,redis 实际上是一个数据库 服务器。我其实很喜欢 SQLite,但我认为在这里 redis 更加适合,原因如上所述。
from redis import Redis
r0 = Redis(db=0)
r0.hmset(user_id : "100143321, {sex : 'M', status : 'registered_user',
traffic_source : 'affiliate', page_views_per_session : 17,
total_purchases : 28.15})