对于一个类,我正在处理原始文本文档(我们的示例包括可以从Gutenberg项目下载的小说)并将它们转换为字典数据结构.对于每个单词,我需要知道它出现在哪个段落中,以及每个段落中出现多少次.
程序大致可分为
>将文档分解为单词,删除空格,逗号,句点等.
>对于每个文档,迭代单词.在字典中查找.如果该单词存在,请更新其条目.如果它不存在,请创建一个新条目.
我正在做这个MATLAB,因为我的其余工作都在MATLAB中,我不想处理另一种语言/环境.事实证明,MATLAB有一些非常好的字符串处理功能.但是,我对代码的运行速度感到不安.我上面提到的第一部分不是问题;我使用parfor循环,它的速度非常快.第二部分是我的问题所在.
我最初尝试创建这个字典是使用结构,一个MATLAB内置数据类型.我们的想法是创建一个名为dictionary的结构,其字段名称是实际的单词,例如,词典’the’和’gnome’的dictionary.the或dictionary.gnome.如果这个词是一个有效的字段名称(例如,它不能是收缩),这就有效.但它运行缓慢,所以我寻求一个不同的解决方案.我的下一次尝试是使用containers.Map,这是MATLAB相当于哈希映射或字典对象. (我的一位同事告诉我,MATLAB在查找结构的字段名称方面效率不高,而哈希表的查找时间为O(1).但是,进行此替换实际上会降低我的性能!
在这一点上,我觉得我在优化代码方面做了一些非常重要的尝试,并开始怀疑MATLAB在这里是否真的是一个明智的选择.我基本上试图弄清楚缓慢是MATLAB的产物还是我是一个糟糕的程序员(通常MATLAB在线性代数,数组和矩阵方面非常快).与其让某人阅读我的代码,我非常感谢社区对以下任何一项提供的任何反馈:
>有没有人在MATLAB或类似语言(如Python)中进行此类事情(即语言处理)?如果是这样,我想尝试对我的一些时间进行基准测试. (我有一台MacBook,2.8 GHz处理器,而且我现在每秒大约需要10-20K字.)
>如果我改用Java或C等编译语言,我是否有可能获得更好的结果? Ballpark估计,有什么样的改进?
最佳答案 我的特殊意见:
如果你的项目可以很好地分为(1)文本,数据处理和(2)数学分析,我会用Java或Python做所有的前者. (注意:我不是NLP人.)
MATLAB要么快得多(例如使用BLAS / LAPACK库的矩阵操作),要么根据你正在做的事情而令人震惊.
Matlab中没有高性能的HashMap解决方案.与你在C或Java中可以做的相比,使用containers.Map并不快. (我听说有人提倡使用struct,fieldname hack作为在Matlab中获得更快地图性能的技巧.)
快速而肮脏,非常不精确的测试:
将100万个随机生成的唯一字符串插入容器中.我的机器上的地图需要大约30秒:
tic();
for i=1:1000000
m(x{i}) = i;
end
toc();
Elapsed time is 38.781537 seconds.
另一方面,调用java虚拟机并运行下面的代码需要我的机器不到2秒:
HashMap<String, Double> hm = new HashMap<String, Double>();
Random r = new Random();
for(long i = 0; i < 1000000; i++) {
hm.put(Double.toString(r.nextDouble()), r.nextDouble());
}
mgunn@odysseus:~/MATLAB/delme/container_test$time java ctest
1.697u 0.151s 0:00.91 202.1% 0+0k 0+1io 0pf+0w
从MATLAB访问Java对象也有很多开销……
tic();
h = java.util.HashMap;
for i=1:1000000
h.put(x{i},i);
end
toc();
Elapsed time is 53.177989 seconds.
附加评论
为了获得最佳性能,很难击败高度优化的c / c代码.除非你非常熟悉c / c(即便如此),否则你最终会遇到令人头疼的内存管理等问题….
对于学术编码,优秀与好的表现通常不是一个问题.获得正确的代码比速度更重要.
Java或Python是更容易编写代码的语言,Java倾向于具有更好的性能(但我不是这里的专家).