AI-powered behavioural profiling

A behavioural profiling system turns posts into measurable features: the times of posting, the topics that recur, the emotional register held over weeks, the vocabulary, the rhythm. A model trained on those features does not need to understand what somebody means in the way a reader does. It learns statistical regularities in what they produce and assigns them a category on that basis.

Scored, clustered, labelled

The process has two stages. The first assigns a sentiment value to each post: a numerical score reflecting how positive or negative the content is. The second converts the words into vectors and groups similar vectors into clusters, each cluster representing a behavioural pattern.

# Stage 1: Sentiment scoring
for each post in user_history:
    sentiment_score = analyse(post.text)
    # result is a float: -1.0 (negative) to +1.0 (positive)
    store(user_id, post_timestamp, sentiment_score)

# Stage 2: Topic and behaviour clustering, across everyone's posts at once
feature_vectors = TF_IDF_transform(all_posts)
# each post becomes a numerical representation of its word patterns,
# with each term weighted by how distinctive it is across the whole collection

run K_means_clustering on feature_vectors
assign each post to a cluster

# Build user profile:
dominant_cluster = most frequent cluster for this user
average_sentiment = mean of sentiment scores over time
topic_map = most prominent terms across this user's feature_vectors

A user who posts frequently about work frustration, weekend socialising, and outdoor activities will generate a profile with a characteristic shape: negative sentiment spikes mid-week, positive spikes on weekends, topics clustering around professional stress and leisure. Mapped across millions of users, these profiles sort people into categories.

It knows the speaker

The pipeline above is one shape a profiling system can take. The experiment below uses a simpler one, a supervised classifier over word frequencies with no clustering step, because what is being asked is what a label can be predicted from, not what categories emerge on their own.

greenhouse-attacks profiling.py runs it against ParlaMint 5.0, the parliamentary corpus published by CLARIN under CC BY 4.0, taking the Latvian part of it: 23,038 speeches of forty words or more by 195 members, the chair and guests set aside. The label on each speech is the orientation recorded for the speaker’s party, a property of the party rather than a statement anybody made about their own opinions. The useful property for the experiment is that the corpus supplies the speech and an externally recorded label beside it.

Two questions hide inside one number here. Can the model predict the party-orientation label, and can it recognise speakers it has already read? Splitting speeches at random lets it answer both at once. Holding out whole speakers separates them.

Orientation predicted correctly

Always guessing the commonest answer

22.3%

Holding out random speeches

69.6%

Holding out whole speakers

34.6%

The middle row is the flattering number the random split produces. It leaves the same 195 people on both sides, so speaker-specific language becomes a shortcut to the party label and the model can take it. Asked about a politician whose speeches it has never read, it manages 34.6% against a floor of 22.3%: twelve points above the baseline, and roughly half the accuracy the flattering split claims.

More text does not rescue the unseen-speaker result. Asking for longer speeches shrinks the corpus, and the gap to the baseline closes:

Speeches of at least

Used

Unseen speaker

Baseline

40 words

23,038

34.6%

22.3%

200 words

10,100

28.5%

25.8%

600 words

1,316

29.7%

29.1%

At six hundred words it is within a point of a rule that ignores the text altogether.

None of that shows profiling failing. It is consistent with the model recovering the speaker from words alone and the position only faintly. That makes the 69.6% partly an author-identification result wearing the label of political inference. A system evaluated on that split alone could be described as reading politics when part of what it has learned is recognising who is speaking.

A label nobody sees

A profile of this kind is a statistical approximation, and it can be used for targeting. An advertiser holding one labelled “high stress, physically active, 30-40 age range” can aim at that person. So can a political operation holding one labelled “politically disengaged, economic anxiety, suburban”. The underlying data can come from public posts, platform activity, purchased datasets or embedded tracking, depending on the system.

The law now reaches the categorisation whether or not it is correct. Recital 79 of the political advertising Regulation says that profiling using special categories covers profiling “evaluated from personal data which are not themselves special categories”, giving as its example a controller using ordinary data “to categorise data subjects as having certain religious, philosophical or political beliefs, and regardless of whether that categorisation is true”. Recital 77 puts such targeting outside what online political advertising may do at all. The experiment above is that example carried out: ordinary parliamentary text, a political category attached, and the category mostly wrong once the speakers are unfamiliar.

None of this requires the profile to be right about anyone in particular. A categorisation that holds often enough across a million people is useful to whoever bought it, and the person it describes badly never sees the label, let alone corrects it. The label does not have to be right about everyone to be useful to somebody.

Profiling builds a broad behavioural category. Predicting one specific hidden attribute is the narrower move next door: the inference attack.

Keeping the hands apart

Behavioural profiling at this level operates on aggregate patterns over time. Reducing the volume and consistency of publicly available data can limit what a profile is built from. Using separate accounts for different contexts removes one direct route by which behaviour from several areas of life is aggregated. Public posts are training data for systems the poster never sees.

Keeping the contexts apart is the part that does the work, and it is harder than choosing what to write about. A model of this kind recovers the writer rather than the position, so steering away from a subject leaves the signal where it was: the statistical habits that attribute an anonymous essay to its author are the same ones that gather two accounts into one person. A separate context lasts as long as the writing in it does not read as the same hand.

Last reviewed: 2026-09-19.