作为计算语言学的学生,我经常进行机器学习实验,需要从各种不同的资源(如原始或标注的文本语料库或句法树库)中准备训练数据。对于每个新任务和每个新实验,我都会编写程序(通常是Python,有时是Java)来提取我需要的特征和值,并将数据从一种格式转换为另一种格式。这通常会导致产生大量的大文件和大量的小程序,这些程序处理这些文件以获取某些机器学习框架的输入(如Weka的arff文件)。
要处理这些,需要极高的组织性,并且要非常小心地编程,以免错过数据中任何重要的特殊情况、例外或错误。对于这些任务,良好的软件设计原则如设计模式或重构范式并没有多大用处,因为安全性、可维护性或可持续性并不重要——一旦程序成功处理了数据,就不再需要它了。这已经到了我甚至不再关心在Python代码中使用类或函数的程度,而是以简单的过程方式编程。下一个实验将需要具有独特特征的不同数据集,并且格式不同,因此它们的准备可能需要从头开始编程。我的经验是,通常一个项目80-90%的时间都花在准备训练数据上。仅仅是思考如何从一种数据格式转换到另一种格式,就可能花费数小时甚至数天。有时,这可能会变得相当令人沮丧。
好吧,你可能已经猜到我有点夸张了,甚至是故意这样做的,但我相信你明白我想表达的意思。实际上,我的疑问是:
有没有处理这些任务的一般框架、架构、最佳实践?我写的代码在最佳设计下有多少可以重用?
回答:
我发现自己主要使用GNU coreutils中的textutils和flex来准备语料库,将它们串联在一起使用简单的脚本,至少当我需要进行的准备足够简单,可以使用正则表达式和简单的过滤等时是这样。
仍然有可能使事情变得可重用,通用的规则也适用于这里。如果你不考虑最佳实践之类的东西,只是以过程方式编程,恕我直言,难怪你每次开始新项目时都得从头开始。
尽管格式要求会大不相同,但仍然有许多常见任务,例如标签剥离、标签转换、选择、制表、一些简单的数数据收集,如标记数、句子数等。针对高重用性编程这些任务,即使一开始需要更长时间,最终也会有回报。