在 Java 中为 Maxent 分类器创建训练数据

Posted

技术标签:

【中文标题】在 Java 中为 Maxent 分类器创建训练数据【英文标题】:Creating training data for a Maxent classfier in Java 【发布时间】:2016-07-02 03:55:29 【问题描述】:

我正在尝试为 maxent 分类器创建 java 实现。我需要将句子分类为n不同的类。

我看过ColumnDataClassifier in stanford maxent classifier。但我无法理解如何创建训练数据。我需要训练数据形式的训练数据,其中训练数据包括句子单词的 POS 标签,以便用于分类器的特征类似于上一个单词、下一个单词等

我正在寻找包含带有 POS TAGGING 的句子和提到的句子类的训练数据。示例:

我的/(POS) 姓名/(POS) 是/(POS) XYZ/(POS) CLASS

任何帮助将不胜感激。

【问题讨论】:

你能举出你正在寻找的训练数据的例子吗? 我正在寻找包含带有 POS TAGGING 的句子和提到的句子类的训练数据。例如:我的/(POS) 姓名/(POS) 是/(POS) XYZ/(POS) CLASS 这些问答有用吗? ***.com/questions/28601653/… 和 ***.com/questions/31091082/… 第二个链接虽然看起来不错。但我仍然不知道如何创建训练集以及如何使用 maxent 分类器来实际使用该训练数据。 【参考方案1】:

如果我理解正确,您是在尝试将句子视为一组 POS 标签。

在您的示例中,句子“我的名字是 XYZ”将表示为一组 (PRP$, NN, VBZ, NNP)。 这意味着,每个句子实际上都是一个长度为 37 的 二进制 向量(因为有 36 possible POS tags according to this page + 整个句子的 CLASS 结果特征)

这可以为 OpenNLP Maxent 编码如下:

PRP$=1 NN=1 VBZ=1 NNP=1 CLASS=SomeClassOfYours1

或者简单地说:

PRP$ NN VBZ NNP CLASS=SomeClassOfYours1

(对于工作代码-sn-p,请在此处查看我的答案:Training models using openNLP maxent)

更多示例数据如下:

    “到 1978 年,无线电城已经失去了它的魅力,洛克菲勒中心的业主决定拆除老化大厅。” “随着时间的推移,他完全被遗忘了,他的许多建筑被拆除,其他建筑被无情地改变。” “诉讼称,她一搬出去,移动房屋就被拆了。” ...

这将产生样本:

IN CD NNP VBD VBN PRP$ NN CC DT NNS IN TO VB VBG CLASS=SomeClassOfYours2
IN NN PRP VBD RB VBN JJ IN PRP$ NNS CLASS=SomeClassOfYours3
IN RB PRP VBD RP DT JJ NN VBN NN CLASS=SomeClassOfYours2
...

但是,我不认为这样的分类会产生好的结果。最好利用句子的其他结构特征,例如解析树或依赖树,可以使用例如Stanford parser.

于 2016 年 3 月 28 日编辑: 您还可以将整个句子用作训练样本。但是,请注意: - 两个句子可能包含相同的单词但具有不同的含义 - 过拟合的可能性很高 - 你应该使用短句 - 你需要一个庞大的训练集

根据您的示例,我将对训练样本进行如下编码:

class=CLASS My_PRP name_NN is_VBZ XYZ_NNP
...

请注意,结果变量是每行的第一个元素。

这是一个使用 opennlp-maxent-3.0.3.jar 的完整工作的最小示例。


package my.maxent;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;

import opennlp.maxent.GIS;
import opennlp.maxent.io.GISModelReader;
import opennlp.maxent.io.SuffixSensitiveGISModelWriter;
import opennlp.model.AbstractModel;
import opennlp.model.AbstractModelWriter;
import opennlp.model.DataIndexer;
import opennlp.model.DataReader;
import opennlp.model.FileEventStream;
import opennlp.model.MaxentModel;
import opennlp.model.OnePassDataIndexer;
import opennlp.model.PlainTextFileDataReader;

public class MaxentTest 


    public static void main(String[] args) throws IOException 

        String trainingFileName = "training-file.txt";
        String modelFileName = "trained-model.maxent.gz";

        // Training a model from data stored in a file.
        // The training file contains one training sample per line.
        DataIndexer indexer = new OnePassDataIndexer( new FileEventStream(trainingFileName)); 
        MaxentModel trainedMaxentModel = GIS.trainModel(100, indexer); // 100 iterations

        // Storing the trained model into a file for later use (gzipped)
        File outFile = new File(modelFileName);
        AbstractModelWriter writer = new SuffixSensitiveGISModelWriter((AbstractModel) trainedMaxentModel, outFile);
        writer.persist();

        // Loading the gzipped model from a file
        FileInputStream inputStream = new FileInputStream(modelFileName);
        InputStream decodedInputStream = new GZIPInputStream(inputStream);
        DataReader modelReader = new PlainTextFileDataReader(decodedInputStream);
        MaxentModel loadedMaxentModel = new GISModelReader(modelReader).getModel();

        // Now predicting the outcome using the loaded model
        String[] context = "is_VBZ", "Gaby_NNP";
        double[] outcomeProbs = loadedMaxentModel.eval(context);

        String outcome = loadedMaxentModel.getBestOutcome(outcomeProbs);
        System.out.println("=======================================");
        System.out.println(outcome);
        System.out.println("=======================================");
    


还有一些虚拟训练数据(存储为training-file.txt):

class=Male      My_PRP name_NN is_VBZ John_NNP
class=Male      My_PRP name_NN is_VBZ Peter_NNP
class=Female    My_PRP name_NN is_VBZ Anna_NNP
class=Female    My_PRP name_NN is_VBZ Gaby_NNP

这会产生以下输出:

Indexing events using cutoff of 0
Computing event counts...  done. 4 events
Indexing...  done.
Sorting and merging events... done. Reduced 4 events to 4.
Done indexing.
Incorporating indexed data for training...  
done.
    Number of Event Tokens: 4
        Number of Outcomes: 2
      Number of Predicates: 7
...done.
Computing model parameters ...
Performing 100 iterations.
  1:  ... loglikelihood=-2.772588722239781  0.5
  2:  ... loglikelihood=-2.4410105407571203 1.0
      ...
 99:  ... loglikelihood=-0.16111520541752372    1.0
100:  ... loglikelihood=-0.15953272940719138    1.0
=======================================
class=Female
=======================================

【讨论】:

感谢您的回复。但我正在寻找这样的训练集 My_PRP name_NN is_VBZ XYZ_NNP CLASS 这意味着该句子也与 POS 标签一起出现在训练集中。然后使用maxent作为分类器,使用的特征包括基于句子单词和POS标签的特征, 我刚刚编辑了我的答案 - 在 java + 示例数据中添加了一个完整的工作示例。 非常感谢。你能再告诉我一件事吗?分类器现在使用的所有功能是什么。 ?也是使用词性标签作为分类特征还是将词性标签视为其他英文单词。 分类器只看到一些标记(例如“My_PRP”作为标记),并不关心它们的含义。我认为它在内部将每个标记视为将 string 映射到 bool 的哈希表中的索引。 分类器使用的特征呢?可以定制吗?

以上是关于在 Java 中为 Maxent 分类器创建训练数据的主要内容,如果未能解决你的问题,请参考以下文章

stanford maxent 分类预测

大数据集的最大熵分类器

Python NLTK 最大熵分类器错误

为啥我们需要正则化来训练 MaxEnt?

opencv训练分类器样本处理

无需评估即可创建 Weka 分类器模型