【问题标题】:Using custom feature generators with parameters in OpenNLP在 OpenNLP 中使用带有参数的自定义特征生成器
【发布时间】:2013-10-16 15:47:47
【问题描述】:

我正在尝试在具有 XML 特征生成器描述符和一些非标准特征的项目中设置 OpenNLP NameFinder。 XML 描述符支持自定义特征生成器:

<generators>
  <cache>
    <generators>
      ...
      <custom class="com.example.MyFeatureGenerator"/>
   </cache>
</generators>

但是,文档没有提到将参数传递给特征生成器。为特征生成器的每个稍微不同的配置创建一个新类是不可取的。另一方面,以编程方式创建特征生成器可能意味着复制大部分 OpenNLP 代码来处理特征生成器设置。在 OpenNLP 中使用自定义特征生成器的推荐方法是什么?

【问题讨论】:

    标签: opennlp


    【解决方案1】:

    如果您不介意在 Apache OpenNLP 上打开 jira 问题并请求解决此问题。自定义元素应该可以传入参数和外部资源。

    【讨论】:

    • 更多的是评论而不是答案
    • 因为新用户无法评论;不是这样吗?
    【解决方案2】:

    目前还没有合适的解决方案,但我通过在 OpenNLP 中注册一个新功能工厂解决了这个问题。不幸的是,这需要通过反射访问 OpenNLP 类 GeneratorFactory 的私有部分。这是一个可行的解决方案。

    首先,定义一个新类,命名为XmlDescriptorUtil:

    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.Map;
    
    import opennlp.tools.util.InvalidFormatException;
    import opennlp.tools.util.featuregen.AdaptiveFeatureGenerator;
    import opennlp.tools.util.featuregen.FeatureGeneratorResourceProvider;
    import opennlp.tools.util.featuregen.GeneratorFactory;
    
    import org.w3c.dom.Element;
    
    public final class XmlDescriptorUtil {
      private XmlDescriptorUtil(){};
    
      public static abstract class XmlDescriptorFactory implements InvocationHandler
      {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          return create((Element)args[0], (FeatureGeneratorResourceProvider)args[1]);
        }
    
        public abstract AdaptiveFeatureGenerator create(Element generatorElement, FeatureGeneratorResourceProvider resourceManager)
          throws InvalidFormatException;
      }
    
      public static void register(String name, XmlDescriptorFactory factory) throws Exception
      {
        Class<?> factoryInterface = Class.forName(GeneratorFactory.class.getName()+"$XmlFeatureGeneratorFactory");
        Object proxy = Proxy.newProxyInstance(GeneratorFactory.class.getClassLoader(), new Class[]{factoryInterface}, factory);
        registerByProxy(name, proxy);
      }
    
      private static void registerByProxy(String name, Object proxy) throws Exception
      {
        Field f = GeneratorFactory.class.getDeclaredField("factories");
        f.setAccessible(true);
        @SuppressWarnings("unchecked")
        Map<String, Object> factories = (Map<String, Object>) f.get(null);
        factories.put(name, proxy);
      }
    
    }
    

    然后,创建一个实现公共接口XmlDescriptorUtil$XmlDescriptorFactory的特征生成器工厂:

    public static void main(String[] args) {
      XmlDescriptorUtil.register("myCustom", new XmlDescriptorUtil.XmlDescriptorFactory() {
        @Override
        public AdaptiveFeatureGenerator create(Element generatorElement, FeatureGeneratorResourceProvider resourceManager) throws InvalidFormatException {
          return new MyFeatureGenerator();
        });
    }
    

    现在,特征生成器已准备就绪,可以在 XML 描述符中使用:

    <generators>
      <cache>
        <generators>
          ...
          <myCustom/>
        </generators>
      </cache> 
    </generators>
    

    如果特征生成器需要参数,可以从工厂类中的generatorElement中提取出来。

    【讨论】:

      猜你喜欢
      • 2018-04-06
      • 2012-08-12
      • 2016-12-23
      • 2020-12-05
      • 1970-01-01
      • 2017-01-22
      • 2019-04-20
      • 2020-11-04
      • 2018-10-23
      相关资源
      最近更新 更多