Learn how WordNet groups words into synsets, why one word can cover many senses, and where a curated lexical resource helps or fails.
A museum cataloguer labels a drawer bank and then hesitates. The drawer might hold river photographs, money records, or a toy building with a coin slot.
The label is a single string. The meaning depends on the sense attached to it.
A synset is a set of words that share one sense. WordNet is a hand-built lexical database that records those sets and links them to broader meanings such as hypernyms, the “is-a” parents in a hierarchy.
TipWhat you will learn
This lesson shows how to:
define a synset in plain language;
count senses for a word string;
compare a sense count with a simple chance baseline;
list synonyms inside one synset;
walk hypernym links up an is-a hierarchy; and
name what WordNet can and cannot support.
Load the WordNet extract
The lesson reads four local CSV files made from Open English WordNet 2024. No code downloads WordNet while the page renders. The metadata file records the source, licence, and SHA-256 fingerprints.
Size of the local WordNet extract used in this lesson
Item
Count
lemmas
38
senses
419
synsets
417
synset membership rows
1050
relations
2432
This slice covers 38 lemmas, not all of English. It is enough to show how a lexical database separates spelling from meaning.
Read the senses of one word
A sense is one listed meaning of a word. The string bank has 18 senses in this extract: 10 noun senses and 8 verb senses. The first noun senses split river land, finance, piles, rows, reserves, and gambling funds.
bank_senses <- senses |>filter(lemma =="bank") |>count(part_of_speech, name ="senses") |>arrange(part_of_speech)bank_noun_senses <- senses |>filter(lemma =="bank", part_of_speech =="noun") |>arrange(sense_order) |>left_join(synsets, by =c("synset_id", "part_of_speech")) |>slice_head(n =6) |>transmute(sense = sense_order, definition )lemma_sense_counts <- senses |>count(lemma, name ="sense_count")bank_sense_null <-permutation_null(observed =sum(senses$lemma =="bank"),replicate_fn =function() { lemma_sense_counts$sense_count[match(sample(lemma_sense_counts$lemma, 1L), lemma_sense_counts$lemma) ] },replicates =1000L,seed =5801L,alternative ="greater")kable( bank_noun_senses,col.names =c("Noun sense", "Definition"),caption ="The first six noun senses of bank in the local WordNet extract",row.names =FALSE)
The first six noun senses of bank in the local WordNet extract
Noun sense
Definition
1
sloping land (especially the slope beside a body of water)
2
a financial institution that accepts deposits and channels the money into lending activities
3
a long ridge or pile
4
an arrangement of similar objects in a row or in tiers
5
a supply or stock held in reserve for future use (especially in emergencies)
6
the funds held by a gambling house or the dealer in some gambling games
kable( bank_sense_null |>mutate(across(where(is.numeric), ~round(.x, 3))),col.names =c("Observed", "Null mean", "Null 5th pct", "Null 95th pct", "p-value", "Replicates", "Alternative"),caption ="Sense count for bank compared with random lemmas in the extract",row.names =FALSE)
Sense count for bank compared with random lemmas in the extract
Observed
Null mean
Null 5th pct
Null 95th pct
p-value
Replicates
Alternative
18
11.352
2
48
0.138
1000
greater
A word string is not a unit of meaning. If a search, model, or count treats every bank as the same thing, it has made a simplifying choice. The null table adds a second caution: this extract was built from ambiguous teaching examples, so 18 senses for bank is not unusual inside this small file.
Any lexical method will return an answer for a known word. The safer habit is to ask what answer appears after the target word is compared with other words drawn from the same source.
Look inside a synset
For the financial-institution sense, the synset contains four member lemmas. These are four names WordNet links to the same sense.
financial_bank_synset <- senses |>filter(lemma =="bank", part_of_speech =="noun", sense_order ==2L) |>pull(synset_id)financial_bank_members <- members |>filter(synset_id == financial_bank_synset) |>arrange(lemma) |>mutate(role =if_else(lemma =="bank", "queried word", "other member"))kable( financial_bank_members,col.names =c("Synset ID", "Lemma", "Role"),caption ="Members of the financial-institution synset for bank",row.names =FALSE)
Members of the financial-institution synset for bank
Synset ID
Lemma
Role
oewn-08437235-n
bank
queried word
oewn-08437235-n
banking company
other member
oewn-08437235-n
banking concern
other member
oewn-08437235-n
depository financial institution
other member
Synonymy here is local to one sense. bank and banking company share the finance sense; river bank belongs elsewhere.
Walk an is-a chain
A hypernym says that one meaning is a kind of another meaning. In this extract, the professor-position sense of chair walks upward through a position synset, then through a work synset, then to activity.
the principal activity in your life that you do to earn money
3
oewn-00408356-n
activity
any specific behavior
The walk assumes this extract contains the chosen chair sense and three hypernym links above it. The functions stop when that assumption is false, so a missing lemma cannot produce a half-empty path that looks valid.
The hierarchy is useful for broadening a search. A reader looking for occupations might want chair, office, and job to meet at a broader node. The same hierarchy can be too coarse for a task that needs the academic rank, the furniture sense, or a named committee role.
Keep the limits attached
WordNet is a curated snapshot with a version and a licence. It is not a direct measurement of English. It covers much common vocabulary, while domain terms, slang, new coinages, and local uses can be missing.
Sense inventories also draw boundaries. A fine split that helps one annotation task can be too fine for another, so a WordNet sense should be treated as a chosen inventory entry rather than a final answer about meaning.
WordNet is still good for teaching the difference between words and meanings, expanding a controlled search, checking whether two labels share a listed sense, and building small rule-based features where coverage can be inspected.