Before you begin
Start with no linguistics background. Lessons 1 and 3 can be done on paper; lesson 2 uses a text editor and Python 3.12 or later. The six invented sentences below are a teaching fixture, not observations of a real community. Basic Python loops help; the Python guide introduces them.
Working toward: Produce a small audit trail: a sampling question, transparent token rules, counts, context checks and a claim whose limits you can explain.
Validation: Exact Python examples and numeric answers checked in disposable fixtures on Python 3.12.14. No real-world corpus or AntConc installation analyzed. Source review: 14 September 2026. These lessons do not add corpus uploads to AUWEN.
Study in order. Attempt each exercise before opening its answer. These are published foundations; advanced stages remain planned.
1. Ask a question your sample can answer
Before this lesson: None. Outcome: distinguish a collection of texts from evidence for a specified population.
A corpus is a collection of language material assembled for analysis. The plural is corpora. Its usefulness depends on what was collected, what was left out and how the records can be traced. Metadata means information about each text: origin, date, genre and the unit being sampled.
Begin with a narrow question: in our six invented service messages, where does please appear? Do not begin with a claim about all English speakers. Each line below is a separate document. Keep IDs even if you reorder the texts. The genre labels describe an invented task; they are not evidence of how shops or travelers actually speak.
For a real project, define the target population first, such as public English notices at ten named stations during one month. Decide how stations and notices will be selected before searching for your favorite word. Preserve original text separately from cleaned copies; document reuse permission and remove personal data you do not need. Keep duplicate notices identifiable. Ten copies of one sign are not ten independent wording decisions.
AI can help propose a search or inspect code. Generated sentences still need to be labeled synthetic: they cannot demonstrate what real speakers said. A fluent summary cannot replace retrievable examples, source records and sampling decisions.
ID | group | text
A1 | request | Please send the map.
A2 | request | Please check the map.
A3 | request | Send the ticket please.
B1 | notice | The map is ready.
B2 | notice | The ticket is ready.
B3 | notice | Please wait here.What to expect
You have six documents, two groups of three, and four documents containing please. All are synthetic. This supports a statement about this fixture, with no estimate of English usage outside it.
Your turn
You collect 30 notices but 20 are exact copies of one template. Your question concerns different wording choices, not how often travelers encounter a notice. What should you retain, and what should you count? Write a four-field metadata record for A1.
Show answer and reasoning
Keep the originals and a duplicate-group marker; create a deduplicated analysis view for the wording question, retaining a record of what was excluded. Exposure frequency would be a different question and might legitimately count copies. A1: id=A1; group=request; provenance=AUWEN synthetic teaching fixture, 2026-09-14; text=Please send the map. For real data, add source location, collection date, sampling decision and reuse conditions. Genre alone is not provenance.
Watch for: A convenient internet collection is not automatically representative. Changing the sampling rule after seeing the result can favor your preferred answer.
Link to this lesson2. Make the counting rule explicit
Before this lesson: Lesson 1; save and run a Python file. Outcome: reproduce token, type and document counts.
A token is one occurrence under your chosen segmentation rule; a type is a distinct form. In 'the map the ticket', there are four tokens but three types. A lemma groups inflected forms under a dictionary headword; lowercasing does not perform lemmatization.
For this deliberately simple English fixture, a token is a run of ASCII letters after lowercasing. The regular expression [a-z]+ says one or more letters from a to z. It drops punctuation and splits contractions and hyphenated forms. That is a declared classroom rule, not a multilingual tokenizer. The same method would destroy many accented words and cannot segment Chinese appropriately.
The code keeps documents separate. Counter adds occurrences; set removes repeated forms when counting types. The last calculation asks how many documents contain please, a different measure from how often please occurs. A single document saying please ten times would raise occurrence frequency by ten but document frequency by one.
import re
from collections import Counter
texts = [
'Please send the map.',
'Please check the map.',
'Send the ticket please.',
'The map is ready.',
'The ticket is ready.',
'Please wait here.',
]
docs = [re.findall(r'[a-z]+', text.lower()) for text in texts]
counts = Counter(word for doc in docs for word in doc)
print('tokens', sum(counts.values()))
print('types', len(counts))
print('please', counts['please'])
print('documents', sum('please' in doc for doc in docs))
print('the', counts['the'])Run it
# Save as counts.py in a new practice folder.
python3 counts.pyWhat to expect
tokens 23; types 10; please 4; documents 4; the 5. There is no network request and no file modification in the program.
Your turn
Append 'Please please wait.' to texts. Predict all five outputs before running again. Then explain what our tokenizer does to café and don't.
Show answer and reasoning
tokens 26; types 10; please 6; documents 5; the 5. Three tokens were added. Each was already a type. The extra document has two please tokens but contributes only one to document frequency. The declared ASCII rule makes café into caf and don't into don plus t. Those are unsuitable results for many research questions. Choose and document a language-aware tokenizer before using real multilingual data.
Watch for: Do not silently change punctuation, capitalization or tokenization between datasets. Type counts also depend strongly on sample length; they are not a stand-alone vocabulary-skill score.
Link to this lesson3. Read context and compare rates
Before this lesson: Lessons 1–2. Outcome: connect a rate to its denominator and inspect every match.
A concordance displays occurrences with surrounding context. KWIC means key word in context. The code below prints at most two tokens on each side and retains a document number, so you can reopen the complete sentence. We do not let context cross a document boundary.
Normalization expresses an occurrence count relative to a corpus size. In group A, please occurs 3 times in 12 tokens: 250 per 1,000 tokens. In group B it occurs once in 11 tokens: about 90.91 per 1,000. Multiplication changes the reporting scale; it does not create another 1,000 observed words. Record the raw counts too.
Read each hit before explaining the difference. Our examples place please at the beginning in A1, A2 and B3, and at the end in A3. This is an observation about four occurrences selected by an author. It cannot establish a population preference, politeness ranking or statistical significance. Zero hits in another tiny sample would mean not observed, not impossible.
# Append to the unchanged counts.py from lesson 2.
for number, doc in enumerate(docs, 1):
for i, word in enumerate(doc):
if word == 'please':
left = ' '.join(doc[max(0, i-2):i])
right = ' '.join(doc[i+1:i+3])
print(number, left, '[please]', right)
for label, group in [('A', docs[:3]), ('B', docs[3:])]:
total = sum(len(doc) for doc in group)
hits = sum(doc.count('please') for doc in group)
rate = hits / total * 1000 if total else None
print(label, hits, total, round(rate, 2) if rate is not None else 'undefined')Run it
python3 counts.pyWhat to expect
After lesson 2's output, four concordance lines identify documents 1, 2, 3 and 6. The final lines read A 3 12 250.0 and B 1 11 90.91. Document 3 shows 'the ticket [please]' with no right context.
Your turn
A new corpus X has 10 hits in 2,000 tokens; Y has 8 in 1,000. Which has more raw hits, and which has the higher rate per 1,000? Write one warranted claim and one claim the data cannot support. What happens when the denominator is zero?
Show answer and reasoning
X has more raw hits. X: 10/2000 × 1000 = 5 per 1,000; Y: 8/1000 × 1000 = 8 per 1,000. Y has the higher observed rate under the same counting rule. Warranted: the observed normalized rate is higher in Y. Unwarranted: Y's authors are more polite. Genre, sampling, repeated authors and context are not controlled. A zero denominator makes the rate undefined; it is not a zero rate.
Watch for: A context window can hide negation or quotation. Inspect complete documents. A normalized difference alone supplies neither uncertainty estimates nor a causal explanation.
Link to this lessonNext stages
Evidence foundations
Three lessons published: sampling, counting and contextual comparison.
IN PROGRESSReal corpus workflow
Permissions and provenance, Unicode normalization, language-aware segmentation, concordance annotation and inter-annotator agreement.
PLANNEDIndependent research
Dispersion, collocation, uncertainty, matched comparisons and a reproducible small study.
PLANNEDAUWEN corpus tools
Corpus upload, storage, search and access controls remain planned.
PLANNED
References
Original AUWEN examples and exercises. Sources checked 14 September 2026.
Learning update log →