Key-Phrase Extraction
Text Analysis
Python NLP
Topic Modeling
Natural Language Processing

Extracting Key-Phrases from text based on the Topic with Python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Generic keyword extraction often returns the most frequent phrases in a document, not the phrases that best represent the topic you care about. If the same text talks about pricing, shipping, and battery life, a topic-aware extractor should surface very different phrases depending on which angle you choose. In Python, a simple and effective way to do that is to score candidate phrases against a topic-specific subset instead of the full corpus.

Start With Topic-Scoped Documents

The easiest approach is to group documents by topic first, then run phrase scoring only on the relevant group. That can be done with labels from your application, a topic model, or even a manual filter.

Here is a small TF-IDF example using topic labels that already exist:

python
1from sklearn.feature_extraction.text import TfidfVectorizer
2
3documents = [
4    ("ml", "Neural networks need good training data and careful feature scaling."),
5    ("ml", "Model evaluation and feature engineering improve machine learning systems."),
6    ("finance", "Bond prices react to interest rates and market sentiment."),
7    ("finance", "Diversification can reduce portfolio risk over time."),
8    ("ml", "Training data quality affects accuracy and generalization."),
9]
10
11
12def extract_topic_terms(docs, topic, top_n=10):
13    topic_texts = [text for label, text in docs if label == topic]
14    if not topic_texts:
15        return []
16
17    vectorizer = TfidfVectorizer(
18        stop_words="english",
19        ngram_range=(1, 2),
20        lowercase=True,
21    )
22    matrix = vectorizer.fit_transform(topic_texts)
23    scores = matrix.mean(axis=0).A1
24    terms = vectorizer.get_feature_names_out()
25    ranked = sorted(zip(terms, scores), key=lambda item: item[1], reverse=True)
26    return ranked[:top_n]
27
28
29for phrase, score in extract_topic_terms(documents, "ml"):
30    print(f"{phrase}: {score:.3f}")

This works because TF-IDF is calculated only from machine-learning texts, so phrases such as training data and feature engineering get promoted instead of being diluted by finance language.

Generate Better Candidate Phrases

Raw n-grams are a useful baseline, but they also produce noisy phrases. A simple improvement is to build candidate phrases first and then score them. Even a lightweight filter can improve quality.

python
1import re
2from collections import Counter
3from sklearn.feature_extraction.text import ENGLISH_STOP_WORDS
4
5
6def candidate_phrases(text):
7    words = re.findall(r"[A-Za-z]+", text.lower())
8    phrases = []
9
10    for left, right in zip(words, words[1:]):
11        if left in ENGLISH_STOP_WORDS or right in ENGLISH_STOP_WORDS:
12            continue
13        phrases.append(f"{left} {right}")
14
15    return phrases
16
17
18sample = "Training data quality improves model accuracy and feature engineering decisions."
19print(candidate_phrases(sample))

This is still simple enough to run anywhere, but it avoids many weak phrases that come from stop words or broken token boundaries.

Compare In-Topic And Out-Of-Topic Frequency

A phrase is more interesting when it is common inside the chosen topic and relatively uncommon elsewhere. You can express that idea with a simple ratio score.

python
1from collections import Counter
2
3
4def topic_phrase_scores(docs, topic):
5    in_topic = Counter()
6    out_topic = Counter()
7
8    for label, text in docs:
9        phrases = candidate_phrases(text)
10        if label == topic:
11            in_topic.update(phrases)
12        else:
13            out_topic.update(phrases)
14
15    ranked = []
16    for phrase, count in in_topic.items():
17        score = count / (1 + out_topic[phrase])
18        ranked.append((phrase, score))
19
20    return sorted(ranked, key=lambda item: item[1], reverse=True)
21
22
23print(topic_phrase_scores(documents, "ml")[:5])

This is not a full research-grade ranking model, but it captures a useful intuition: topic phrases should be distinctive, not just frequent.

Where Topic Labels Come From

If you do not already have topic labels, you can produce them before extraction. Some pipelines use clustering or topic modeling, while others label documents through metadata such as product category or support queue.

The important design choice is to keep topic assignment separate from phrase ranking. If the extracted phrases look wrong, you can then ask two focused questions: was the document assigned to the wrong topic, or was the phrase scorer weak inside the right topic?

That separation makes the pipeline much easier to debug than a monolithic "NLP magic" step.

Common Pitfalls

The biggest mistake is extracting phrases from the full corpus and expecting topic-specific answers to appear automatically. Without topic scoping, frequent but irrelevant language will dominate the scores.

Another issue is relying only on single tokens. Many high-value concepts appear as multi-word phrases such as training data, interest rates, or battery life.

It is also easy to forget stop-word filtering and basic cleanup. Poor candidate generation can make a good scoring method look bad.

Finally, avoid mixing topic detection and phrase ranking into one opaque step unless you have a strong reason. Keeping them separate makes evaluation and debugging much simpler.

Summary

  • Topic-aware extraction scores phrases relative to the subject you care about.
  • A topic-scoped TF-IDF pipeline is a strong baseline in Python.
  • Candidate phrase filtering improves results over raw token frequency.
  • Comparing in-topic counts against out-of-topic counts highlights distinctive phrases.
  • Separate topic assignment from phrase ranking so the system stays debuggable.

Course illustration
Course illustration

All Rights Reserved.