0

我是一名数据挖掘者,因此,我花费大量时间以各种方式转换原始数据,以支持预测模型的消费。例如,以某种格式读取文件、标记化、语法化并投影为某种数字表示。多年来,我开发了一套丰富的方法来完成我能想到的大多数数据处理任务,但除了最基本的方式之外,我没有一个很好的方法来配置这些组件——通常我所做的是很多源代码中依赖于特定任务的特定方法的调用次数。我现在正在尝试将我的库重构为更好的东西,但我不太确定这是什么。

我目前的想法是,有一个函数对象列表,每个函数对象定义一些方法(比如,operate(...)),它们按顺序调用,每个对象要么通过引用处理某些数据流的内容,要么消耗前一个函数对象。这与我想要的很接近,但是由于输入和输出的数据类型会有所不同,因此使用泛型变得非常困难。要使用我上面的例子,我想通过这个处理数据的“管道”传递一些东西,比如:

input: string filename
filename -> collection of strings
collection<string> -> (stemming, stopword removal) -> collection of strings
collection<string> -> (tokenize) -> collection of string arrays
collection<string[]> -> (gram-ify) -> augment individual token strings with n-grams -> collection of string arrays
collection<string[]> -> projection into numeric vectors -> collection< double[] >

这是一个简单的例子,但想象一下我有 100 个这样的组件,我想将它们添加到一些数据流中。这满足了我易于配置的要求——我可以轻松地构建一个管道工厂来读取一些 yaml 文件并将其构建出来。然而,组件的设计模式一直困扰着我一段时间?合适的接口是什么样的?似乎在这里做事的唯一简单方法是传递对象,本质上取消对象(或者传递一些将对象作为成员变量的上下文对象),然后在输入时检查兼容性,抛出运行时异常. 这两种选择似乎同样糟糕。然而,我觉得我在这里接近一个非常好的和灵活的系统。你们能帮我把它推过栅栏吗?

4

3 回答 3

1

我可能是从字面上看你的例子;这意味着此解决方案可能不适用于您的实际问题。

public interface Interface1 {
  public List<String> operate(List<String> list);
}

public interface InterfaceBridge {
  public List<List<String>> operate(List<String> list);
}

public interface Interface2 {
  public List<List<String>> operate(List<List<String>> list);
}

您显然应该选择更好的接口名称。然后,您可以使用以下方式组合它们:

public class Interface1Composite implements Interface1 {
  List<Interface1> components = new ArrayList<>();

  public Interface1Composite(Interface1... components) {
    for (Interface1 i1 : components)
      this.components.add(i1);
  }

  @Override 
  public List<String> operate(List<String> list) {
    for (Interface1 i1 : components)
      list = i1.operate(list);
    return list;
  }

我想这几乎就是你已经在做的事情。我只是通过使用 3 种类型的接口而不是尝试使用泛型来简化。但正如我之前所说,我不知道您是否可以将其应用于您的问题。

于 2011-11-10T03:05:04.147 回答
1

apache 基金会有一个名为 pipelines https://commons.apache.org/sandbox/pipeline/的项目。也许它可以派上用场。我认为那里有更多基于管道的项目。浏览该站点可能很有用。

于 2011-11-10T02:14:20.170 回答
1

我认为将您的库绑定在一起的更灵活的工具将是一个好方法。例如,其中一种新的动态语言将非常适合。

Clojure 非常适合内置的 map、pmap、reduce 过滤器等工具。Clojure 的集合都实现了 java.util 集合库的接口,因此您可以将更高级别的 Clojure 函数应用于现有的 Java 代码,或者您还可以将 Clojure 数据结构直接传递给您的 Java 代码(只要 Java 代码不希望修改它)。

该语言的轻量级和动态特性使其可以轻松快速地将事物组合在一起,而无需太多开销。

于 2011-11-10T02:23:00.403 回答