我正在用C++编写一个前馈神经网络的反向传播实现,并使用Armadillo库。目前,我使用Armadillo库中matrix
类的load
方法来加载训练数据。我有两个问题:
1) 对于存储已经格式化好的(CSV格式)、适合内存(<2GB)的数值数据,使用这种方法是否合理?当然,有更好的方法来做这件事,如果这不是一个好做法,我很想知道。我的一部分感觉这不是一个好的选择,因为可能有更适合数据的结构/框架(比如我应该访问某个SQL数据库之类的东西)。而我的另一部分感觉数值数据本质上就是矩阵,所以这应该很好。
2) 在我的实现中,我需要从数据集中无放回地抽样,我看到两种方法:要么我可以打乱数据集的行,要么打乱一个索引数据集的数组。Armadillo库中的matrix
类有一个shuffle
方法,我怀疑被打乱的是地址而不是行本身。这不就像打乱一个索引数组一样有效吗?
回答:
1) 是的,这样做是可以的,我也会这样做,但请注意Armadillo矩阵是列主序的,因此你可能需要转置你加载的CSV。如果你的数据足够大,无法装入主内存,你可以考虑编写一个自定义的CSV解析器,以流的方式查看数据(即一次一个点),从而减少你的RAM占用,或者你甚至可以使用mmap()
将一个充满打包双精度数的文件映射为你的矩阵,让内核决定何时需要交换进来什么数据。
2) 因为所有矩阵数据都是连续存储的(即double*
而不是double**
),shuffle()
将移动矩阵中的元素。在这种情况下,我通常会创建一个索引向量并对其进行打乱:
uvec indices = linspace<uvec>(0, n, n);shuffle(indices);// 现在遍历每个打乱的点...for (uword i = 0; i < n; ++i){ // 使用data.col(indices[i])访问点并执行任何操作}
(以上代码未经测试,但应该可以工作或很容易改编成可用的代码。)
顺便说一下,mlpack (http://www.mlpack.org/)确实有一个尚未稳定的神经网络基础设施,它使用Armadillo,可能值得你花时间查看;下面的链接直接指向相关源代码,但在Github和mlpack网站上浏览应该能找到更好的文档。
https://github.com/mlpack/mlpack/tree/master/src/mlpack/methods/ann