Machine Learning Tutorial



This lab combines machine learning with DevOps and cloud technologies. You will build a machine learning model to predict music genres based on user age and gender, create a prediction service using FastAPI, containerize it with Docker, set up a CI/CD pipeline with GitHub Actions, and deploy it to Render, a free cloud provider.

Lab Overview

  • Objective: Build, deploy, and monitor an ML-powered prediction service using FastAPI, Docker, GitHub Actions, and Render.
  • Tools and Technologies:
    • Python, Jupyter Notebook, scikit-learn (for ML)
    • Git (version control)
    • Docker (containerization)
    • FastAPI (web service framework)
    • GitHub Actions (CI/CD)
    • Render (free cloud deployment)
  • Duration: Approximately 4-6 hours.
  • Prerequisites:
    • Basic Python programming skills.
    • Familiarity with Git.
    • A GitHub account and a Render account (free tier).

Lab Structure

The lab is divided into six modules, each building on the previous one to create a complete ML deployment pipeline.

Part 1: Building the Machine Learning Model

Goal: Develop and train an ML model to predict music preferences.

Steps:

  1. Set Up the Environment:

    • Install Anaconda.
    • Launch Jupyter Notebook:
      jupyter notebook
  2. Create a New Notebook:

    • In Jupyter, click “New” > “Python 3” and name it MusicRecommender.ipynb.
  3. Import Required Libraries:

    import pandas as pd
    import numpy as np
    from sklearn.model_selection import train_test_split
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.metrics import accuracy_score
    import joblib
  4. Load the Dataset:

    • Download music.csv
    • Load it into the notebook:
      df = pd.read_csv('music.csv')
  5. Explore the Data:

    df.head()  # View first 5 rows
    df.describe()  # Statistical summary
    print(df.shape)  # Expected output: (18, 3)
  6. Prepare the Data:

    • Split features (X) and target (y):
      X = df.drop(columns=['genre'])
      y = df['genre']
      X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
  7. Train the Model:

    model = DecisionTreeClassifier()
    model.fit(X_train, y_train)
  8. Evaluate the Model:

    predictions = model.predict(X_test)
    accuracy = accuracy_score(y_test, predictions)
    print(f'Accuracy: {accuracy}')
  9. Save the Model:

    joblib.dump(model, 'music_recommender.joblib')

Deliverable: A trained ML model saved as music_recommender.joblib.

Part 2: Version Control with Git

Goal: Use Git to manage the project code.

Steps:

  1. Initialize a Git Repository:

    git init
  2. Add and Commit Files:

    git add MusicRecommender.ipynb music.csv
    git commit -m "Initial commit: ML model development"
  3. Push to a Remote Repository:

    • Create a new repository on GitHub (e.g., music-recommender-lab).
    • Link and push:
      git remote add origin https://github.com/your-username/music-recommender-lab.git
      git branch -M main
      git push -u origin main

Deliverable: Project files tracked in a GitHub repository.

Part 3: Creating a Prediction Service with FastAPI

Goal: Build a web service using FastAPI to serve model predictions.

Steps:

  1. Install FastAPI and Uvicorn:

    pip install fastapi uvicorn
  2. Create app.py:

    • Define a FastAPI app with a POST endpoint for predictions:

      from fastapi import FastAPI
      from pydantic import BaseModel
      import joblib
      
      app = FastAPI()
      model = joblib.load('music_recommender.joblib')
      
      class UserInput(BaseModel):
          age: int
          gender: int
      
      @app.post('/predict')
      def predict(user_input: UserInput):
          prediction = model.predict([[user_input.age, user_input.gender]])
          return {'genre': prediction[0]}
  3. Test Locally:

    • Run the FastAPI app:
      uvicorn app:app --host 0.0.0.0 --port 5000 --reload
    • Test the endpoint using curl:
      curl -X POST http://127.0.0.1:5000/predict -H "Content-Type: application/json" -d '{"age": 21, "gender": 1}'
    • Expected output: {"genre":"HipHop"} (or similar).
  4. Commit Changes:

    git add app.py
    git commit -m "Added FastAPI prediction service"
    git push origin main

Deliverable: A functional FastAPI app serving predictions at http://127.0.0.1:5000/predict.

Part 4: Containerization with Docker

Goal: Containerize the FastAPI app using Docker.

Steps:

  1. Create a Dockerfile:

    • The Dockerfile installs dependencies and runs the app with Uvicorn:
      FROM python:3.8-slim
      WORKDIR /app
      COPY app.py music_recommender.joblib ./
      RUN pip install fastapi uvicorn joblib scikit-learn
      EXPOSE 5000
      CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "5000"]
  2. Build the Docker Image:

    docker build -t music-recommender:latest .
  3. Run the Container:

    docker run -p 5000:5000 music-recommender
    • Test again with curl:
      curl -X POST http://127.0.0.1:5000/predict -H "Content-Type: application/json" -d '{"age": 21, "gender": 1}'
  4. Push to Docker Hub:

    • Tag and push the image:
      docker tag music-recommender your-username/music-recommender:latest
      docker push your-username/music-recommender:latest
  5. Commit the Dockerfile:

    git add Dockerfile
    git commit -m "Added Docker configuration for FastAPI app"
    git push origin main

Deliverable: A Dockerized FastAPI app pushed to Docker Hub.

Part 5: CI/CD Pipeline with GitHub Actions

Goal: Automate building and deploying the Docker image using GitHub Actions.

Steps:

  1. Create a Workflow File:

    • Add the following to .github/workflows/ci-cd.yml:
      name: CI/CD Pipeline
      on:
        push:
          branches: [main]
      jobs:
        build-and-deploy:
          runs-on: ubuntu-latest
          steps:
            - uses: actions/checkout@v3
            - name: Build Docker Image
              run: docker build -t music-recommender .
            - name: Login to Docker Hub
              run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
            - name: Tag and Push Image
              run: |
                docker tag music-recommender ${{ secrets.DOCKER_USERNAME }}/music-recommender:latest
                docker push ${{ secrets.DOCKER_USERNAME }}/music-recommender:latest          
  2. Configure Secrets in GitHub:

    • Go to your GitHub repository > Settings > Secrets and variables > Actions.
    • Add DOCKER_USERNAME and DOCKER_PASSWORD as secrets.
  3. Test the Pipeline:

    • Commit and push the workflow file:
      git add .github/workflows/ci-cd.yml
      git commit -m "Added CI/CD pipeline for Docker image"
      git push origin main
    • Check the Actions tab in GitHub to verify the pipeline runs successfully.

Deliverable: An automated CI/CD pipeline that builds and pushes the Docker image to Docker Hub.

Part 6: Cloud Deployment and Monitoring (Using Render)

Goal: Deploy your FastAPI application to Render, a free cloud platform, and monitor its performance.

Steps:

  1. Set Up a Render Account:

    • Sign up for a free account at render.com.
    • Connect your GitHub account to Render via the Render dashboard.
  2. Create a New Web Service:

    • In the Render dashboard, click “New” > “Web Service”.
    • Select your GitHub repository (e.g., music-recommender-lab).
    • Choose the branch to deploy (e.g., main).
  3. Configure the Web Service:

    • Environment: Select “Python 3”.
    • Build Command: Enter pip install -r requirements.txt.
    • Start Command: Enter uvicorn app:app --host 0.0.0.0 --port $PORT.
    • Instance Type: Choose the “Free” tier.
  4. Add requirements.txt (If Not Already Present):

    • Ensure your project includes a requirements.txt file:
      fastapi
      uvicorn
      joblib
      scikit-learn
      pandas
      numpy
    • Commit and push if needed:
      git add requirements.txt
      git commit -m "Added requirements.txt for Render deployment"
      git push origin main
  5. Deploy the Service:

    • Click “Create Web Service” in the Render dashboard.
    • Render will build and deploy your app, providing a unique URL (e.g., https://music-recommender.onrender.com).
  6. Test the Deployment:

    • Test your app’s prediction endpoint:
      curl -X POST https://music-recommender.onrender.com/predict -H "Content-Type: application/json" -d '{"age": 21, "gender": 1}'
  7. Monitor Logs:

    • In the Render dashboard, go to your service and click the “Logs” tab to view real-time logs.
    • Use these logs to monitor and debug your app.

Deliverable: A deployed FastAPI prediction service on Render with logging enabled.

Optional Challenges

  1. Automated Model Retraining:
    • Extend the CI/CD pipeline to retrain the model when new data is added.
  2. Model Experimentation:
    • Experiment with other ML algorithms (e.g., Random Forest) and compare accuracy.
  3. Interactive API Documentation:
    • Explore FastAPI’s built-in documentation at /docs (e.g., https://music-recommender.onrender.com/docs).

This lab provides a comprehensive, end-to-end workflow for building, deploying, and monitoring an ML-powered prediction service using modern DevOps and cloud practices, all while leveraging free-tier resources for learning or small-scale projects.


By Wahid Hamdi