现在的Java程序中用到了Stanford Parser,在程序功能完整实现后,我开始对这个Parser的使用进行加速。
由于采用的直接嵌入式的调用,没有遇到命令行调用方式下会遇到的资源重复加载的问题。在主控程序中对Parser采用一个类(A)的静态函数来加载所需资源到该类的静态成员变量上,就得到了一个全局的常驻内存资源。哈哈,第一次采用这种方案来实现全局资源,感觉甚为不错!在类A中另写了一个静态函数来执行句法分析。在对文件的处理循环中的某个特征抽取部分,使用类A的静态句法分析函数,从而实现了全局的调用。
加速方案我采用的主要有两种:
- 如果pair的第二个元素和第一个元素位于同一个句子,就只parse一次。
- 在类A的parse函数中对已经parse过的句子直接加载parse结果。
第一个方法实现起来非常简单,关键是第二个。尝试了几种解决方案后我最后结合hashcode和序列化方法实现了这个功能。这里记录一下,以备查找。
hashcode是对即将Parse的句子采用.HashCode()方法获得这个对象唯一的整数索引值,将这个索引值对应成文件名即可实现每个句子parse后对应一个唯一的文件。说起来这个hashcode函数还真是很神奇的 :)
序列化是我在Python里面常用的技巧,想来就是将对象存入文件以及从文加载对象两步。基于原理都是一样的。但是看了一下Java中对序列化的介绍后,感觉序列化功能也是有巨大应用功能的。参考了一下如下一段讲述Java序列化方法的文章后完成了我的Parse加速。
3.一般序列化实例 程序名称:SerializationDemo.java 程序主题:实现对象的序列化和反序列化 程序说明:该程序由实例化一个MyClass类的对象开始,该对象有三个实例变量,类型分别为String、int、double,是希望存储和恢复的信息。 import java.io.Serializable; class MyClass implements Serializable { String s; int i; double d; public MyClass(String s, int i, double d) { this.s = s; this.i = i; this.d = d; } public String toString() { return "s=" + s + ";i=" + i + ";d=" + d; } } 要想序列化对象,你必须先创建一个OutputStream,然后把它嵌进ObjectOutputStream。这时,你就能用writeObject ( )方法把对象写入OutputStream了。读的时候,你得把InputStream嵌到ObjectInputStream里面,然后再调用 readObject( )方法。 import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerializationDemo { public static void main(String args[]) { FileInputStream in = null; FileOutputStream out = null; ObjectInputStream oin = null; ObjectOutputStream oout = null; MyClass object1 = new MyClass("Hello", -7, 2.7e10); System.out.println("object1:" + object1); // Object serialization try { out = new FileOutputStream("serial.txt"); oout = new ObjectOutputStream(out); oout.writeObject(object1); oout.close(); } catch (Exception e) { System.out.println("Exception during serialization:" + e); System.exit(0); } // Object deserialization try { MyClass object2; in = new FileInputStream("serial"); oin = new ObjectInputStream(in); object2 = (MyClass) oin.readObject(); oin.close(); System.out.println("object2:" + object2); } catch (Exception e) { System.out.println("Exception during deserialization:" + e); System.exit(0); } finally { // …此处省略 } } } 结果: object1:s=Hello;i=-7;d=2.7E10 object2:s=Hello;i=-7;d=2.7E10 |
现在我的程序正在健步如飞的运行着,任何两个一模一样的句子都只会被parse一次。
序列化和hashcode搭配起来真是不错~!
1 条评论:
您好,请问您是如何 在java程序中使用Stanford Parser api的? 我是这样用的
LexicalizedParser lexParser = new LexicalizedParser(“englishPCFG.ser.gz”);
public String parse(String sentence)
{
lexParser.parse(sentence);
String s = lexParser.getBestParse().toString();
return s;
}
,但是,当连续分析了很多句子后(多次调用parse),内存消耗非常大。希望能得到您的帮助。谢谢。我的邮箱lujun59[AT]gmail.com
发表评论