Mock Exam 02¶
Instructions¶
Use the Olympics Data directory. Prefer clear, small code over overly general code.
Task 1: Databases and SQL, 45 points¶
- Load the top-level CSV files into DataFrames and create an in-memory SQLite database.
- Write SQL queries for:
- The number of athletes per discipline.
- The five venues hosting the most distinct sports.
- Medal counts by gender.
- Countries that have both coaches and athletes in the dataset.
- Disciplines where at least ten countries won medals.
- Explain each query in one or two sentences.
Task 2: Clustering and method choice, 30 points¶
- Generate a dataset with four compact blob clusters and 40 random noise points.
- Run k-means with
k=4and plot the result. - Explain how noise can affect k-means centers.
- Explain whether DBSCAN might be a better choice.
- Explain whether scaling matters for clustering.
Task 3: Generative AI, 15 points¶
- Compare classic sentiment-analysis preprocessing with LLM text preprocessing.
- Explain bag-of-words, TF-IDF, token IDs, embeddings, and positional embeddings.
- Explain pretraining versus finetuning.
- Explain why a pretrained GPT model produces poor output before training but can generate coherent output after pretraining.
Answer Key¶
Task 1 answer¶
from pathlib import Path
import sqlite3
import pandas as pd
dataframes = {
path.stem: pd.read_csv(path)
for path in Path("Data").glob("*.csv")
}
conn = sqlite3.connect(":memory:")
for name, df in dataframes.items():
df.to_sql(name, conn, index=False, if_exists="replace")
Athletes per discipline:
SELECT disciplines, COUNT(*) AS athlete_count
FROM athletes
GROUP BY disciplines
ORDER BY athlete_count DESC;
This counts athlete rows for each discipline-list value. A stronger answer may note that disciplines is stored like a list in text, so exact multi-discipline normalization is limited.
Venues hosting the most distinct sports:
Because sports is stored as a text representation of a list, SQLite cannot directly count list elements without preprocessing. This answer is acceptable if the limitation is explained. A Pandas preprocessing answer that explodes the list before writing to SQL is stronger.
Medal counts by gender:
This groups medal rows by the gender field in the medal table.
Countries with both coaches and athletes:
SELECT DISTINCT a.country
FROM athletes AS a
JOIN coaches AS c
ON a.country_code = c.country_code
ORDER BY a.country;
This joins by country code and keeps countries appearing in both tables.
Disciplines where at least ten countries won medals:
SELECT discipline, COUNT(DISTINCT country_code) AS medal_country_count
FROM medals
GROUP BY discipline
HAVING COUNT(DISTINCT country_code) >= 10
ORDER BY medal_country_count DESC;
This uses HAVING because the filter depends on an aggregate value.
Task 2 answer¶
import matplotlib.pyplot as plt
import numpy as np
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
X_blobs, _ = make_blobs(
n_samples=360,
centers=4,
cluster_std=0.65,
random_state=11,
)
rng = np.random.default_rng(11)
noise = rng.uniform(low=-10, high=10, size=(40, 2))
X = np.vstack([X_blobs, noise])
model = KMeans(n_clusters=4, random_state=11, n_init=10)
labels = model.fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=labels, s=18, cmap="viridis")
plt.scatter(
model.cluster_centers_[:, 0],
model.cluster_centers_[:, 1],
c="red",
marker="X",
s=180,
)
plt.show()
Noise can pull k-means centers away from the true compact groups because k-means minimizes squared distance to centroids. DBSCAN may be better because it can mark sparse points as noise and find dense regions without preselecting k. Scaling matters because distance-based methods treat large-scale features as more important unless features are standardized.
Task 3 answer¶
Classic sentiment analysis often cleans text aggressively: lowercasing, removing HTML, removing stop words, stemming, and converting documents into bag-of-words or TF-IDF vectors. LLM preprocessing usually keeps more of the original text structure because punctuation, word endings, capitalization, and order can carry useful information.
Bag-of-words counts token occurrences and mostly loses order. TF-IDF downweights common terms and upweights terms that are more specific to a document. Token IDs are integer identifiers for tokens. Embeddings turn token IDs into learned dense vectors. Positional embeddings add order information because the model otherwise sees a set of token vectors without sequence position.
Pretraining learns general language patterns from large unlabeled text through next-token prediction. Finetuning adapts a pretrained model to a specific task, such as spam classification, or to an instruction-following response style.
An untrained GPT architecture has random weights, so its output is essentially random. After pretraining, the weights encode statistical patterns of language, syntax, facts, and task-relevant representations, so next-token predictions become coherent.