# How to Build a Machine Learning Recommendation System for Exercises

> Learn to build a machine learning recommendation system for exercises using the Exercises Dataset. Explore content-based and collaborative filtering methods with TF-IDF and cosine similarity.

- Repository: [Hasan Emir Yıldırım/exercises-dataset](https://github.com/hasaneyldrm/exercises-dataset)
- Tags: how-to-guide
- Published: 2026-07-31

---

**The Exercises Dataset repository provides a fully-featured, multilingual catalog of 1,324 exercises with JSON schema validation, enabling you to build content-based or collaborative filtering recommenders using TF-IDF vectors, categorical encodings, and cosine similarity.**

The `hasaneyldrm/exercises-dataset` repository offers a production-ready foundation for building a machine learning recommendation system for exercises. With structured data covering equipment requirements, target muscles, and multilingual instructions, you can rapidly prototype fitness applications that suggest relevant workouts based on user constraints. This guide walks through the complete architecture—from ingesting [`data/exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json) to deploying a FastAPI recommendation service.

## Data Ingestion and Schema Validation

Every recommendation pipeline begins with reliable data loading. The repository stores the master catalog in [`data/exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json), which contains 1,324 exercise records with fields for `category`, `equipment`, `target`, and `muscle_group`. To ensure data integrity, validate incoming JSON against [`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json) before processing.

```python
import json

# Load and validate the exercise catalog

with open("data/exercises.json", "r", encoding="utf-8") as f:
    exercises = json.load(f)

print(f"Loaded {len(exercises)} exercises")  # Output: 1324

```

Validating against the schema guarantees that each record contains required multilingual instruction sets and media references. This step prevents runtime errors when processing text fields or categorical attributes later in the pipeline.

## Feature Engineering for Exercise Recommendations

Transforming raw exercise data into numeric vectors requires handling both textual instructions and categorical metadata. The dataset supports multilingual text in the `instructions` field, allowing you to build language-aware recommenders.

### Text Vectorization with TF-IDF

Extract features from exercise descriptions using **TF-IDF** (Term Frequency-Inverse Document Frequency) on the instruction text. The repository stores instructions as nested objects by language code (e.g., `instructions.en` for English).

```python
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer

df = pd.DataFrame(exercises)

# Extract English instructions (swap .en for other language codes)

texts = df["instructions"].apply(lambda x: x["en"])

tfidf = TfidfVectorizer(stop_words="english", max_features=2000)
text_matrix = tfidf.fit_transform(texts)

```

### Encoding Categorical Attributes

Convert structured fields into machine-readable formats using **one-hot encoding**. The key categorical columns include `category`, `equipment`, `target`, and `muscle_group`.

```python
from sklearn.preprocessing import OneHotEncoder

cat_features = df[["category", "equipment", "target", "muscle_group"]]
encoder = OneHotEncoder(sparse=True)
cat_matrix = encoder.fit_transform(cat_features)

```

Combine text and categorical features into a single sparse matrix for efficient similarity computation.

```python
from scipy.sparse import hstack

# Horizontally stack TF-IDF and categorical features

X = hstack([text_matrix, cat_matrix])
print(f"Feature matrix shape: {X.shape}")  # Output: (1324, ~2500)

```

## Implementing the Recommendation Engine

With feature vectors prepared, implement either content-based filtering or collaborative filtering to generate recommendations.

### Content-Based Filtering with Cosine Similarity

For equipment-constrained recommendations, compute **cosine similarity** between a query vector (representing user preferences) and all exercise vectors. This approach requires no historical user interaction data.

```python
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

def recommend_by_equipment_target(equipment, target, top_k=5):
    # Build query vector from categorical encodings

    query_df = pd.DataFrame([{
        "category": "", "equipment": equipment,
        "target": target, "muscle_group": ""
    }])
    q_cat = encoder.transform(query_df)
    # Zero-vector for text component

    q_text = np.zeros((1, text_matrix.shape[1]))
    q = hstack([q_text, q_cat])
    
    sims = cosine_similarity(q, X).flatten()
    idx = sims.argsort()[::-1][:top_k]
    return df.iloc[idx][["name", "equipment", "target"]]

# Example: Find dumbbell exercises for biceps

print(recommend_by_equipment_target("dumbbell", "biceps"))

```

### Collaborative Filtering Approaches

When user interaction data (e.g., workout history) is available, train matrix factorization models such as **LightFM** or **implicit**. These algorithms incorporate the engineered TF-IDF and categorical features as side-information to handle cold-start scenarios for new exercises.

## Deploying Your Exercise Recommender API

The repository includes [`setup.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/setup.html), a developer wizard that generates SQL import scripts and API client code for multiple frameworks including FastAPI, Express.js, and Spring Boot. Export your trained model using `joblib` and serve predictions via a lightweight endpoint.

```python
from fastapi import FastAPI
import joblib

app = FastAPI()
model = joblib.load("model.pkl")          # Trained LightFM or similarity matrix

features = joblib.load("features.pkl")    # TF-IDF + one-hot matrix

@app.get("/recommend")
def recommend(equipment: str, target: str, k: int = 5):
    # Compute similarity and return top-k exercises

    # Implementation uses encoder and cosine similarity as shown above

    pass

```

For client-side validation of recommendations, use [`index.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/index.html) to browse the dataset interactively before deployment.

## Summary

- **Data Validation**: Always validate [`data/exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json) against [`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json) to ensure 1,324 records contain complete multilingual instructions and media references.
- **Feature Engineering**: Combine TF-IDF vectors from instruction text with one-hot encoded categorical fields (`equipment`, `target`, `muscle_group`) to create a sparse feature matrix of approximately 2,500 dimensions.
- **Content-Based Filtering**: Use cosine similarity on the combined feature matrix to recommend exercises matching specific equipment and muscle targets without requiring user history.
- **Deployment**: Leverage [`setup.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/setup.html) to generate boilerplate API code for FastAPI, Express.js, or other frameworks, exporting models via `joblib` for production serving.

## Frequently Asked Questions

### How do I handle multilingual recommendations in the Exercises Dataset?

The dataset stores instructions as nested objects by language code (e.g., `instructions.en`, `instructions.tr`). Extract the desired language field before applying TF-IDF vectorization, or concatenate multiple languages into a single text field to build cross-lingual recommendation models.

### What is the recommended approach for cold-start users with no workout history?

Use the content-based filtering approach described in `hasaneyldrm/exercises-dataset`. By encoding the user's available equipment and target muscles into the one-hot categorical matrix, you can compute cosine similarity against all 1,324 exercises immediately, without requiring historical interaction data.

### Can I use the dataset for commercial fitness applications?

According to the repository's `LICENSE` and [`NOTICE.md`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/NOTICE.md) files, the dataset is available for commercial use provided you comply with media attribution requirements for the exercise GIFs and thumbnails. Always verify the specific license terms in [`NOTICE.md`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/NOTICE.md) before deploying commercially.

### How do I validate that my JSON data matches the expected schema?

Load both [`data/exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json) and [`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json), then use a JSON Schema validator library (such as `jsonschema` for Python) to verify each record contains required fields including `category`, `equipment`, `target`, and multilingual `instructions`. This prevents processing errors during feature engineering.