AI News HubLIVE
In-site rewrite6 min read

Train, Serve, and Deploy a Scikit-learn Model with FastAPI

This guide walks through training a Scikit-learn classifier, building a FastAPI inference server, testing it locally, and deploying it to FastAPI Cloud. It uses the breast cancer dataset and a RandomForest model.

SourceMachine Learning MasteryAuthor: Abid Ali Awan

Train, Serve, and Deploy a Scikit-learn Model with FastAPI - MachineLearningMastery.com

Train, Serve, and Deploy a Scikit-learn Model with FastAPI - MachineLearningMastery.com

In this article, you will learn how to train a Scikit-learn classification model, serve it with FastAPI, and deploy it to FastAPI Cloud.

Topics we will cover include:

How to structure a simple project and train a Scikit-learn model for inference.

How to build and test a FastAPI inference API locally.

How to deploy the API to FastAPI Cloud and prepare it for more production-ready usage.

Train, Serve, and Deploy a Scikit-learn Model with FastAPI

Image by Author

Introduction

FastAPI has become one of the most popular ways to serve machine learning models because it is lightweight, fast, and easy to use. Many machine learning and AI applications use FastAPI to turn trained models into simple APIs that can be tested, shared, and deployed in production.

In this guide, you will learn how to train, serve, and deploy a Scikit-learn model with FastAPI. We will start by setting up a simple project, then train a model on a toy dataset, build a FastAPI inference server, test it locally, and finally deploy it to FastAPI Cloud.

  1. Setting Up the Project

Start by creating a new folder for your project and setting up a simple directory structure. This will help keep your training code, application code, and saved model files organized from the beginning.

Run the following commands in your terminal:

1

2

3

4

mkdir sklearn-fastapi-app

cd sklearn-fastapi-app

mkdir app artifacts

touch app/init.py

After that, your project structure should look like this:

1

2

3

4

5

6

7

8

sklearn-fastapi-app/

├── app/

│ ├── init.py

│ └── main.py

├── artifacts/

├── train.py

├── pyproject.toml

└── requirements.txt

Next, create a requirements.txt file and add the following dependencies:

1

2

3

4

fastapi[standard]

scikit-learn

joblib

numpy

These packages will be used to build and run the API, train the Scikit-learn model, save the trained model, and handle numerical input data.

Once the file is ready, install the dependencies with:

1

pip install -r requirements.txt

At this point, the project skeleton is ready, and you can move on to training your first Scikit-learn model.

  1. Training the Machine Learning Model

In this section, you will train a simple Scikit-learn classification model using the built-in breast cancer dataset.

The script loads the dataset, splits it into training and testing sets, trains a RandomForestClassifier, evaluates its accuracy, and saves everything needed for inference into a .joblib file inside the artifacts folder.

Create a train.py file with the following code:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

from pathlib import Path

import joblib

from sklearn.datasets import load_breast_cancer

from sklearn.ensemble import RandomForestClassifier

from sklearn.metrics import accuracy_score

from sklearn.model_selection import train_test_split

def main():

data = load_breast_cancer()

X = data.data

y = data.target

X_train, X_test, y_train, y_test = train_test_split(

X,

y,

test_size=0.2,

random_state=42,

stratify=y,

)

model = RandomForestClassifier(

n_estimators=200,

random_state=42,

)

model.fit(X_train, y_train)

predictions = model.predict(X_test)

accuracy = accuracy_score(y_test, predictions)

artifact = {

"model": model,

"target_names": data.target_names.tolist(),

"feature_names": data.feature_names,

}

output_path = Path("artifacts/breast_cancer_model.joblib")

output_path.parent.mkdir(parents=True, exist_ok=True)

joblib.dump(artifact, output_path)

print(f"Model saved to: {output_path}")

print(f"Test accuracy: {accuracy:.4f}")

if name == "main":

main()

Once the file is ready, run the training script from your terminal:

1

python train.py

You should see output similar to this:

1

2

Model saved to: artifacts/breast_cancer_model.joblib

Test accuracy: 0.9561

This means the model was trained successfully, evaluated on the test split, and saved for later use in the FastAPI application.

  1. Building the FastAPI Server

Now that the model has been trained and saved, the next step is to build a FastAPI server that loads the saved model and serves predictions through an API.

This application loads the model once when the server starts, provides a simple health check endpoint, and exposes a /predict route that accepts feature values and returns both the predicted class and class probabilities.

Create app/main.py with the following code:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

from pathlib import Path

import joblib

import numpy as np

from fastapi import FastAPI, HTTPException

from pydantic import BaseModel

ARTIFACT_PATH = Path("artifacts/breast_cancer_model.joblib")

app = FastAPI(

title="Breast Cancer Prediction API",

version="1.0.0",

description="A FastAPI server for serving a scikit-learn breast cancer classifier",

)

class PredictionRequest(BaseModel):

mean_radius: float

mean_texture: float

mean_perimeter: float

mean_area: float

mean_smoothness: float

mean_compactness: float

mean_concavity: float

mean_concave_points: float

mean_symmetry: float

mean_fractal_dimension: float

radius_error: float

texture_error: float

perimeter_error: float

area_error: float

smoothness_error: float

compactness_error: float

concavity_error: float

concave_points_error: float

symmetry_error: float

fractal_dimension_error: float

worst_radius: float

worst_texture: float

worst_perimeter: float

worst_area: float

worst_smoothness: float

worst_compactness: float

worst_concavity: float

worst_concave_points: float

worst_symmetry: float

worst_fractal_dimension: float

@app.on_event("startup")

def load_model():

if not ARTIFACT_PATH.exists():

raise RuntimeError(

f"Model file not found at {ARTIFACT_PATH}. Run python train.py first."

)

artifact = joblib.load(ARTIFACT_PATH)

app.state.model = artifact["model"]

app.state.target_names = artifact["target_names"]

@app.get("/health")

def health():

return {"status": "ok"}

@app.post("/predict")

def predict(request: PredictionRequest):

try:

features = np.array([[

request.mean_radius,

request.mean_texture,

request.mean_perimeter,

request.mean_area,

request.mean_smoothness,

request.mean_compactness,

request.mean_concavity,

request.mean_concave_points,

request.mean_symmetry,

request.mean_fractal_dimension,

request.radius_error,

request.texture_error,

request.perimeter_error,

request.area_error,

request.smoothness_error,

request.compactness_error,

request.concavity_error,

request.concave_points_error,

request.symmetry_error,

request.fractal_dimension_error,

request.worst_radius,

request.worst_texture,

request.worst_perimeter,

request.worst_area,

request.worst_smoothness,

request.worst_compactness,

request.worst_concavity,

request.worst_concave_points,

request.worst_symmetry,

request.worst_fractal_dimension,

]])

model = app.state.model

target_names = app.state.target_names

prediction_id = int(model.predict(features)[0])

probabilities = model.predict_proba(features)[0]

return {

"prediction_id": prediction_id,

"prediction_label": target_names[prediction_id],

"probabilities": {

target_names[i]: float(round(probabilities[i], 6))

for i in range(len(target_names))

}

}

except Exception as e:

raise HTTPException(status_code=500, detail=str(e))

This FastAPI app does three useful things.

It loads the trained model once during startup, exposes a /health endpoint so you can quickly check whether the server is running, and provides a /predict endpoint that accepts input features and returns an inference result. This makes it easy to turn your Scikit-learn model into a reusable API that other applications or services can call.

  1. Testing the Model Inference Server Locally

With the FastAPI app ready, the next step is to run it locally and test whether the prediction endpoint works as expected. FastAPI makes this easy because it automatically detects your application, starts a local development server, and provides built-in interactive API documentation that you can use directly from the browser.

Start the server with:

1

fastapi dev app/main.py

Once the server starts, FastAPI will serve the API locally, usually on port 8000.

FastAPI will serve the API locally

Next, open the interactive API docs in your browser:

1

http://127.0.0.1:8000/docs

Inside the docs page, you can test the /predict endpoint directly. Expand the endpoint, click Try it out, paste in the input values, and execute the request.

You can also test the API from the terminal using curl:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

curl -X POST "http://127.0.0.1:8000/predict" \

-H "Content-Type: application/json" \

-d '{

"mean_radius": 17.99,

"mean_texture": 10.38,

"mean_perimeter": 122.8,

"mean_area": 1001.0,

"mean_smoothness": 0.1184,

"mean_compactness": 0.2776,

"mean_concavity": 0.3001,

"mean_concave_points": 0.1471,

"mean_symmetry": 0.2419,

"mean_fractal_dimension": 0.07871,

"radius_error": 1.095,

"texture_error": 0.9053,

"perimeter_error": 8.589,

"area_error": 153.4,

"smoothness_error": 0.006399,

"compactness_error": 0.04904,

"concavity_error": 0.05373,

"concave_points_error": 0.01587,

"symmetry_error": 0.03003,

"fractal_dimension_error": 0.006193,

"worst_radius": 25.38,

"worst_texture": 17.33,

"worst_perimeter": 184.6,

"worst_area": 2019.0,

"worst_smoothness": 0.1622,

"worst_compactness": 0.6656,

"worst_concavity": 0.7119,

"worst_concave_points": 0.2654,

"worst_symmetry": 0.4601,

"worst_fractal_dimension": 0.1189

}'

The response will be returned as JSON, including the predicted class ID, the predicted label, and the probability scores for each class.

This confirms that the inference server is working locally and is ready to be deployed.

  1. Deploying the API to the Cloud

Once you have finished testing the API locally, you can stop the development server by pressing CTRL + C. The next step is to deploy the application to FastAPI Cloud. FastAPI Cloud supports deployment directly from the CLI, and the standard flow is fastapi login followed by fastapi deploy.

Log in with:

1

fastapi login

After logging in, deploy the app with:

1

fastapi deploy

During the first deployment, the CLI can guide you through setup, such as selecting or creating a team and choosing whether to create a new app or link to an existing one.

FastAPI Cloud then packages and uploads your code, installs dependencies in the cloud, deploys the application, and verifies that deployment completed successfully. After the first deploy, it also creates a .fastapicloud directory in your project so later deployments are simpler.

A successful deployment will end with output similar to this:

1

✅ Ready the chicken! 🐔 Your app is ready at https://sklearn-fastapi-app.fastapicloud.dev

Once the app is live, open the deployed docs page in your browser to check that the endpoints are working.

You can also test the deployed API from the terminal by replacing the local URL with your cloud URL.

Finally, you can go to the FastAPI Cloud dashboard, click your deployed app, and check the logs to monitor builds, startup behavior, and runtime issues.

What to D

[truncated for AI cost control]