Unsurprisingly, this method performs rather poorly. On a typical corpus, it will tag
only about an eighth of the tokens correctly, as we see here:
>>> default_tagger.evaluate(brown_tagged_sents)
0.13089484257215028
Default taggers assign their tag to every single word, even words that have never been
encountered before. As it happens, once we have processed several thousand words of
English text, most new words will be nouns. As we will see, this means that default
taggers can help to improve the robustness of a language processing system. We will
return to them shortly.
The Regular Expression Tagger
The regular expression tagger assigns tags to tokens on the basis of matching patterns.
For instance, we might guess that any word ending in ed is the past participle of a verb,
and any word ending with ’s is a possessive noun. We can express these as a list of
regular expressions:
>>> patterns = [
...     (r'.*ing$', 'VBG'),               # gerunds
...     (r'.*ed$', 'VBD'),                # simple past
...     (r'.*ould$', 'MD'),               # modals
...     (r'.*s$', 'NNS'),                 # plural nouns
... ]
Note that these are processed in order, and the first one that matches is applied. Now
we can set up a tagger and use it to tag a sentence. After this step, it is correct about a
fifth of the time.
>>> regexp_tagger = nltk.RegexpTagger(patterns)
>>> regexp_tagger.tag(brown_sents[3])
>>> regexp_tagger.evaluate(brown_tagged_sents)
0.20326391789486245
The final regular expression «
.*
» is a catch-all that tags everything as a noun. This is
equivalent to the default tagger (only much less efficient). Instead of respecifying this
as part of the regular expression tagger, is there a way to combine this tagger with the
default tagger? We will see how to do this shortly.
5.4  Automatic Tagging g | 199
Asp.net merge pdf files - Merge, append PDF files in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Provide C# Demo Codes for Merging and Appending PDF Document
add pdf files together online; attach pdf to mail merge in word
Asp.net merge pdf files - VB.NET PDF File Merge Library: Merge, append PDF files in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
VB.NET Guide and Sample Codes to Merge PDF Documents in .NET Project
pdf merge files; batch pdf merger
Your Turn: See if you can come up with patterns to improve the per-
formance of the regular expression tagger just shown. (Note that Sec-
tion 6.1 describes a way to partially automate such work.)
The Lookup Tagger
A lot of high-frequency words do not have the 
NN
tag. Let’s find the hundred most
frequent words and store their most likely tag. We can then use this information as the
model for a “lookup tagger” (an NLTK 
UnigramTagger
):
>>> fd = nltk.FreqDist(brown.words(categories='news'))
>>> most_freq_words = fd.keys()[:100]
>>> baseline_tagger = nltk.UnigramTagger(model=likely_tags)
>>> baseline_tagger.evaluate(brown_tagged_sents)
0.45578495136941344
It should come as no surprise by now that simply knowing the tags for the 100 most
frequent words enables us to tag a large fraction of tokens correctly (nearly half, in fact).
Let’s see what it does on some untagged input text:
>>> sent = brown.sents(categories='news')[3]
>>> baseline_tagger.tag(sent)
Many words have been assigned a tag of 
None
, because they were not among the 100
most frequent words. In these cases we would like to assign the default tag of 
NN
. In
other words, we want to use the lookup table first, and if it is unable to assign a tag,
then use the default tagger, a process known as backoff (Section 5.5). We do this by
specifying one tagger as a parameter to the other, as shown next. Now the lookup tagger
will only store word-tag pairs for words other than nouns, and whenever it cannot
assign a tag to a word, it will invoke the default tagger.
>>> baseline_tagger = nltk.UnigramTagger(model=likely_tags,
Let’s put all this together and write a program to create and evaluate lookup taggers
having a range of sizes (Example 5-4).
200 | | Chapter 5: Categorizing and Tagging Words
VB.NET PDF- HTML5 PDF Viewer for VB.NET Project
PDF; Merge PDF Files; Split PDF Document; Remove Password from PDF; Change PDF Permission Settings. FREE TRIAL: HOW TO: XDoc.HTML5 Viewer for C#▶: C# ASP.NET:
combine pdfs online; reader merge pdf
Online Merge PDF files. Best free online merge PDF tool.
Thus, C#.NET PDF document merge library control can Download and try RasterEdge.XDoc. PDF for .NET and imaging solutions, available for ASP.NET AJAX, Silverlight
c# merge pdf files; c# merge pdf files into one
Example 5-4. Lookup tagger performance with varying model size.
def performance(cfd, wordlist):
lt = dict((word, cfd[word].max()) for word in wordlist)
def display():
import pylab
sizes = 2 ** pylab.arange(15)
perfs = [performance(cfd, words_by_freq[:size]) for size in sizes]
pylab.plot(sizes, perfs, '-bo')
pylab.xlabel('Model Size')
pylab.ylabel('Performance')
pylab.show()
>>> display()                                  
Observe in Figure 5-4 that performance initially increases rapidly as the model size
grows, eventually reaching a plateau, when large increases in model size yield little
improvement in performance. (This example used the 
pylab
plotting package, dis-
cussed in Section 4.8.)
Evaluation
In the previous examples, you will have noticed an emphasis on accuracy scores. In
fact, evaluating the performance of such tools is a central theme in NLP. Recall the
processing pipeline in Figure 1-5; any errors in the output of one module are greatly
multiplied in the downstream modules.
We evaluate the performance of a tagger relative to the tags a human expert would
assign. Since we usually don’t have access to an expert and impartial human judge, we
make do instead with gold standard test data. This is a corpus which has been man-
ually annotated and accepted as a standard against which the guesses of an automatic
system are assessed. The tagger is regarded as being correct if the tag it guesses for a
given word is the same as the gold standard tag.
Of course, the humans who designed and carried out the original gold standard anno-
tation were only human. Further analysis might show mistakes in the gold standard,
or may eventually lead to a revised tagset and more elaborate guidelines. Nevertheless,
the gold standard is by definition “correct” as far as the evaluation of an automatic
tagger is concerned.
5.4  Automatic Tagging g | 201
VB.NET PDF Convert to HTML SDK: Convert PDF to html files in vb.
Embed converted html files in html page or iframe. Export PDF form data to html form in .NET WinForms and ASP.NET. Turn PDF images to HTML images in VB.NET.
c# combine pdf; add pdf files together
C# HTML5 PDF Viewer SDK to view PDF document online in C#.NET
PDF; Merge PDF Files; Split PDF Document; Remove Password from PDF; Change PDF Permission Settings. FREE TRIAL: HOW TO: XDoc.HTML5 Viewer for C#▶: C# ASP.NET:
combine pdf online; acrobat merge pdf files
Developing an annotated corpus is a major undertaking. Apart from the
data, it generates sophisticated tools, documentation, and practices for
ensuring high-quality annotation. The tagsets and other coding schemes
inevitably depend on some theoretical position that is not shared by all.
However, corpus creators often go to great lengths to make their work
as theory-neutral as possible in order to maximize the usefulness of their
work. We will discuss the challenges of creating a corpus in Chapter 11.
5.5  N-Gram Tagging
Unigram Tagging
Unigram taggers are based on a simple statistical algorithm: for each token, assign the
tag that is most likely for that particular token. For example, it will assign the tag 
JJ
to
any occurrence of the word frequent, since frequent is used as an adjective (e.g., a fre-
quent word) more often than it is used as a verb (e.g., I frequent this cafe). A unigram
tagger behaves just like a lookup tagger (Section 5.4), except there is a more convenient
Figure 5-4. Lookup tagger
202 | | Chapter 5: Categorizing and Tagging Words
VB.NET PDF File Split Library: Split, seperate PDF into multiple
Split PDF file into two or multiple files in ASP.NET webpage online. Support to break a large PDF file into smaller files in .NET WinForms.
append pdf; pdf combine pages
C# HTML5 Viewer: Load, View, Convert, Annotate and Edit PDF
HTML5 Viewer for C# .NET. Related Resources. To view, convert, edit, process, protect, sign PDF files, please refer to XDoc.PDF SDK for .NET overview.
acrobat combine pdf; acrobat combine pdf files
technique for setting it up, called training. In the following code sample, we train a
unigram tagger, use it to tag a sentence, and then evaluate:
>>> from nltk.corpus import brown
>>> brown_tagged_sents = brown.tagged_sents(categories='news')
>>> brown_sents = brown.sents(categories='news')
>>> unigram_tagger = nltk.UnigramTagger(brown_tagged_sents)
>>> unigram_tagger.tag(brown_sents[2007])
('direct', 'JJ'), ('.', '.')]
>>> unigram_tagger.evaluate(brown_tagged_sents)
0.9349006503968017
We train a 
UnigramTagger
by specifying tagged sentence data as a parameter when we
initialize the tagger. The training process involves inspecting the tag of each word and
storing the most likely tag for any word in a dictionary that is stored inside the tagger.
Separating the Training and Testing Data
Now that we are training a tagger on some data, we must be careful not to test it on
the same data, as we did in the previous example. A tagger that simply memorized its
training data and made no attempt to construct a general model would get a perfect
score, but would be useless for tagging new text. Instead, we should split the data,
training on 90% and testing on the remaining 10%:
>>> size = int(len(brown_tagged_sents) * 0.9)
>>> size
4160
>>> train_sents = brown_tagged_sents[:size]
>>> test_sents = brown_tagged_sents[size:]
>>> unigram_tagger = nltk.UnigramTagger(train_sents)
>>> unigram_tagger.evaluate(test_sents)
0.81202033290142528
Although the score is worse, we now have a better picture of the usefulness of this
tagger, i.e., its performance on previously unseen text.
General N-Gram Tagging
When we perform a language processing task based on unigrams, we are using one
item of context. In the case of tagging, we consider only the current token, in isolation
from any larger context. Given such a model, the best we can do is tag each word with
its a priori most likely tag. This means we would tag a word such as wind with the same
tag, regardless of whether it appears in the context the wind or to wind.
An n-gram tagger is a generalization of a unigram tagger whose context is the current
word together with the part-of-speech tags of the n-1 preceding tokens, as shown in
Figure 5-5. The tag to be chosen, t
n
, is circled, and the context is shaded in grey. In the
example of an n-gram tagger shown in Figure 5-5, we have n=3; that is, we consider
5.5  N-Gram Tagging g | 203
VB.NET Create PDF from Word Library to convert docx, doc to PDF in
PDF; Merge PDF Files; Split PDF Document; Remove Password from PDF; Change PDF Permission Settings. FREE TRIAL: HOW TO: XDoc.HTML5 Viewer for C#▶: C# ASP.NET:
pdf split and merge; pdf combine two pages into one
C# PDF Convert to SVG SDK: Convert PDF to SVG files in C#.net, ASP
Instantly convert all PDF document pages to SVG image files in C#.NET class application. Perform high-fidelity PDF to SVG conversion in both ASP.NET web and
add multiple pdf files into one online; c# merge pdf pages
the tags of the two preceding words in addition to the current word. An n-gram tagger
picks the tag that is most likely in the given context.
A 1-gram tagger is another term for a unigram tagger: i.e., the context
used to tag a token is just the text of the token itself. 2-gram taggers are
also called bigram taggers, and 3-gram taggers are called trigram taggers.
The 
NgramTagger
class uses a tagged training corpus to determine which part-of-speech
tag is most likely for each context. Here we see a special case of an n-gram tagger,
namely a bigram tagger. First we train it, then use it to tag untagged sentences:
>>> bigram_tagger = nltk.BigramTagger(train_sents)
>>> bigram_tagger.tag(brown_sents[2007])
>>> unseen_sent = brown_sents[4203]
>>> bigram_tagger.tag(unseen_sent)
Notice that the bigram tagger manages to tag every word in a sentence it saw during
training, but does badly on an unseen sentence. As soon as it encounters a new word
(i.e., 13.5), it is unable to assign a tag. It cannot tag the following word (i.e., million),
even if it was seen during training, simply because it never saw it during training with
None
tag on the previous word. Consequently, the tagger fails to tag the rest of the
sentence. Its overall accuracy score is very low:
>>> bigram_tagger.evaluate(test_sents)
0.10276088906608193
Figure 5-5. Tagger context.
204 | | Chapter 5: Categorizing and Tagging Words
As n gets larger, the specificity of the contexts increases, as does the chance that the
data we wish to tag contains contexts that were not present in the training data. This
is known as the sparse data problem, and is quite pervasive in NLP. As a consequence,
there is a trade-off between the accuracy and the coverage of our results (and this is
related to the precision/recall trade-off in information retrieval).
Caution!
N-gram taggers should not consider context that crosses a sentence
boundary. Accordingly, NLTK taggers are designed to work with lists
of sentences, where each sentence is a list of words. At the start of a
sentence, t
n-1
and preceding tags are set to 
None
.
Combining Taggers
One way to address the trade-off between accuracy and coverage is to use the more
accurate algorithms when we can, but to fall back on algorithms with wider coverage
when necessary. For example, we could combine the results of a bigram tagger, a
unigram tagger, and a default tagger, as follows:
1.Try tagging the token with the bigram tagger.
2.If the bigram tagger is unable to find a tag for the token, try the unigram tagger.
3.If the unigram tagger is also unable to find a tag, use a default tagger.
Most NLTK taggers permit a backoff tagger to be specified. The backoff tagger may
itself have a backoff tagger:
>>> t0 = nltk.DefaultTagger('NN')
>>> t1 = nltk.UnigramTagger(train_sents, backoff=t0)
>>> t2 = nltk.BigramTagger(train_sents, backoff=t1)
>>> t2.evaluate(test_sents)
0.84491179108940495
Your Turn: Extend the preceding example by defining a 
TrigramTag
ger
called 
t3
, which backs off to 
t2
.
Note that we specify the backoff tagger when the tagger is initialized so that training
can take advantage of the backoff tagger. Thus, if the bigram tagger would assign the
same tag as its unigram backoff tagger in a certain context, the bigram tagger discards
the training instance. This keeps the bigram tagger model as small as possible. We can
further specify that a tagger needs to see more than one instance of a context in order
to retain it. For example, 
nltk.BigramTagger(sents, cutoff=2, backoff=t1)
will dis-
card contexts that have only been seen once or twice.
5.5  N-Gram Tagging g | 205
Tagging Unknown Words
Our approach to tagging unknown words still uses backoff to a regular expression
tagger or a default tagger. These are unable to make use of context. Thus, if our tagger
encountered the word blog, not seen during training, it would assign it the same tag,
regardless of whether this word appeared in the context the blog or to blog. How can
we do better with these unknown words, or out-of-vocabulary items?
A useful method to tag unknown words based on context is to limit the vocabulary of
a tagger to the most frequent n words, and to replace every other word with a special
word UNK using the method shown in Section 5.3. During training, a unigram tagger
will probably learn that UNK is usually a noun. However, the n-gram taggers will detect
contexts in which it has some other tag. For example, if the preceding word is to (tagged
TO
), then UNK will probably be tagged as a verb.
Storing Taggers
Training a tagger on a large corpus may take a significant time. Instead of training a
tagger every time we need one, it is convenient to save a trained tagger in a file for later
reuse. Let’s save our tagger 
t2
to a file t2.pkl:
>>> from cPickle import dump
>>> output = open('t2.pkl', 'wb')
>>> dump(t2, output, -1)
>>> output.close()
Now, in a separate Python process, we can load our saved tagger:
>>> from cPickle import load
>>> input = open('t2.pkl', 'rb')
>>> tagger = load(input)
>>> input.close()
Now let’s check that it can be used for tagging:
>>> text = """The board's action shows what free enterprise
...     is up against in our complex maze of regulatory laws ."""
>>> tokens = text.split()
>>> tagger.tag(tokens)
Performance Limitations
What is the upper limit to the performance of an n-gram tagger? Consider the case of
a trigram tagger. How many cases of part-of-speech ambiguity does it encounter? We
can determine the answer to this question empirically:
206 | | Chapter 5: Categorizing and Tagging Words
>>> cfd = nltk.ConditionalFreqDist(
...            ((x[1], y[1], z[0]), z[1])
...            for sent in brown_tagged_sents
...            for x, y, z in nltk.trigrams(sent))
>>> sum(cfd[c].N() for c in ambiguous_contexts) / cfd.N()
0.049297702068029296
Thus, 1 out of 20 trigrams is ambiguous. Given the current word and the previous two
tags, in 5% of cases there is more than one tag that could be legitimately assigned to
the current word according to the training data. Assuming we always pick the most
likely tag in such ambiguous contexts, we can derive a lower bound on the performance
of a trigram tagger.
Another way to investigate the performance of a tagger is to study its mistakes. Some
tags may be harder than others to assign, and it might be possible to treat them specially
by pre- or post-processing the data. A convenient way to look at tagging errors is the
confusion matrix. It charts expected tags (the gold standard) against actual tags gen-
erated by a tagger:
...                  for (word, tag) in t2.tag(sent)]
>>> print nltk.ConfusionMatrix(gold, test)                
Based on such analysis we may decide to modify the tagset. Perhaps a distinction be-
tween tags that is difficult to make can be dropped, since it is not important in the
context of some larger processing task.
Another way to analyze the performance bound on a tagger comes from the less than
100% agreement between human annotators.
In general, observe that the tagging process collapses distinctions: e.g., lexical identity
is usually lost when all personal pronouns are tagged 
PRP
. At the same time, the tagging
process introduces new distinctions and removes ambiguities: e.g., deal tagged as 
VB
or
NN
. This characteristic of collapsing certain distinctions and introducing new distinc-
tions is an important feature of tagging which facilitates classification and prediction.
When we introduce finer distinctions in a tagset, an n-gram tagger gets more detailed
information about the left-context when it is deciding what tag to assign to a particular
word. However, the tagger simultaneously has to do more work to classify the current
token, simply because there are more tags to choose from. Conversely, with fewer dis-
tinctions (as with the simplified tagset), the tagger has less information about context,
and it has a smaller range of choices in classifying the current token.
We have seen that ambiguity in the training data leads to an upper limit in tagger
performance. Sometimes more context will resolve the ambiguity. In other cases, how-
ever, as noted by (Abney, 1996), the ambiguity can be resolved only with reference to
syntax or to world knowledge. Despite these imperfections, part-of-speech tagging has
played a central role in the rise of statistical approaches to natural language processing.
In the early 1990s, the surprising accuracy of statistical taggers was a striking
5.5  N-Gram Tagging g | 207
demonstration that it was possible to solve one small part of the language understand-
ing problem, namely part-of-speech disambiguation, without reference to deeper sour-
ces of linguistic knowledge. Can this idea be pushed further? In Chapter 7, we will see
that it can.
Tagging Across Sentence Boundaries
An n-gram tagger uses recent tags to guide the choice of tag for the current word. When
tagging the first word of a sentence, a trigram tagger will be using the part-of-speech
tag of the previous two tokens, which will normally be the last word of the previous
sentence and the sentence-ending punctuation. However, the lexical category that
closed the previous sentence has no bearing on the one that begins the next sentence.
To deal with this situation, we can train, run, and evaluate taggers using lists of tagged
sentences, as shown in Example 5-5.
Example 5-5. N-gram tagging at the sentence level.
brown_tagged_sents = brown.tagged_sents(categories='news')
brown_sents = brown.sents(categories='news')
size = int(len(brown_tagged_sents) * 0.9)
train_sents = brown_tagged_sents[:size]
test_sents = brown_tagged_sents[size:]
t0 = nltk.DefaultTagger('NN')
t1 = nltk.UnigramTagger(train_sents, backoff=t0)
t2 = nltk.BigramTagger(train_sents, backoff=t1)
>>> t2.evaluate(test_sents)
0.84491179108940495
5.6  Transformation-Based Tagging
A potential issue with n-gram taggers is the size of their n-gram table (or language
model). If tagging is to be employed in a variety of language technologies deployed on
mobile computing devices, it is important to strike a balance between model size and
tagger performance. An n-gram tagger with backoff may store trigram and bigram ta-
bles, which are large, sparse arrays that may have hundreds of millions of entries.
A second issue concerns context. The only information an n-gram tagger considers
from prior context is tags, even though words themselves might be a useful source of
information. It is simply impractical for n-gram models to be conditioned on the iden-
tities of words in the context. In this section, we examine Brill tagging, an inductive
tagging method which performs very well using models that are only a tiny fraction of
the size of n-gram taggers.
Brill tagging is a kind of transformation-based learning, named after its inventor. The
general idea is very simple: guess the tag of each word, then go back and fix the mistakes.
208 | | Chapter 5: Categorizing and Tagging Words
Documents you may be interested
Documents you may be interested