CRF++ is a simple, customizable, and open source implementation of Conditional Random Fields (CRFs) for segmenting/labeling sequential data. CRF++ is designed for generic purpose and will be applied to a variety of NLP tasks, such as Named Entity Recognition, Information Extraction and Text Chunking.
% ./configure % make % su # make installYou can change default install path by using --prefix option of configure script.
Both the training file and the test file need to be in a particular format for CRF++ to work properly. Generally speaking, training and test file must consist of multiple tokens. In addition, a token consists of multiple (but fixed-numbers) columns. The definition of tokens depends on tasks, however, in most of typical cases, they simply correspond to words. Each token must be represented in one line, with the columns separated by white space (spaces or tabular characters). A sequence of token becomes a sentence. To identify the boundary between sentences, an empty line is put.
You can give as many columns as you like, however the number of columns must be fixed through all tokens. Furthermore, there are some kinds of "semantics" among the columns. For example, 1st column is 'word', second column is 'POS tag' third column is 'sub-category of POS' and so on.
The last column represents a true answer tag which is going to be trained by CRF.
Here's an example of such a file: (data for CoNLL shared task)
He PRP B-NP reckons VBZ B-VP the DT B-NP current JJ I-NP account NN I-NP deficit NN I-NP will MD B-VP narrow VB I-VP to TO B-PP only RB B-NP # # I-NP 1.8 CD I-NP billion CD I-NP in IN B-PP September NNP B-NP . . O He PRP B-NP reckons VBZ B-VP ..
There are 3 columns for each token.
The following data is invalid, since the number of columns of second and third are 2. (They have no POS column.) The number of columns should be fixed.
He PRP B-NP reckons B-VP the B-NP current JJ I-NP account NN I-NP ..
As CRF++ is designed as a general purpose tool, you have to specify the feature templates in advance. This file describes which features are used in training and testing.
Each line in the template file denotes one template. In each template, special macro %x[row,col] will be used to specify a token in the input data. row specfies the relative position from the current focusing token and col specifies the absolute position of the column.
Here you can find some examples for the replacements
Input: Data He PRP B-NP reckons VBZ B-VP the DT B-NP << CURRENT TOKEN current JJ I-NP account NN I-NP
template | expanded feature |
%x[0,0] | the |
%x[0,1] | DT |
%x[-1,0] | rokens |
%x[-2,1] | PRP |
%x[0,0]/%x[0,1] | the/DT |
ABC%x[0,1]123 | ABCthe123 |
Note also that there are two types of templates. The types are specified with the first character of templates.
This is a template to describe unigram features. When you give a template "U01:%x[0,1]", CRF++ automatically generates a set of feature functions (func1 ... funcN) like:
func1 = if (output = B-NP and feature="U01:DT") return 1 else return 0 func2 = if (output = I-NP and feature="U01:DT") return 1 else return 0 func3 = if (output = O and feature="U01:DT") return 1 else return 0 .... funcXX = if (output = B-NP and feature="U01:NN") return 1 else return 0 funcXY = if (output = O and feature="U01:NN") return 1 else return 0 ...
The number of feature functions generated by a template amounts to (L * N), where L is the number of output classes and N is the number of unique string expanded from the given template.
This is a template to describe bigram features. With this template, a combination of the current output token and previous output token (bigram) is automatically generated. Note that this type of template generates a total of (L * L * N) distinct features, where L is the number of output classes and N is the number of unique features generated by the templates. When the number of classes is large, this type of templates would produce a tons of distinct features that would cause inefficiency both in training/testing.
The words unigram/bigram are confusing, since a macro for unigram-features does allow you to write word-level bigram like %x[-1,0]%x[0,0]. Here, unigram and bigram features mean uni/bigrams of output tags.
You also have to put an identifier in templates when they want to distinguish relative positions of tokens.
In the following case, the macro "%x[-2,1]" and "%x[1,1]" will be replaced into "DT". But they indicates different "DT".
The DT B-NP pen NN I-NP is VB B-VP << CURRENT TOKEN a DT B-NP
To distinguish both two, put an unique identifier (U01: or U02:) in the template:
U01:%x[-2,1] U02:%x[1,1]
In this case both two templates are regarded as different ones, as they are expanded into different features, "U01:DT" and "U02:DT". You can use any identifier whatever you like, but it is useful to use numerical numbers to manage them, because they simply correspond to feature numbers.
If you want to use "bag-of-words" feature, in other words, not to care the relative position of features, You don't have to put such identifiers.
Here is the template example for CoNLL 2000 shared task and Base-NP chunking task. Only one bigram template ('B') is used. This means that only combinations of previous output token and current token are exploited as bigram features. The lines starting from # or empty lines are discarded as comments
# Unigram U00:%x[-2,0] U01:%x[-1,0] U02:%x[0,0] U03:%x[1,0] U04:%x[2,0] U05:%x[-1,0]/%x[0,0] U06:%x[0,0]/%x[1,0] U10:%x[-2,1] U11:%x[-1,1] U12:%x[0,1]q U13:%x[1,1] U14:%x[2,1] U15:%x[-2,1]/%x[-1,1] U16:%x[-1,1]/%x[0,1] U17:%x[0,1]/%x[1,1] U18:%x[1,1]/%x[2,1] U20:%x[-2,1]/%x[-1,1]/%x[0,1] U21:%x[-1,1]/%x[0,1]/%x[1,1] U22:%x[0,1]/%x[1,1]/%x[2,1] # Bigram B
Use crf_learn command:
% crf_learn template_file train_file model_file
where template_file and train_file are the files you have to prepare in advance. crf_learn generates the trained model file in model_file.
Typically, crf_learn outputs the following information to STDOUT. Also, crf_learn shows additional information for each iteration of LBFGS routine.
% crf_learn template_file train_file model_file CRF++: Yet Another CRF Tool Kit Copyright (C) 2005 Taku Kudo, All rights reserved. reading training data: Done! 0.32 s Number of sentences: 77 Number of features: 32856 Freq: 1 eta: 0.0001 C(sigma^2): 10 iter=0 terr=0.7494725738 serr=1 obj=2082.968899 diff=1 iter=1 terr=0.1671940928 serr=0.8831168831 obj=1406.329356 diff=0.3248438053 iter=2 terr=0.1503164557 serr=0.8831168831 obj=626.9159973 diff=0.5542182244
There are two major parameters to control the training condition
Here is the example where these two parameters are used.
% crf_learn -f 3 -c 1.5 template_file train_file model_file
Use crf_test command:
% crf_test -m model_file test_files ...
where model_file is the file crf_learncreates. In the testing, you don't have to specify the template file, because the model file has the same information for the template. test_file is the test data you want to assign sequential tags. This file has to be written in the same format as training file.
Here is an output of crf_test:
% crf_test -m model test.data Rockwell NNP B B International NNP I I Corp. NNP I I 's POS B B Tulsa NNP I I unit NN I I ..
The last column is given (estimated) tag. If the 3rd column is true answer tag , you can evaluate the accuracy by simply seeing the difference between the 3rd and 4th columns.
The -v option sets verbose level. default value is 0. By increasing the level, you can have an extra information from CRF++
% crf_test -v1 -m model test.data| head # 0.478113 Rockwell NNP B B/0.992465 International NNP I I/0.979089 Corp. NNP I I/0.954883 's POS B B/0.986396 Tulsa NNP I I/0.991966 ...
The first line "# 0.478113" shows the conditional probably for the output. Also, each output tag has a probability represented like "B/0.992465".
You can also have marginal probabilities for all other candidates.
% crf_test -v2 -m model test.data # 0.478113 Rockwell NNP B B/0.992465 B/0.992465 I/0.00144946 O/0.00608594 International NNP I I/0.979089 B/0.0105273 I/0.979089 O/0.0103833 Corp. NNP I I/0.954883 B/0.00477976 I/0.954883 O/0.040337 's POS B B/0.986396 B/0.986396 I/0.00655976 O/0.00704426 Tulsa NNP I I/0.991966 B/0.00787494 I/0.991966 O/0.00015949 unit NN I I/0.996169 B/0.00283111 I/0.996169 O/0.000999975 ..
With the -n option, you can obtain N-best results sorted by the conditional probability of CRF. With n-best output mode, CRF++ first gives one additional line like "# N prob", where N means that rank of the output starting from 0 and prob denotes the conditional probability for the output.
Note that CRF++ sometimes discards enumerating N-best results if it cannot find candidates any more. This is the case when you give CRF++ a short sentence.
CRF++ uses a combination of forward Viterbi and backward A* search. This combination yields the exact list of n-best results.
Here is the example of the N-best results.
% crf_test -n 20 -m model test.data # 0 0.478113 Rockwell NNP B B International NNP I I Corp. NNP I I 's POS B B ... # 1 0.194335 Rockwell NNP B B International NNP I I
In the example directories, you can find three case studies, baseNP chunking, Text Chunking, and Japanese named entity recognition, to use CRF++.
In each directory, please try the following commands
% crf_learn template train model % crf_test -m model test
$Id: index.html,v 1.23 2003/01/06 13:11:21 taku-ku Exp $;
taku@chasen.org