# Reading the Signals Behind an Anonymous Profile

How a Bayesian model reads public Facebook posts to estimate the odds an account belongs to a senior Republican man.

*2026-10-22 · Scott Isaacson*


![Techne Path](https://t3.storage.dev/morning-wood-5868/technepath/assets/techne-path-logo.png) From systems to signals. 

A Field Guide · Decision Dashboards

# Reading the signals behind an anonymous profile

Given nothing but a public trail of Facebook posts and comments, how confidently can you guess that the person behind the account is a man over 65 who votes Republican? This is how we would build that estimate, step by step, with a Bayesian scoring model and a healthy respect for how often it will be wrong.

5.2%

Starting base rate

Share of active U.S. Facebook accounts matching all three traits, before reading a single post.

9

Signal families scored

Vocabulary, timing, style, and sharing habits, each converted into evidence.

82%

Example posterior

The model's confidence after one fully loaded account runs through every signal.

01 

## State the Question Precisely

Most profiling efforts fail before any math happens, because the question is vague. Ours is not. We want one number: the probability that a single anonymous account belongs to a man, aged 65 or older, who identifies as or consistently leans Republican, conditional on everything the account has publicly written and shared.

P( 65+ ∩ Male ∩ Republican | post history ) 

That is a _joint_ probability, and it matters. The three traits are not independent: older men are more likely than the general population to lean Republican, and older Republicans on Facebook skew male. If we scored each trait separately and multiplied the results, we would understate the overlap and get the wrong answer.

So the model works in two passes. First it estimates each trait on its own, which tells you _where_ the evidence is coming from. Then it scores the combined persona as a single class against everyone else, which is the number you actually act on.

### Pass One: Each Trait on Its Own

Here is the worked example account after pass one. Every margin is high, but no single trait carries the answer alone.

Age 65 or older

91%

Male

86%

Republican leaning

84%

Illustrative output. Multiplying the margins gives 65 percent, which understates the joint estimate of 82 percent. The gap is exactly the correlation the two-pass design exists to catch.

02 

## The Engine Is Bayes' Theorem

The whole model is one idea applied patiently: start with what you knew before the evidence, then update it every time the account does something informative. Nothing more exotic than that.

Prior

5.2 percent of accounts fit the persona before we read anything

+

Evidence

Each observed signal adds or subtracts log-odds

\=

Posterior

The updated probability, converted back from log-odds

Formally, Bayes' theorem says the posterior odds equal the prior odds times the likelihood ratio of the evidence:

P(persona | evidence)P(not persona | evidence)\= P(persona)P(not persona)× P(evidence | persona)P(evidence | not persona) 

Multiplying ratios is clumsy, so we work in logarithms, where multiplication becomes addition. The model is then just a running total. Every signal the account exhibits adds its weight; every expected signal that is missing subtracts. This is the naive Bayes assumption: treat the signals as if they were independent given the class, accept that they are not perfectly so, and correct for the resulting overconfidence during calibration.

log-odds(persona | evidence) = log-odds(persona) + Σ log LRi 

Convert back with the logistic function: probability = 1 / (1 + e−log-odds)

**Why log-odds and not raw percentages.** A percentage cannot show you its work. Log-odds can. Each signal's contribution stays visible as a number you can audit, challenge, and defend, which is the difference between a model you can explain and a score you have to take on faith.

03 

## What Counts as Evidence

A signal is anything an account does that is more common among 65-plus Republican men than among everyone else. The weight below each one is its log-likelihood ratio: how much it moves the running total when present. Weights are learned from a labeled training set of accounts whose owners' traits are known, then frozen before the model ever touches a new account.

Signal Weights, Worked Example Model

Log-likelihood ratio added when the signal is present. A weight of 0.80 roughly doubles the odds on its own.

Evidence weight (log LR) 

Three things are worth noticing. First, no single signal is decisive. Even the strongest one only shifts the total by a fraction of what is needed. Second, the signals are mundane: what time you post, how you punctuate, what you share. Demographics leak through habits, not through confessions. Third, every weight can go negative. An account that never mentions family, never posts before noon, and shares no political content is actively scoring _against_ the persona.

**Where the weights come from.** Take a labeled sample of accounts, count how often each signal appears in the persona group versus everyone else, and divide. A phrase used by 12 percent of persona accounts and 3 percent of others has a likelihood ratio of 4, which becomes a weight of about 1.39 in log space. That is the entire training process.

04 

## Watch the Estimate Move

This is the part most explainers skip. Toggle the signals below and the model reruns in front of you: the running log-odds total, the waterfall of contributions, and the final probability all update together. Start with everything on, then take evidence away and watch the estimate fall back toward the base rate.

Interactive Scoring Console Toggle signals to rerun the model 

82%

Posterior probability

Log-Odds Waterfall

From the prior on the left to the posterior on the right. Each bar is one signal's contribution to the running total.

Prior Signal contribution Posterior 

The prior is fixed at 5.2 percent, a log-odds of −2.90\. Weights are illustrative, sized to the training patterns described above. Turn everything off and the model correctly returns to the base rate, because with no evidence there is nothing to update.

05 

## How Wrong It Can Be

A model you cannot distrust is a model you should not use. Two failure modes matter here, and both are arithmetic, not bad intentions.

### Failure One: The Base Rate Fights Back

Even a good model drowns in false positives when the thing it hunts is rare. Picture 100 random accounts. About 5 fit the persona. The model catches 9 of every 10 true matches but still wrongly flags 5 of every 95 others. The result: it flags 9 or 10 accounts, and roughly half of them are innocent of the label.

100 Random Accounts, Rounded Counts

A 90 percent sensitivity model with a 5 percent false-positive rate, applied to a 5 percent base-rate population.

True match, correctly flagged (5) False alarm, wrongly flagged (5) Everyone else (90) 

Precision lands near 50 percent. Raise the flagging threshold to cut false alarms and you start missing true matches. That trade is not a bug to fix. It is the cost of looking for something rare.

### Failure Two: The Curve Is Not the Person

The ROC curve below summarizes every threshold the model could use. An area under the curve of 0.93 looks strong on paper, and it is, for ranking a population. But the curve describes the model's average behavior across millions of accounts. It says nothing certain about the single account in front of you, which could be a 40-year-old libertarian woman who types in all caps and loves her grandchildren.

Model Performance, Held-Out Test Set

True-positive rate against false-positive rate as the flagging threshold sweeps from strict to loose.

Operating point: 90% caught, 5% false alarms Chance line (AUC 0.50) Model AUC 0.93 False-positive rate True-positive rate 0.00.250.500.751.0 0.00.250.500.751.0 

### And One Rule Above the Math

An estimate like this is a statistical statement about patterns, never a fact about a person. Public posts are not consent to be profiled, platform terms restrict this kind of inference, and political affiliation is a sensitive attribute in many jurisdictions. We build models like this to measure audiences in aggregate, with consent and disclosure, not to tag individuals. If your use case needs a name attached to a score, that is the point to stop and redesign the question.

* **Calibrate before you trust.** Run the model on accounts with known outcomes and confirm that its 80 percents are right about 80 percent of the time.
* **Report ranges, not points.** An honest output is "70 to 90 percent," never a bare "82 percent."
* **Retire stale weights.** Language and habits drift. Weights learned last year describe last year's users.
* **Keep a human veto.** Any downstream action that matters should require a person to look at the evidence first.

Authored by Scott Isaacson.

![Techne Path](https://t3.storage.dev/morning-wood-5868/technepath/assets/techne-path-logo-reverse.png) 

Your data already knows the answer. We build the dataset that lets you ask.

Techne Path designs the datasets, dashboards, and machine-readable workflows behind decisions like this one: documented definitions, auditable models, and numbers you can defend in the room where they get used.

[Work with us](https://technepath.com) 

Techne Path · technepath.com Methods Note · Illustrative model, not a measurement of any real person
