Saltar al contenido principal

LIA - Detailed Requirements

Requirements Reference Document Advanced

Requirements Overview

Your LIA is evaluated across six components. Each component has specific requirements that must be met. This page provides the detailed rubric and checklists for each.


A. Model Training (20%)

Objectives

Demonstrate your ability to select, train, evaluate, and serialize machine learning models using a structured methodology.

Requirements

  • Dataset Selection: Choose an appropriate dataset (at least 500 samples, ≥ 5 features)
  • Exploratory Data Analysis: Perform thorough EDA with visualizations (distributions, correlations, missing values)
  • Data Preprocessing: Handle missing values, encode categorical variables, normalize/scale features
  • Train at least 2 models: Different algorithms (e.g., Logistic Regression vs Random Forest)
  • Evaluate with at least 3 metrics: Choose metrics appropriate for your problem type
  • Hyperparameter tuning: Attempt at least basic tuning (GridSearch or RandomizedSearch)
  • Serialize the best model: Save with joblib, pickle, or ONNX
  • Document your methodology: Justify every decision in your notebook and report
Problem TypeMetric 1Metric 2Metric 3Metric 4 (bonus)
Binary ClassificationAccuracyPrecision / RecallF1-ScoreAUC-ROC
Multi-class ClassificationAccuracyMacro F1-ScoreConfusion MatrixClassification Report
RegressionMAERMSER² ScoreMAPE

Expected Code Structure

# notebooks/02_model_training.ipynb

# 1. Load and explore data
import pandas as pd
from sklearn.model_selection import train_test_split

df = pd.read_csv("data/dataset.csv")
X = df.drop(columns=["target"])
y = df["target"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 2. Train Model A
from sklearn.linear_model import LogisticRegression
model_a = LogisticRegression(max_iter=1000)
model_a.fit(X_train, y_train)

# 3. Train Model B
from sklearn.ensemble import RandomForestClassifier
model_b = RandomForestClassifier(n_estimators=100, random_state=42)
model_b.fit(X_train, y_train)

# 4. Evaluate both models
from sklearn.metrics import accuracy_score, f1_score, roc_auc_score

results = {
"Model": ["Logistic Regression", "Random Forest"],
"Accuracy": [accuracy_score(y_test, model_a.predict(X_test)),
accuracy_score(y_test, model_b.predict(X_test))],
"F1-Score": [f1_score(y_test, model_a.predict(X_test)),
f1_score(y_test, model_b.predict(X_test))],
"AUC-ROC": [roc_auc_score(y_test, model_a.predict_proba(X_test)[:, 1]),
roc_auc_score(y_test, model_b.predict_proba(X_test)[:, 1])]
}
pd.DataFrame(results)

# 5. Serialize best model
import joblib
joblib.dump(model_b, "models/best_model.pkl")

Grading Rubric — Model Training

CriterionExcellent (18-20)Good (16-17)Satisfactory (14-15)Insufficient (< 14)
DatasetWell-chosen, relevant, properly justifiedAppropriate datasetDataset works but poorly justifiedInappropriate or too small dataset
EDAThorough analysis with ≥ 5 visualizations, insights documentedGood EDA with 3-4 visualizationsBasic EDA, few visualizationsNo EDA or minimal exploration
PreprocessingAll steps justified, pipeline documentedMost steps presentBasic preprocessing onlyMissing critical preprocessing steps
Models≥ 3 models compared, hyperparameter tuning performed2 models compared with basic tuning2 models trained, no tuningOnly 1 model, no comparison
Metrics≥ 4 metrics, correct interpretation, comparison table3 metrics with interpretation3 metrics reported, minimal interpretation< 3 metrics or incorrect metrics
SerializationModel saved with metadata (version, metrics, features)Model saved correctlyModel saved but no metadataModel not serialized
MethodologyClear narrative, every decision justifiedMost decisions explainedSome explanations providedNo methodology documentation

B. API Service (25%)

Objectives

Build a production-ready REST API that serves predictions from your trained model, with proper input validation, error handling, and auto-generated documentation.

Requirements

  • Framework: Use FastAPI (recommended) or Flask
  • Endpoint /predict (POST): Accept input features, return prediction and confidence
  • Endpoint /health (GET): Return service health status
  • Endpoint /model-info (GET): Return model metadata (name, version, features, metrics)
  • Input validation: Use Pydantic models (FastAPI) or manual validation (Flask)
  • Error handling: Return proper HTTP status codes (400, 404, 422, 500) with descriptive messages
  • Swagger documentation: Auto-generated and accessible at /docs
  • Clean code: Functions documented, consistent naming, no hardcoded values

API Endpoint Specifications

EndpointMethodInputOutputStatus Codes
/predictPOSTJSON with feature values{ prediction, confidence, model_version }200, 400, 422, 500
/healthGETNone{ status: "healthy", timestamp }200
/model-infoGETNone{ model_name, version, features, metrics }200
/predict/batchPOSTArray of inputsArray of predictions200, 400, 422
Bonus Endpoint

Implementing a /predict/batch endpoint for batch predictions earns bonus consideration. It demonstrates understanding of real-world API patterns.

Expected Code — FastAPI

# src/app.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
from datetime import datetime
import joblib
import numpy as np

app = FastAPI(
title="My ML Prediction API",
description="LIA Project — AI Model Deployment",
version="1.0.0"
)

model = joblib.load("models/best_model.pkl")

class PredictionInput(BaseModel):
feature_1: float = Field(..., description="Description of feature 1")
feature_2: float = Field(..., description="Description of feature 2")
feature_3: float = Field(..., ge=0, description="Must be non-negative")

class Config:
json_schema_extra = {
"example": {
"feature_1": 5.1,
"feature_2": 3.5,
"feature_3": 1.4
}
}

class PredictionOutput(BaseModel):
prediction: int
confidence: float
model_version: str

@app.get("/health")
def health_check():
return {
"status": "healthy",
"timestamp": datetime.now().isoformat(),
"model_loaded": model is not None
}

@app.get("/model-info")
def model_info():
return {
"model_name": "RandomForestClassifier",
"version": "1.0.0",
"features": ["feature_1", "feature_2", "feature_3"],
"training_metrics": {
"accuracy": 0.95,
"f1_score": 0.93,
"auc_roc": 0.97
}
}

@app.post("/predict", response_model=PredictionOutput)
def predict(data: PredictionInput):
try:
features = np.array([[data.feature_1, data.feature_2, data.feature_3]])
prediction = model.predict(features)[0]
confidence = float(model.predict_proba(features).max())
return PredictionOutput(
prediction=int(prediction),
confidence=round(confidence, 4),
model_version="1.0.0"
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Prediction failed: {str(e)}")

Expected Code — Flask Alternative

# src/app.py
from flask import Flask, request, jsonify
from datetime import datetime
import joblib
import numpy as np

app = Flask(__name__)
model = joblib.load("models/best_model.pkl")

@app.route("/health", methods=["GET"])
def health_check():
return jsonify({
"status": "healthy",
"timestamp": datetime.now().isoformat(),
"model_loaded": model is not None
})

@app.route("/predict", methods=["POST"])
def predict():
data = request.get_json()
if not data:
return jsonify({"error": "No input data provided"}), 400

required_fields = ["feature_1", "feature_2", "feature_3"]
for field in required_fields:
if field not in data:
return jsonify({"error": f"Missing field: {field}"}), 400

try:
features = np.array([[data["feature_1"], data["feature_2"], data["feature_3"]]])
prediction = model.predict(features)[0]
confidence = float(model.predict_proba(features).max())
return jsonify({
"prediction": int(prediction),
"confidence": round(confidence, 4),
"model_version": "1.0.0"
})
except Exception as e:
return jsonify({"error": f"Prediction failed: {str(e)}"}), 500

Grading Rubric — API Service

CriterionExcellent (22-25)Good (20-21)Satisfactory (18-19)Insufficient (< 18)
EndpointsAll 3 required + bonus endpointsAll 3 required endpoints work2 of 3 endpoints work< 2 endpoints working
ValidationPydantic models with constraints, type checking, examplesBasic Pydantic validationMinimal validationNo input validation
Error HandlingAll error codes correct, descriptive messages, edge cases handledMost errors handled properlyBasic error handlingNo error handling
DocumentationSwagger complete with examples, descriptions for all fieldsSwagger accessible and usefulSwagger auto-generated, minimal customizationNo API documentation
Code QualityClean architecture, separation of concerns, docstringsWell-organized codeCode works but messySpaghetti code, hardcoded values
Response FormatConsistent JSON structure, proper status codes, timestampsConsistent responsesInconsistent response formatsBroken or missing responses

C. Testing (15%)

Objectives

Demonstrate your ability to write automated tests that validate your model and API, and to use Postman for API testing.

Requirements

  • Minimum 10 tests using pytest
  • Unit tests: Test model loading, prediction logic, input validation
  • Integration tests: Test API endpoints end-to-end
  • Edge case tests: Test with invalid inputs, empty data, extreme values
  • Code coverage > 70%: Measured with pytest-cov
  • Postman collection: Exported .json with tests for all endpoints
  • Test documentation: Explain what each test validates

Test Categories

Expected Test Code

# tests/test_api.py
import pytest
from fastapi.testclient import TestClient
from src.app import app

client = TestClient(app)

# --- Health Check Tests ---

def test_health_returns_200():
response = client.get("/health")
assert response.status_code == 200
assert response.json()["status"] == "healthy"

def test_health_has_timestamp():
response = client.get("/health")
assert "timestamp" in response.json()

# --- Model Info Tests ---

def test_model_info_returns_200():
response = client.get("/model-info")
assert response.status_code == 200

def test_model_info_contains_version():
response = client.get("/model-info")
data = response.json()
assert "version" in data
assert "model_name" in data
assert "features" in data

# --- Prediction Tests ---

def test_predict_valid_input():
payload = {"feature_1": 5.1, "feature_2": 3.5, "feature_3": 1.4}
response = client.post("/predict", json=payload)
assert response.status_code == 200
data = response.json()
assert "prediction" in data
assert "confidence" in data

def test_predict_confidence_range():
payload = {"feature_1": 5.1, "feature_2": 3.5, "feature_3": 1.4}
response = client.post("/predict", json=payload)
confidence = response.json()["confidence"]
assert 0.0 <= confidence <= 1.0

def test_predict_missing_field_returns_422():
payload = {"feature_1": 5.1} # Missing features
response = client.post("/predict", json=payload)
assert response.status_code == 422

def test_predict_wrong_type_returns_422():
payload = {"feature_1": "not_a_number", "feature_2": 3.5, "feature_3": 1.4}
response = client.post("/predict", json=payload)
assert response.status_code == 422

def test_predict_empty_body_returns_422():
response = client.post("/predict", json={})
assert response.status_code == 422

# --- Edge Case Tests ---

def test_predict_extreme_values():
payload = {"feature_1": 99999.0, "feature_2": -99999.0, "feature_3": 0.0}
response = client.post("/predict", json=payload)
assert response.status_code in [200, 400]

Running Tests with Coverage

# Run all tests
pytest tests/ -v

# Run with coverage report
pytest tests/ --cov=src --cov-report=term-missing

# Generate HTML coverage report
pytest tests/ --cov=src --cov-report=html

Postman Collection Requirements

Your Postman collection must include:

RequestMethodTests
Health CheckGET /healthStatus is 200, body contains "healthy"
Model InfoGET /model-infoStatus is 200, body contains model name
Valid PredictionPOST /predictStatus is 200, response has prediction and confidence
Missing FieldsPOST /predictStatus is 422, error message present
Wrong TypesPOST /predictStatus is 422, validation error
Empty BodyPOST /predictStatus is 422
Postman Test Scripts

Each Postman request should include test scripts. Example:

pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});

pm.test("Response has prediction", function () {
var jsonData = pm.response.json();
pm.expect(jsonData).to.have.property("prediction");
pm.expect(jsonData).to.have.property("confidence");
});

Grading Rubric — Testing

CriterionExcellent (14-15)Good (12-13)Satisfactory (11)Insufficient (< 11)
Test Count≥ 15 tests, comprehensive coverage10-14 tests, good variety10 tests, basic coverage< 10 tests
Unit TestsModel + validation + utility functions testedModel and validation testedBasic model test onlyNo unit tests
Integration TestsAll endpoints tested with multiple scenariosAll endpoints tested onceMost endpoints testedFew endpoint tests
Edge CasesInvalid inputs, extreme values, empty data, wrong typesSome edge cases covered1-2 edge casesNo edge cases
Coverage> 80%> 70%> 60%< 60%
PostmanComplete collection with test scripts for all requestsCollection with basic testsCollection exists, few testsNo Postman collection

D. Explainability (15%)

Objectives

Apply model interpretability techniques to explain your model's predictions and build trust in your AI system.

Requirements

  • Apply LIME and/or SHAP to your trained model
  • Generate at least 3 visualizations: Feature importance, individual explanations, summary plots
  • Interpret results: Explain in plain language what the model is learning
  • Identify potential biases: Check if certain features have unexpected influence
  • Document findings: Include analysis in your report and notebook

Visualization Requirements

#VisualizationToolDescription
1Global Feature ImportanceSHAP summary_plot or bar_plotWhich features matter most overall?
2Individual Prediction ExplanationLIME explain_instanceWhy did the model make this specific prediction?
3Feature InteractionSHAP dependence_plotHow do features interact?
4Decision Boundary (if applicable)LIME or customHow does the model separate classes?
5Waterfall Plot (bonus)SHAP waterfall_plotStep-by-step contribution of each feature

Expected Code — SHAP

# notebooks/03_explainability.ipynb
import shap
import matplotlib.pyplot as plt

explainer = shap.TreeExplainer(model) # For tree-based models
shap_values = explainer.shap_values(X_test)

# 1. Global feature importance (summary plot)
shap.summary_plot(shap_values, X_test, show=False)
plt.title("SHAP Feature Importance — Global View")
plt.tight_layout()
plt.savefig("docs/shap_summary.png", dpi=150)
plt.show()

# 2. Single prediction explanation (waterfall)
shap.plots.waterfall(shap.Explanation(
values=shap_values[0],
base_values=explainer.expected_value,
data=X_test.iloc[0],
feature_names=X_test.columns.tolist()
))

# 3. Feature dependence plot
shap.dependence_plot("feature_1", shap_values, X_test)

Expected Code — LIME

# notebooks/03_explainability.ipynb
from lime.lime_tabular import LimeTabularExplainer

explainer = LimeTabularExplainer(
training_data=X_train.values,
feature_names=X_train.columns.tolist(),
class_names=["Class 0", "Class 1"],
mode="classification"
)

# Explain a single prediction
instance = X_test.iloc[0].values
explanation = explainer.explain_instance(
instance,
model.predict_proba,
num_features=10
)

# Show explanation
explanation.show_in_notebook()

# Save as HTML
explanation.save_to_file("docs/lime_explanation.html")

Interpretation Guide

When interpreting your results, answer these questions:

QuestionWhat to Look For
Which features are most important?Top features in SHAP summary or LIME global
Are the important features logical?Do they make business sense?
Are there any surprises?Unexpected feature importance may indicate data leakage
Is the model biased?Does it rely heavily on sensitive attributes?
How confident is the model?Are predictions high-confidence or uncertain?
Data Leakage

If a feature has disproportionately high importance (e.g., one feature alone has SHAP value 10x higher than all others), it may indicate data leakage — a variable that wouldn't be available at prediction time. Investigate before finalizing your model.

Grading Rubric — Explainability

CriterionExcellent (14-15)Good (12-13)Satisfactory (11)Insufficient (< 11)
MethodsBoth LIME and SHAP appliedOne method applied thoroughlyOne method, basic usageNo explainability analysis
Visualizations≥ 5 clear, well-labeled visualizations3-4 visualizations2-3 basic visualizations< 2 or poorly formatted
InterpretationDeep analysis, business implications, bias checkGood interpretation, some insightsSurface-level interpretationNo interpretation, just plots
DocumentationFindings integrated in report with recommendationsFindings mentioned in reportBrief mention in reportNot documented

E. Documentation & Report (10%)

Objectives

Produce professional documentation that would allow another developer to understand, run, and extend your project.

Requirements

  • README.md: Project description, setup instructions, usage examples, API reference
  • Technical report (5-8 pages): Follows the provided template
  • API documentation: Swagger/OpenAPI accessible at /docs
  • Code documentation: Docstrings for all public functions
  • Clear writing: No spelling errors, consistent formatting, logical structure

README.md Requirements

Your README must include:

SectionContent
Project TitleClear, descriptive name
Description2-3 sentences explaining the project
InstallationStep-by-step setup instructions
UsageHow to start the API, example requests
API EndpointsTable with all endpoints
TestingHow to run tests
Project StructureDirectory tree
Model InformationAlgorithm, metrics, dataset
AuthorYour name and student ID

Technical Report Structure

Your report must follow the template provided in the Report Template section:

SectionPagesKey Content
Executive Summary0.5Overview of entire project
Problem Definition1Business context, dataset, objectives
Methodology1-1.5Preprocessing, model selection, evaluation strategy
Results1-1.5Metrics, comparisons, confusion matrices
API Design1Architecture, endpoints, response formats
Testing Strategy0.5Test plan, coverage, Postman results
Explainability1LIME/SHAP results, interpretation
Deployment0.5How to run, Docker, environment
Conclusion0.5Summary, lessons learned, future work

Grading Rubric — Documentation & Report

CriterionExcellent (9-10)Good (8)Satisfactory (7)Insufficient (< 7)
READMEComplete, clear, anyone can set up the projectMost sections present, minor gapsBasic README, missing sectionsNo README or unusable
Report StructureAll sections present, logical flowMost sections, minor gapsMissing 1-2 sectionsMissing many sections
Writing QualityProfessional, clear, concise, no errorsGood writing, few minor errorsUnderstandable, some errorsPoor writing, many errors
Technical DepthDeep analysis, justified decisionsGood depth, most decisions explainedSurface-level analysisNo depth, just descriptions
FormattingConsistent, tables, figures captionedMostly consistentInconsistent formattingNo formatting effort

F. Oral Presentation (15%)

Objectives

Present your project professionally, demonstrate a working system, and defend your technical decisions during Q&A.

Requirements

  • Duration: 15 minutes presentation + 5 minutes Q&A
  • Slide deck: 10-15 slides, clean design
  • Live demo: Show the API working in real-time
  • Technical depth: Explain model choice, metrics, architecture decisions
  • Q&A readiness: Be able to answer questions about any aspect of your project

Presentation Time Allocation

SectionDurationContent
Introduction & Context2 minProblem statement, dataset, objectives
Model Training & Results3 minEDA highlights, model comparison, best model
API Architecture2 minEndpoints, validation, error handling
Live Demo3 minShow API working: health, predict, model-info
Testing & Explainability3 minTest results, coverage, LIME/SHAP insights
Conclusion & Lessons2 minWhat you learned, what you'd do differently
Q&A5 minAnswer instructor questions

Grading Rubric — Oral Presentation

CriterionExcellent (14-15)Good (12-13)Satisfactory (11)Insufficient (< 11)
ContentComprehensive, well-structured, covers all componentsGood coverage, minor gapsAdequate coverage, missing detailsMajor components missing
DemoAPI works flawlessly, multiple requests shownDemo works, minor hiccupsDemo partially worksDemo fails or not attempted
CommunicationConfident, clear, professional, good paceGood delivery, minor nervousnessAdequate deliveryUnclear, reading from slides
SlidesClean design, informative visuals, no text wallsGood slides, minor issuesAcceptable but text-heavyPoor design, too much text
Q&AAnswers all questions confidently, shows deep understandingAnswers most questions wellAnswers some questionsCannot answer basic questions
Time Management14-16 minutes, well-paced12-18 minutes, mostly well-pacedUnder 10 or over 20 minutesSignificantly over/under time
See the Presentation Guide

For detailed presentation tips, time allocation advice, and common Q&A questions, see the Presentation Guide.


Complete Submission Checklist

Use this checklist before submitting your LIA:

Code & Model

  • Git repository is clean and organized
  • .gitignore excludes __pycache__, .env, large files
  • requirements.txt with all dependencies (pinned versions)
  • Trained model file is in models/ directory
  • EDA notebook is complete and runs without errors
  • Training notebook is complete and runs without errors

API

  • API starts without errors (uvicorn src.app:app --reload)
  • /health returns 200 with status and timestamp
  • /predict accepts valid input and returns prediction + confidence
  • /predict returns 422 for invalid input
  • /model-info returns model metadata
  • Swagger docs accessible at /docs

Testing

  • At least 10 pytest tests pass
  • Code coverage > 70%
  • Postman collection exported to postman/collection.json
  • Edge cases are tested (invalid types, missing fields, extreme values)

Explainability

  • LIME and/or SHAP analysis complete
  • At least 3 visualizations saved
  • Interpretations written in notebook and report

Documentation

  • README.md is complete with setup instructions
  • Technical report is 5-8 pages, follows template
  • All code has docstrings

Presentation

  • Slide deck is 10-15 slides
  • Live demo prepared and tested
  • Practiced within 15-minute time limit
  • Prepared for potential Q&A questions
Final Verification

Before submitting, clone your repository to a fresh directory and follow your own README instructions to set up the project from scratch. If you can't run it, neither can your instructor.