{"id":2516,"date":"2026-02-02T09:45:34","date_gmt":"2026-02-02T09:45:34","guid":{"rendered":"https:\/\/demo.materiamedica.net\/demo6\/?p=2516"},"modified":"2026-02-02T09:45:34","modified_gmt":"2026-02-02T09:45:34","slug":"chapter-10-multinomial-distribution","status":"publish","type":"post","link":"https:\/\/demo.materiamedica.net\/demo6\/chapter-10-multinomial-distribution\/","title":{"rendered":"Chapter 10: Multinomial Distribution"},"content":{"rendered":"<h3 dir=\"auto\">1. What is the Multinomial distribution really?<\/h3>\n<p dir=\"auto\">The <strong>multinomial distribution<\/strong> is the <strong>generalization of the binomial distribution<\/strong> to <strong>more than two categories<\/strong>.<\/p>\n<ul dir=\"auto\">\n<li>Binomial = <strong>2 outcomes<\/strong> (success\/failure, heads\/tails, yes\/no)<\/li>\n<li>Multinomial = <strong>k outcomes<\/strong> (k \u2265 2 categories)<\/li>\n<\/ul>\n<p dir=\"auto\">You have:<\/p>\n<ul dir=\"auto\">\n<li><strong>n<\/strong> independent trials \/ experiments \/ draws<\/li>\n<li><strong>k<\/strong> possible categories \/ outcomes \/ classes<\/li>\n<li><strong>p\u2081, p\u2082, &#8230;, p\u2096<\/strong> probabilities for each category (they sum to 1)<\/li>\n<li>Each trial must produce <strong>exactly one<\/strong> of the k categories<\/li>\n<\/ul>\n<p dir=\"auto\">The multinomial tells you the probability of getting a particular <strong>combination of counts<\/strong> across all categories.<\/p>\n<h3 dir=\"auto\">2. Classic real-world examples (these appear very often)<\/h3>\n<div>\n<div dir=\"auto\">\n<table dir=\"auto\">\n<thead>\n<tr>\n<th data-col-size=\"lg\">Situation<\/th>\n<th data-col-size=\"sm\">n (trials)<\/th>\n<th data-col-size=\"lg\">Categories (k)<\/th>\n<th data-col-size=\"md\">Probabilities p\u2081, p\u2082, \u2026<\/th>\n<th data-col-size=\"lg\">What we count<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td data-col-size=\"lg\">Rolling a 6-sided die 100 times<\/td>\n<td data-col-size=\"sm\">100<\/td>\n<td data-col-size=\"lg\">{1,2,3,4,5,6}<\/td>\n<td data-col-size=\"md\">each 1\/6<\/td>\n<td data-col-size=\"lg\">How many times each face appeared<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Customers choosing product categories<\/td>\n<td data-col-size=\"sm\">5000 purchases<\/td>\n<td data-col-size=\"lg\">{electronics, clothing, books, \u2026}<\/td>\n<td data-col-size=\"md\">different shares<\/td>\n<td data-col-size=\"lg\">How many purchases in each category<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Words in a document<\/td>\n<td data-col-size=\"sm\">800 words<\/td>\n<td data-col-size=\"lg\">vocabulary size (e.g. 5000)<\/td>\n<td data-col-size=\"md\">word probabilities<\/td>\n<td data-col-size=\"lg\">Word counts (bag-of-words)<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Image classification predictions<\/td>\n<td data-col-size=\"sm\">10000 images<\/td>\n<td data-col-size=\"lg\">{cat, dog, bird, car, \u2026}<\/td>\n<td data-col-size=\"md\">predicted probabilities<\/td>\n<td data-col-size=\"lg\">Predicted class counts<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">A\/B\/C test results<\/td>\n<td data-col-size=\"sm\">30000 visitors<\/td>\n<td data-col-size=\"lg\">{A, B, C}<\/td>\n<td data-col-size=\"md\">conversion rates<\/td>\n<td data-col-size=\"lg\">Number of conversions per variant<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Election votes<\/td>\n<td data-col-size=\"sm\">millions<\/td>\n<td data-col-size=\"lg\">{party A, B, C, \u2026}<\/td>\n<td data-col-size=\"md\">vote shares<\/td>\n<td data-col-size=\"lg\">Votes per party<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div><\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">3. The core idea with a small example<\/h3>\n<p dir=\"auto\">Imagine you have a biased 3-sided die with probabilities:<\/p>\n<ul dir=\"auto\">\n<li>Face A: 0.5<\/li>\n<li>Face B: 0.3<\/li>\n<li>Face C: 0.2<\/li>\n<\/ul>\n<p dir=\"auto\">You roll it <strong>n = 10<\/strong> times.<\/p>\n<p dir=\"auto\">Possible outcomes are all combinations where the counts add up to 10, e.g.:<\/p>\n<ul dir=\"auto\">\n<li>(A=6, B=3, C=1)<\/li>\n<li>(A=4, B=4, C=2)<\/li>\n<li>(A=10, B=0, C=0)<\/li>\n<li>etc.<\/li>\n<\/ul>\n<p dir=\"auto\">The multinomial gives the probability of each possible <strong>count vector<\/strong>.<\/p>\n<h3 dir=\"auto\">4. Generating multinomial data in NumPy<\/h3>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code># Classic 6-sided die rolled 1000 times\r\n# probabilities: all faces equally likely\r\np = [1\/6] * 6\r\nrolls = np.random.multinomial(n=1000, pvals=p)\r\n\r\nprint(\"Counts for faces 1 to 6:\", rolls)\r\nprint(\"Sum (should be n):\", rolls.sum())<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Multiple independent experiments at once<\/strong> (very common)<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code># 20,000 simulated documents, each with 300 words\r\n# Simplified 5-word vocabulary\r\np_vocab = [0.35, 0.25, 0.20, 0.12, 0.08]\r\nword_counts = np.random.multinomial(n=300, pvals=p_vocab, size=20000)\r\n\r\nprint(\"Shape:\", word_counts.shape)               # (20000, 5)\r\nprint(\"First document word counts:\", word_counts[0])\r\nprint(\"Average count per word:\", word_counts.mean(axis=0).round(1))<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">5. Visualizing multinomial counts (very important)<\/h3>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code># Simulate many rolls of a biased 4-sided die\r\np = [0.4, 0.3, 0.2, 0.1]\r\nn_trials = 500\r\nn_simulations = 30000\r\n\r\ncounts = np.random.multinomial(n_trials, p, size=n_simulations)\r\n\r\nfig, axes = plt.subplots(2, 2, figsize=(14, 9))\r\n\r\nfor i, ax in enumerate(axes.flat):\r\n    sns.histplot(counts[:, i], bins=range(0, n_trials+5, 5),\r\n                 stat=\"probability\", color=sns.color_palette()[i],\r\n                 discrete=True, alpha=0.8, ax=ax)\r\n    \r\n    ax.set_title(f\"Category {i+1} (p = {p[i]})\", fontsize=13)\r\n    ax.set_xlabel(\"Number of occurrences\")\r\n    ax.set_ylabel(\"Probability\")\r\n\r\n    # Theoretical mean &amp; std\r\n    mean = n_trials * p[i]\r\n    std = np.sqrt(n_trials * p[i] * (1 - p[i]))\r\n    ax.axvline(mean, color='darkred', linestyle='--', lw=1.8, label=f\"mean = {mean:.1f}\")\r\n    ax.legend()\r\n\r\nplt.suptitle(f\"Multinomial counts after {n_trials} trials (30,000 simulations)\", fontsize=15, y=1.02)\r\nplt.tight_layout()\r\nplt.show()<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>What you should observe<\/strong>:<\/p>\n<ul dir=\"auto\">\n<li>Higher p \u2192 distribution centered farther to the right<\/li>\n<li>Lower p \u2192 distribution squeezed near zero, more skewed<\/li>\n<li>Variance = n \u00d7 p \u00d7 (1-p) \u2192 maximum when p=0.5<\/li>\n<\/ul>\n<h3 dir=\"auto\">6. Realistic code patterns you will actually use<\/h3>\n<p dir=\"auto\"><strong>Pattern 1 \u2013 Simulating A\/B\/C test results<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>n_visitors = 25000\r\np = [0.032, 0.038, 0.035]           # conversion rates A, B, C\r\n\r\nconversions = np.random.multinomial(n_visitors, p)\r\n\r\nprint(\"Visitors:\", n_visitors)\r\nprint(\"Conversions:\", conversions)\r\nprint(\"Conversion rates:\", (conversions \/ n_visitors * 100).round(2), \"%\")<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Pattern 2 \u2013 Simulating bag-of-words \/ topic proportions<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code># 4 topics with different probabilities\r\ntopic_probs = [0.45, 0.25, 0.18, 0.12]\r\nwords_per_doc = 400\r\n\r\n# 1000 documents\r\ndoc_topic_counts = np.random.multinomial(words_per_doc, topic_probs, size=1000)\r\n\r\nprint(\"Average topic proportions:\", doc_topic_counts.mean(axis=0) \/ words_per_doc)<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Pattern 3 \u2013 Simulating class distribution in imbalanced classification<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>n_samples = 15000\r\nclass_probs = [0.65, 0.25, 0.08, 0.02]   # very imbalanced\r\n\r\nlabels = np.random.multinomial(1, class_probs, size=n_samples).argmax(axis=1)\r\n\r\nprint(\"Class distribution:\", np.bincount(labels))\r\nprint(\"Percentages:\", np.bincount(labels) \/ n_samples * 100)<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">Summary \u2013 Multinomial Distribution Quick Reference<\/h3>\n<div>\n<div dir=\"auto\">\n<table dir=\"auto\">\n<thead>\n<tr>\n<th data-col-size=\"lg\">Property<\/th>\n<th data-col-size=\"lg\">Value \/ Formula<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td data-col-size=\"lg\">Number of trials<\/td>\n<td data-col-size=\"lg\"><strong>n<\/strong> (fixed)<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Number of categories<\/td>\n<td data-col-size=\"lg\"><strong>k<\/strong> (\u2265 2)<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Probabilities<\/td>\n<td data-col-size=\"lg\"><strong>p\u2081 + p\u2082 + \u2026 + p\u2096 = 1<\/strong><\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Counts vector<\/td>\n<td data-col-size=\"lg\">(c\u2081, c\u2082, \u2026, c\u2096) where c\u2081 + \u2026 + c\u2096 = n<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Expected count for category i<\/td>\n<td data-col-size=\"lg\"><strong>n \u00d7 p\u1d62<\/strong><\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Variance for category i<\/td>\n<td data-col-size=\"lg\"><strong>n \u00d7 p\u1d62 \u00d7 (1 \u2212 p\u1d62)<\/strong><\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Covariance between i and j<\/td>\n<td data-col-size=\"lg\"><strong>\u2212n \u00d7 p\u1d62 \u00d7 p\u2c7c<\/strong> (negative!)<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">NumPy function<\/td>\n<td data-col-size=\"lg\">np.random.multinomial(n, pvals, size=&#8230;)<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">When n large &amp; p\u1d62 not extreme<\/td>\n<td data-col-size=\"lg\">Approximates normal (multivariate)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div><\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">Final teacher messages<\/h3>\n<ol dir=\"auto\">\n<li><strong>Whenever you are counting \u201chow many times each category appeared after n trials\u201d<\/strong> \u2192 think multinomial.<\/li>\n<li><strong>Multinomial is the multivariate version of binomial<\/strong>.<\/li>\n<li><strong>When you only care about one category vs everything else<\/strong> \u2192 you can collapse to binomial.<\/li>\n<li><strong>Multinomial + Dirichlet<\/strong> is the foundation of topic modeling (LDA).<\/li>\n<\/ol>\n<p dir=\"auto\">Would you like to continue with any of these next?<\/p>\n<ul dir=\"auto\">\n<li>Multinomial vs multinomial logistic regression<\/li>\n<li>Dirichlet-multinomial (topic modeling intuition)<\/li>\n<li>How multinomial becomes multivariate normal (large n)<\/li>\n<li>Realistic mini-project: simulate customer segments or A\/B\/C test<\/li>\n<li>Comparing multinomial to binomial &amp; Poisson<\/li>\n<\/ul>\n<p dir=\"auto\">Just tell me what you want to explore next! \ud83d\ude0a<\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. What is the Multinomial distribution really? The multinomial distribution is the generalization of the binomial distribution to more than two categories. Binomial = 2 outcomes (success\/failure, heads\/tails, yes\/no) Multinomial = k outcomes (k&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[75],"tags":[],"class_list":["post-2516","post","type-post","status-publish","format-standard","hentry","category-numpy"],"_links":{"self":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2516","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/comments?post=2516"}],"version-history":[{"count":1,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2516\/revisions"}],"predecessor-version":[{"id":2517,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2516\/revisions\/2517"}],"wp:attachment":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/media?parent=2516"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/categories?post=2516"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/tags?post=2516"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}