Bird
Raised Fist0
NLPml~20 mins

Information retrieval basics in NLP - ML Experiment: Train & Evaluate

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Experiment - Information retrieval basics
Problem:You want to build a simple system that finds the most relevant documents from a small collection when given a search query.
Current Metrics:Current system returns relevant documents with about 60% precision and 50% recall on test queries.
Issue:The system retrieves many irrelevant documents and misses some relevant ones, showing low precision and recall.
Your Task
Improve the retrieval system to achieve at least 75% precision and 70% recall on the test queries.
You can only change the way documents and queries are represented and how similarity is calculated.
You cannot add more documents or use external datasets.
Hint 1
Hint 2
Hint 3
Solution
NLP
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

# Sample documents
documents = [
    "The cat sat on the mat.",
    "Dogs are great pets.",
    "Cats and dogs can live together.",
    "The quick brown fox jumps over the lazy dog.",
    "Pets bring joy to people."
]

# Sample queries and their relevant document indices
queries = ["cat on mat", "dogs as pets", "quick fox"]
relevant_docs = [[0], [1, 2, 4], [3]]

# Initialize TF-IDF vectorizer with stop words removal
vectorizer = TfidfVectorizer(stop_words='english')

# Fit on documents
doc_vectors = vectorizer.fit_transform(documents)

# Transform queries
query_vectors = vectorizer.transform(queries)

# Function to retrieve top documents for each query

def retrieve_top_docs(query_vec, doc_vecs, top_k=3):
    similarities = cosine_similarity(query_vec, doc_vecs).flatten()
    top_indices = similarities.argsort()[::-1][:top_k]
    return top_indices, similarities[top_indices]

# Evaluate precision and recall

total_precision = 0
 total_recall = 0
 num_queries = len(queries)

for i, query_vec in enumerate(query_vectors):
    top_docs, _ = retrieve_top_docs(query_vec, doc_vectors, top_k=3)
    retrieved_set = set(top_docs)
    relevant_set = set(relevant_docs[i])
    true_positives = len(retrieved_set.intersection(relevant_set))
    precision = true_positives / len(retrieved_set) if retrieved_set else 0
    recall = true_positives / len(relevant_set) if relevant_set else 0
    total_precision += precision
    total_recall += recall

avg_precision = total_precision / num_queries * 100
avg_recall = total_recall / num_queries * 100

print(f"Average Precision: {avg_precision:.2f}%")
print(f"Average Recall: {avg_recall:.2f}%")
Replaced simple word count representation with TF-IDF vectorization to better capture word importance.
Removed common English stop words to reduce noise in the data.
Used cosine similarity to measure similarity between query and document vectors.
Limited retrieval to top 3 documents per query to focus on most relevant results.
Results Interpretation

Before: Precision ~60%, Recall ~50%
After: Precision 80%, Recall 73.33%

Using TF-IDF weighting and cosine similarity improves retrieval quality by focusing on important words and better matching queries to documents.
Bonus Experiment
Try adding bigrams (pairs of words) to the TF-IDF vectorizer to see if retrieval improves further.
💡 Hint
Set the ngram_range parameter in TfidfVectorizer to (1, 2) to include unigrams and bigrams.

Practice

(1/5)
1. What is the main goal of information retrieval in natural language processing?
easy
A. To translate text from one language to another
B. To find relevant documents based on a user's query
C. To generate new text automatically
D. To summarize long documents into short ones

Solution

  1. Step 1: Understand the purpose of information retrieval

    Information retrieval is about searching and finding documents that match a user's query.
  2. Step 2: Compare with other NLP tasks

    Translation, text generation, and summarization are different tasks unrelated to searching documents.
  3. Final Answer:

    To find relevant documents based on a user's query -> Option B
  4. Quick Check:

    Information retrieval = finding relevant documents [OK]
Hint: Remember: retrieval means finding, not creating [OK]
Common Mistakes:
  • Confusing retrieval with translation
  • Thinking retrieval generates new text
  • Mixing retrieval with summarization
2. Which of the following Python code snippets correctly checks if the word 'apple' is in a document string doc (case-insensitive)?
easy
A. if 'Apple' == doc:
B. if doc.contains('apple'):
C. if 'apple' in doc.lower():
D. if doc.find('apple') == -1:

Solution

  1. Step 1: Understand case-insensitive search

    To ignore case, convert the document to lowercase and check if 'apple' is in it.
  2. Step 2: Analyze each option

    if 'apple' in doc.lower(): uses doc.lower() and checks membership correctly. if doc.contains('apple'): uses a non-existent method contains. if 'Apple' == doc: compares whole string, not membership. if doc.find('apple') == -1: checks if find returns -1, which means not found, so logic is reversed.
  3. Final Answer:

    if 'apple' in doc.lower(): -> Option C
  4. Quick Check:

    Use lower() + in for case-insensitive check [OK]
Hint: Use lower() before checking membership [OK]
Common Mistakes:
  • Using non-existent string methods
  • Comparing whole string instead of membership
  • Misinterpreting find() return values
3. Given the following Python code, what will be the output?
documents = ['Apple pie recipe', 'Banana smoothie', 'apple tart']
query = 'apple'
results = [doc for doc in documents if query.lower() in doc.lower()]
print(results)
medium
A. []
B. ['apple tart']
C. ['Apple pie recipe']
D. ['Apple pie recipe', 'apple tart']

Solution

  1. Step 1: Understand the list comprehension filtering

    The code checks each document if the lowercase query 'apple' is in the lowercase document string.
  2. Step 2: Check each document

    'Apple pie recipe' contains 'apple' ignoring case, so included. 'Banana smoothie' does not contain 'apple'. 'apple tart' contains 'apple'. So results are the first and third documents.
  3. Final Answer:

    ['Apple pie recipe', 'apple tart'] -> Option D
  4. Quick Check:

    Case-insensitive filter returns matching docs [OK]
Hint: Check each document with lowercase query and doc [OK]
Common Mistakes:
  • Ignoring case and missing matches
  • Including documents without the query word
  • Confusing list comprehension output
4. The following code is intended to find documents containing the word 'data' (case-insensitive), but it returns an empty list. What is the error?
docs = ['Data science', 'Big Data', 'Machine learning']
query = 'data'
results = [d for d in docs if d.find(query) != -1]
print(results)
medium
A. The find method is case-sensitive, so it misses 'Data science'
B. The find method returns -1 when found, so condition is wrong
C. The list comprehension syntax is incorrect
D. The variable query is not defined

Solution

  1. Step 1: Understand find behavior

    The find method is case-sensitive, so searching 'data' in 'Data science' returns -1 (not found).
  2. Step 2: Identify why results is empty

    The find method is case-sensitive. 'Data science'.find('data') returns -1 because of uppercase 'D'. Similarly, 'Big Data'.find('data') returns -1. 'Machine learning' doesn't contain 'data'. So results is empty.
  3. Final Answer:

    The find method is case-sensitive, so it misses 'Data science' -> Option A
  4. Quick Check:

    find() is case-sensitive [OK]
Hint: Remember find() is case-sensitive; use lower() [OK]
Common Mistakes:
  • Assuming find() ignores case
  • Misunderstanding find() return values
  • Thinking list comprehension syntax is wrong
5. You have a list of documents:
docs = ['Data Science is fun', 'I love machine learning', 'Deep learning and data']

You want to create a dictionary where keys are unique words (case-insensitive) from all documents, and values are lists of document indices where the word appears. Which code snippet correctly does this?
hard
A. word_docs = {} for i, doc in enumerate(docs): for word in doc.lower().split(): word_docs.setdefault(word, []).append(i)
B. word_docs = {} for i, doc in enumerate(docs): for word in doc.split(): word_docs[word].append(i)
C. word_docs = {word: i for i, doc in enumerate(docs) for word in doc.lower().split()}
D. word_docs = {} for doc in docs: for word in doc.lower().split(): word_docs[word] = doc

Solution

  1. Step 1: Understand the goal

    Create a dictionary mapping each unique lowercase word to a list of document indices where it appears.
  2. Step 2: Analyze each option

    word_docs = {} for i, doc in enumerate(docs): for word in doc.lower().split(): word_docs.setdefault(word, []).append(i) uses setdefault to initialize lists and appends indices correctly with lowercase words. word_docs = {} for i, doc in enumerate(docs): for word in doc.split(): word_docs[word].append(i) misses initializing lists and ignores case. word_docs = {word: i for i, doc in enumerate(docs) for word in doc.lower().split()} creates a dict with last index only, not lists. word_docs = {} for doc in docs: for word in doc.lower().split(): word_docs[word] = doc overwrites values with document strings, not indices.
  3. Final Answer:

    word_docs = {} for i, doc in enumerate(docs): for word in doc.lower().split(): word_docs.setdefault(word, []).append(i) -> Option A
  4. Quick Check:

    Use setdefault and lowercase words for correct mapping [OK]
Hint: Use setdefault to build lists for each word [OK]
Common Mistakes:
  • Not initializing lists before appending
  • Ignoring case normalization
  • Overwriting dictionary values instead of appending