<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>spam classification Archives - OVHcloud Blog</title>
	<atom:link href="https://blog.ovhcloud.com/tag/spam-classification/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.ovhcloud.com/tag/spam-classification/</link>
	<description>Innovation for Freedom</description>
	<lastBuildDate>Fri, 03 Mar 2023 16:39:19 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://blog.ovhcloud.com/wp-content/uploads/2019/07/cropped-cropped-nouveau-logo-ovh-rebranding-32x32.gif</url>
	<title>spam classification Archives - OVHcloud Blog</title>
	<link>https://blog.ovhcloud.com/tag/spam-classification/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Deploy a custom Docker image for Data Science project – A spam classifier with FastAPI (Part 3)</title>
		<link>https://blog.ovhcloud.com/deploy-a-custom-docker-image-for-data-science-project-a-spam-classifier-with-fastapi-part-3/</link>
		
		<dc:creator><![CDATA[Eléa Petton]]></dc:creator>
		<pubDate>Fri, 30 Dec 2022 10:39:54 +0000</pubDate>
				<category><![CDATA[OVHcloud Engineering]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[AI Deploy]]></category>
		<category><![CDATA[AI Notebook]]></category>
		<category><![CDATA[AI Solutions]]></category>
		<category><![CDATA[Artificial Intelligence]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Machine learning]]></category>
		<category><![CDATA[OVHcloud]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Scikit Learn]]></category>
		<category><![CDATA[spam classification]]></category>
		<guid isPermaLink="false">https://blog.ovhcloud.com/?p=24202</guid>

					<description><![CDATA[A guide to deploy a custom Docker image for an API with FastAPI and AI Deploy. Welcome to the third article concerning custom Docker image deployment. If you haven&#8217;t read the previous ones, you can check it: &#8211; Gradio sketch recognition app&#8211; Streamlit app for EDA and interactive prediction When creating code for a Data [&#8230;]<img src="//blog.ovhcloud.com/wp-content/plugins/matomo/app/matomo.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fblog.ovhcloud.com%2Fdeploy-a-custom-docker-image-for-data-science-project-a-spam-classifier-with-fastapi-part-3%2F&amp;action_name=Deploy%20a%20custom%20Docker%20image%20for%20Data%20Science%20project%20%E2%80%93%20A%20spam%20classifier%20with%20FastAPI%20%28Part%203%29&amp;urlref=https%3A%2F%2Fblog.ovhcloud.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[
<p><em>A guide to deploy a custom Docker image for an API with <a href="https://fastapi.tiangolo.com/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">FastAPI</a> and <strong>AI Deploy</strong>.</em></p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="815" src="https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-spam-classifier-1024x815.jpg" alt="fastapi for spam classification" class="wp-image-24226" srcset="https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-spam-classifier-1024x815.jpg 1024w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-spam-classifier-300x239.jpg 300w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-spam-classifier-768x612.jpg 768w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-spam-classifier-1536x1223.jpg 1536w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-spam-classifier.jpg 1620w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p><em>Welcome to the third article concerning <strong>custom Docker image deployment</strong>. If you haven&#8217;t read the previous ones, you can check it:</em></p>



<p><em>&#8211; </em><a href="https://blog.ovhcloud.com/deploy-a-custom-docker-image-for-data-science-project-gradio-sketch-recognition-app-part-1/" data-wpel-link="internal">Gradio sketch recognition app</a><br><em>&#8211; </em><a href="https://docs.ovh.com/fr/publiccloud/ai/deploy/tuto-streamlit-eda-iris/" data-wpel-link="exclude">Streamlit app for EDA and interactive prediction</a></p>



<p>When creating code for a <strong>Data Science project</strong>, you probably want it to be as portable as possible. In other words, it can be run as many times as you like, even on different machines.</p>



<p>Unfortunately, it is often the case that a Data Science code works fine locally on a machine but gives errors during runtime. It can be due to different versions of libraries installed on the host machine.</p>



<p>To deal with this problem, you can use <a href="https://www.docker.com/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">Docker</a>.</p>



<p><strong>The article is organized as follows:</strong></p>



<ul class="wp-block-list">
<li>Objectives</li>



<li>Concepts</li>



<li>Define a model for spam classification</li>



<li>Build the FastAPI app with Python</li>



<li>Containerize your app with Docker</li>



<li>Launch the app with AI Deploy</li>
</ul>



<p><em>All the code for this blogpost is available in our dedicated <a href="https://github.com/ovh/ai-training-examples/tree/main/apps/fastapi/spam-classifier-api" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">GitHub repository</a>. You can test it with OVHcloud <strong>AI Deploy</strong> tool, please refer to the <a href="https://docs.ovh.com/gb/en/publiccloud/ai/deploy/tuto-fastapi-spam-classifier/" data-wpel-link="exclude">documentation</a> to boot it up.</em></p>



<h2 class="wp-block-heading">Objectives</h2>



<p>In this article, you will learn how to develop <strong>FastAPI</strong> API for spam classification.</p>



<p>Once your app is up and running locally, it will be a matter of containerizing it, then deploying the custom Docker image with AI Deploy.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="2160" height="1215" src="https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-objective-edited.jpg" alt="objective of api deployment" class="wp-image-24228" srcset="https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-objective-edited.jpg 2160w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-objective-edited-300x169.jpg 300w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-objective-edited-1024x576.jpg 1024w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-objective-edited-768x432.jpg 768w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-objective-edited-1536x864.jpg 1536w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-objective-edited-2048x1152.jpg 2048w" sizes="(max-width: 2160px) 100vw, 2160px" /></figure>



<h2 class="wp-block-heading">Concepts</h2>



<p>In Artificial Intelligence, you have probably heard of <strong>Natural Language Processing</strong> (NLP). <strong>NLP</strong> gathers several tasks related to language processing such as <strong>text classification</strong>.</p>



<p>This technique is ideal for distinguishing spam from other messages.</p>



<h3 class="wp-block-heading">Spam Ham Collection&nbsp;Dataset</h3>



<p>The <a href="https://archive.ics.uci.edu/ml/datasets/sms+spam+collection" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">SMS Spam Collection</a> is a public set of SMS labeled messages that have been collected for mobile phone spam research.</p>



<p>The dataset contains <strong>5,574 messages</strong> in English. The SMS are tagged as follow:</p>



<ul class="wp-block-list">
<li><strong>HAM</strong> if the message is legitimate</li>



<li><strong>SPAM</strong> if it is not</li>
</ul>



<p>The collection is a <strong>text file</strong>, where each line has the correct <strong>class</strong> followed by the raw <strong>message</strong>.</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img decoding="async" src="https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-5-1024x576.png" alt="spam ham dataset" class="wp-image-24219" width="773" height="435" srcset="https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-5-1024x576.png 1024w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-5-300x169.png 300w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-5-768x432.png 768w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-5-1536x864.png 1536w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-5.png 1920w" sizes="(max-width: 773px) 100vw, 773px" /></figure>



<h3 class="wp-block-heading">Logistic regression</h3>



<p><strong>What is a Logistic Regression?</strong></p>



<p><a href="https://fr.wikipedia.org/wiki/R%C3%A9gression_logistique" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">Logistic regression</a> is a statistical model. It allows to study the relationships between a set of <code>i</code> <strong>qualitative variables</strong> (<code>Xi</code>) and a <strong>qualitative variable</strong> (<code>Y</code>).</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img loading="lazy" decoding="async" src="https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-logistic-regression-1024x779.jpg" alt="logistic regression" class="wp-image-24229" width="467" height="355" srcset="https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-logistic-regression-1024x779.jpg 1024w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-logistic-regression-300x228.jpg 300w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-logistic-regression-768x584.jpg 768w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-logistic-regression-1536x1168.jpg 1536w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-logistic-regression.jpg 1620w" sizes="auto, (max-width: 467px) 100vw, 467px" /></figure>



<p>It is a generalized linear model using a logistic function as a link function.</p>



<p>A logistic regression model can also predict the <strong>probability</strong> of an event occurring (value close to <code><strong>1</strong></code>) or not (value close to <strong><code>0</code></strong>) from the optimization of the <strong>regression coefficients</strong>. This result always varies between <strong><code>0</code></strong> and <strong><code>1</code></strong>.</p>



<p>For the spam classification use case, <strong>words</strong> are inputs and <strong>class</strong> (spam or ham) is output.</p>



<h3 class="wp-block-heading">FastAPI</h3>



<p><strong>What is FastAPI?</strong></p>



<p><a href="https://fastapi.tiangolo.com/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">FastAPI</a> is a web framework for building <strong>RESTful APIs</strong> with Python.</p>



<p>FastAPI is based on <a href="https://docs.pydantic.dev/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">Pydantic</a> and type guidance to <em>validate</em>, <em>serialize</em> and <em>deserialize</em> data, and automatically generate OpenAPI documents.</p>



<h3 class="wp-block-heading">Docker</h3>



<p><a href="https://www.docker.com/" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Docker</a>&nbsp;platform allows you to build, run and manage isolated applications. The principle is to build an application that contains not only the written code but also all the context to run the code: libraries and their versions for example</p>



<p>When you wrap your application with all its context, you build a Docker image, which can be saved in your local repository or in the Docker Hub.</p>



<p>To get started with Docker, please, check this&nbsp;<a href="https://www.docker.com/get-started" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">documentation</a>.</p>



<p>To build a Docker image, you will define 2 elements:</p>



<ul class="wp-block-list">
<li>the application code (<em>FastAPI app</em>)</li>



<li>the&nbsp;<a href="https://docs.docker.com/engine/reference/builder/" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Dockerfile</a></li>
</ul>



<p>In the next steps, you will see how to develop the Python code for your app, but also how to write the Dockerfile.</p>



<p>Finally, you will see how to deploy your custom docker image with&nbsp;<strong>OVHcloud AI Deploy</strong>&nbsp;tool.</p>



<h3 class="wp-block-heading">AI Deploy</h3>



<p><strong>AI Deploy</strong>&nbsp;enables AI models and managed applications to be started via Docker containers.</p>



<p>To know more about AI Deploy, please refer to this&nbsp;<a href="https://docs.ovh.com/gb/en/publiccloud/ai/deploy/getting-started/" data-wpel-link="exclude">documentation</a>.</p>



<h2 class="wp-block-heading">Define a model for spam classification</h2>



<p>❗ <strong><code>To develop an API that uses a Machine Learning model, you have to load the model in the correct format. For this tutorial, a Logistic Regression is used and the Python file model.py is used to define it</code></strong>.<br><br><code><strong>To better understand the model.py code, refer to the <a href="https://github.com/ovh/ai-training-examples/blob/main/notebooks/natural-language-processing/text-classification/miniconda/spam-classifier/notebook-spam-classifier.ipynb" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">notebook</a> which details all the steps</strong></code>.</p>



<p>First of all, you have to import the&nbsp;<strong>Python libraries</strong>&nbsp;needed to create the Logistic Regression in the <code>model.py</code> file.</p>



<pre class="wp-block-code"><code class="">import pandas as pd
import numpy as np
from sklearn import model_selection
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression</code></pre>



<p>Now, you can create the Logistic Regression based on the <strong>Spam Ham Collection&nbsp;Dataset</strong>. The Python framework named <strong>Scikit-Learn</strong> is used to define this model.</p>



<p>Firstly, you can load the dataset and transform your input file into a <code>dataframe</code>.</p>



<p>You will also be able to define the <code>input</code> and the <code>output</code> of the model.</p>



<pre class="wp-block-code"><code class="">def load_data():

    PATH = 'SMSSpamCollection'
    df = pd.read_csv(PATH, delimiter = "\t", names=["classe", "message"])

    X = df['message']
    y = df['classe']

    return X, y</code></pre>



<p>In a second step, you split the data in a training and a test set.</p>



<p>To <strong>separate the dataset fairly</strong> and to have a <code>test_size</code> between 0 and 1, you can calculate <code>ntest</code> as follows.</p>



<pre class="wp-block-code"><code class="">def split_data(X, y):

    ntest = 2000/(3572+2000)

    X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size=ntest, random_state=0)

    return X_train, y_train</code></pre>



<p>Now you can concentrate on creating the <strong>Machine Learning model</strong>. To do this, create a <code>spam_classifier_model</code> function.</p>



<p>To fully understand the code, refer to <strong>Steps 6 to 9</strong> of this <a href="https://github.com/ovh/ai-training-examples/blob/main/notebooks/natural-language-processing/text-classification/miniconda/spam-classifier/notebook-spam-classifier.ipynb" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">notebook</a>. In these steps you will learn how to:</p>



<ul class="wp-block-list">
<li>create the model using <strong>Logistic Regression</strong></li>



<li>evaluate on the test set</li>



<li>do <strong>dimension reduction</strong> with stop words and term frequency</li>



<li>do <strong>dimension reduction</strong> to post-processing of the model</li>
</ul>



<pre class="wp-block-code"><code class="">def spam_classifier_model(Xtrain, ytrain):

    model_logistic_regression = LogisticRegression()
    model_logistic_regression = model_logistic_regression.fit(Xtrain, ytrain)

    coeff = model_logistic_regression.coef_
    coef_abs = np.abs(coeff)

    quantiles = np.quantile(coef_abs,[0, 0.25, 0.5, 0.75, 0.9, 1])

    index = np.where(coeff[0] &gt; quantiles[1])
    newXtrain = Xtrain[:, index[0]]

    model_logistic_regression = LogisticRegression()
    model_logistic_regression.fit(newXtrain, ytrain)

    return model_logistic_regression, index</code></pre>



<p>Once these Python functions are defined, you can call and apply them as follows.</p>



<p>Firstly, extract input and output data with <code>load_data()</code>:</p>



<pre class="wp-block-code"><code class="">data_input, data_output = load_data()</code></pre>



<p>Secondly, split the data using the <code>split_data(data_input, data_output)</code>:</p>



<pre class="wp-block-code"><code class="">X_train, ytrain = split_data(data_input, data_output)</code></pre>



<p>❗ <code><strong>Here, there is no need to use the test set. Indeed, the evaluation of the final model has already been done in <em>Step 9 - Dimensionality reduction: post processing of the model</em> of the <a href="https://github.com/ovh/ai-training-examples/blob/main/notebooks/natural-language-processing/text-classification/miniconda/spam-classifier/notebook-spam-classifier.ipynb" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">notebook</a>.</strong></code></p>



<p>Thirdly, <strong>transform</strong> and <strong>fit</strong> training set. In order to<strong> </strong>prepare<strong> </strong>the data, you can use <code>CountVectorizer</code> from Scikit-Learn to remove <strong>stop-words</strong> and then <code>fit_transform</code> to fit the inputs.</p>



<pre class="wp-block-code"><code class="">vectorizer = CountVectorizer(stop_words='english', binary=True, min_df=10)
Xtrain = vectorizer.fit_transform(X_train.tolist())
Xtrain = Xtrain.toarray()</code></pre>



<p>Fourthly, use the model and index for prediction by calling <code>spam_classifier_model</code> function.</p>



<pre class="wp-block-code"><code class="">model_logistic_regression, index = spam_classifier_model(Xtrain, ytrain)</code></pre>



<p>Find out the full Python code <a href="https://github.com/ovh/ai-training-examples/blob/main/apps/fastapi/spam-classifier-api/model.py" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">here</a>.</p>



<p>Have you successfully defined your model? Good job 🥳 !</p>



<p>Let&#8217;s go for the creation of the API!</p>



<h2 class="wp-block-heading">Build the FastAPI app with Python</h2>



<p>❗ <code><strong>All the codes below are available in the <em>app.py</em> file. You can find the complete Python code of the <em>app.py</em> file <a href="https://github.com/ovh/ai-training-examples/blob/main/apps/fastapi/spam-classifier-api/app.py" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">here</a>.</strong></code></p>



<p>To begin, you can import dependencies for FastAPI app.</p>



<ul class="wp-block-list">
<li>uvicorn</li>



<li>fastapi</li>



<li>pydantic</li>
</ul>



<pre class="wp-block-code"><code class="">import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel
from model import model_logistic_regression, index, vectorizer</code></pre>



<p>In the first place, you can initialize an instance of FastAPI.</p>



<pre class="wp-block-code"><code class="">app = FastAPI()</code></pre>



<p>Next, you can define the data format by creating the Python class named <code>request_body</code>. Here, the <strong>string</strong> (<code>str</code>) format is required.</p>



<pre class="wp-block-code"><code class="">class request_body(BaseModel):
    message : str</code></pre>



<p>Now, you can create the process function in order to prepare the sent message to be used by the model.</p>



<pre class="wp-block-code"><code class="">def process_message(message):

    desc = vectorizer.transform(message)
    dense_desc = desc.toarray()
    dense_select = dense_desc[:, index[0]]

    return dense_select</code></pre>



<p>At the exit of this function the message does not contain any more <strong>stop words</strong>, it is put in the right format for the model thanks to the <code>transform</code> and is then represented as an <code>array</code>.</p>



<p>Now that the function for processing the input data is defined, you can pass the <code>GET</code> and <code>POST</code> methods.</p>



<p>First, let&#8217;s go for the <code>GET</code> method!</p>



<pre class="wp-block-code"><code class="">@app.get('/')
def root():
    return {'message': 'Welcome to the SPAM classifier API'}</code></pre>



<p>Here you can see the <em>welcome message</em> when you arrive on your API.</p>



<pre class="wp-block-preformatted"><code><strong>{"message":"Welcome to the SPAM classifier API"}</strong></code></pre>



<p>Now it&#8217;s the turn of the <code>POST</code> method. In this part of the code, you will be able to:</p>



<ul class="wp-block-list">
<li>define the message format</li>



<li>check if a message has been sent or not</li>



<li>process the message to fit with the model</li>



<li>extract the probabilities</li>



<li>return the results</li>
</ul>



<pre class="wp-block-code"><code class="">@app.post('/spam_detection_path')
def classify_message(data : request_body):

    message = [
        data.message
    ]

    if (not (message)):
        raise HTTPException(status_code=400, detail="Please Provide a valid text message")

    dense_select = process_message(message)

    label = model_logistic_regression.predict(dense_select)
    proba = model_logistic_regression.predict_proba(dense_select)

    if label[0]=='ham':
        label_proba = proba[0][0]
    else:
        label_proba = proba[0][1]

    return {'label': label[0], 'label_probability': label_proba}</code></pre>



<p><code><strong>❗ Again, you can find the full code <a href="https://github.com/ovh/ai-training-examples/blob/main/apps/fastapi/spam-classifier-api/app.py" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">here</a></strong></code>.</p>



<p>Before deploying your API, you can test it locally using the following command:</p>



<pre class="wp-block-code"><code class="">uvicorn app:app --reload</code></pre>



<p>Then, you can test your app locally at the following address:&nbsp;<strong><code>http://localhost:8000/</code></strong></p>



<p>You will arrive on the following page:</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" src="https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-4.png" alt="" class="wp-image-24217" width="590" height="721" srcset="https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-4.png 760w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-4-245x300.png 245w" sizes="auto, (max-width: 590px) 100vw, 590px" /></figure>



<p><strong>How to interact with your&nbsp;API?</strong></p>



<p>You can add&nbsp;<code>/docs</code>&nbsp;at the end of the url of your&nbsp;app: <strong><code>http://localhost:8000/</code></strong><code><strong>docs</strong></code></p>



<p>A new page opens to you. It provides a complete dashboard for interacting with the&nbsp;API!</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" src="https://blog.ovhcloud.com/wp-content/uploads/2022/12/image.png" alt="" class="wp-image-24213" width="590" height="722" srcset="https://blog.ovhcloud.com/wp-content/uploads/2022/12/image.png 760w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-245x300.png 245w" sizes="auto, (max-width: 590px) 100vw, 590px" /></figure>



<p>To be able to send a message for classification, select&nbsp;<code><strong>/spam_detection_path</strong></code>&nbsp;in the green box. Click on<strong>&nbsp;<code>Try</code></strong><code><strong> it out</strong></code>&nbsp;and type the message of your choice in the dedicated&nbsp;zone.</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" src="https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-2.png" alt="" class="wp-image-24215" width="596" height="729" srcset="https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-2.png 760w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-2-245x300.png 245w" sizes="auto, (max-width: 596px) 100vw, 596px" /></figure>



<p>Enter the message of your choice. It must be in the form of a <code><strong>string</strong></code>. </p>



<p><em>Example:</em> <code><strong>"A new free service for you only"</strong></code></p>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" src="https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-1.png" alt="" class="wp-image-24214" width="599" height="733" srcset="https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-1.png 760w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-1-245x300.png 245w" sizes="auto, (max-width: 599px) 100vw, 599px" /></figure>



<p>To get the result of the prediction, click on the&nbsp;<code><strong>Execute</strong></code>&nbsp;button.</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" src="https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-3.png" alt="" class="wp-image-24216" width="611" height="748" srcset="https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-3.png 760w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/image-3-245x300.png 245w" sizes="auto, (max-width: 611px) 100vw, 611px" /></figure>



<p>Finally, you obtain the result of the prediction with the&nbsp;<strong>label</strong>&nbsp;and the&nbsp;<strong>confidence&nbsp;score</strong>.</p>



<p>Your app works locally? Congratulations&nbsp;🎉 !</p>



<p>Now it’s time to move on to containerization!</p>



<h2 class="wp-block-heading">Containerize your app with Docker</h2>



<p>First of all, you have to build the file that will contain the different Python modules to be installed with their corresponding version.</p>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="574" src="https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-docker-1024x574.jpg" alt="docker image datascience" class="wp-image-24230" srcset="https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-docker-1024x574.jpg 1024w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-docker-300x168.jpg 300w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-docker-768x430.jpg 768w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-docker-1536x861.jpg 1536w, https://blog.ovhcloud.com/wp-content/uploads/2022/12/draw-docker.jpg 1620w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h3 class="wp-block-heading">Create the requirements.txt file</h3>



<p>The&nbsp;<code><a href="https://github.com/ovh/ai-training-examples/blob/main/apps/fastapi/spam-classifier-api/requirements.txt" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">requirements.txt</a></code>&nbsp;file will allow us to write all the modules needed to make our application work.</p>



<pre class="wp-block-code"><code class="">fastapi==0.87.0
pydantic==1.10.2
uvicorn==0.20.0
pandas==1.5.1
scikit-learn==1.1.3</code></pre>



<p>This file will be useful when writing the&nbsp;<code>Dockerfile</code>.</p>



<h3 class="wp-block-heading">Write the Dockerfile</h3>



<p>Your&nbsp;<code><a href="https://github.com/ovh/ai-training-examples/blob/main/apps/fastapi/spam-classifier-api/Dockerfile" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">Dockerfile</a></code>&nbsp;should start with the the&nbsp;<code>FROM</code>&nbsp;instruction indicating the parent image to use. In our case we choose to start from a classic Python image.</p>



<p>For this Streamlit app, you can use version&nbsp;<strong><code>3.8</code></strong>&nbsp;of Python.</p>



<pre class="wp-block-code"><code class="">FROM python:3.8</code></pre>



<p>Next, you have to to fill in the working directory and add all&nbsp;files into.</p>



<p><code><strong>❗&nbsp;Here you must be in the /workspace directory. This is the basic directory for launching an OVHcloud AI Deploy.</strong></code></p>



<pre class="wp-block-code"><code class="">WORKDIR /workspace
ADD . /workspace</code></pre>



<p>Install the&nbsp;<code>requirements.txt</code>&nbsp;file which contains your needed Python modules using a&nbsp;<code>pip install…</code>&nbsp;command.</p>



<pre class="wp-block-code"><code class="">RUN pip install -r requirements.txt</code></pre>



<p>Set the listening port of the&nbsp;container. For <strong>FastAPI</strong>, you can use the port <code>8000</code>.</p>



<pre class="wp-block-code"><code class="">EXPOSE 8000</code></pre>



<p>Then, you have to define the <strong>entrypoint</strong> and the <strong>default launching command</strong> to start the application.</p>



<pre class="wp-block-code"><code class="">ENTRYPOINT ["uvicorn"]
CMD [ "streamlit", "run", "/workspace/app.py", "--server.address=0.0.0.0" ]</code></pre>



<p>Finally, you can give correct access rights to OVHcloud user (<code>42420:42420</code>).</p>



<pre class="wp-block-code"><code class="">RUN chown -R 42420:42420 /workspace
ENV HOME=/workspace</code></pre>



<p>Once your&nbsp;<code>Dockerfile</code>&nbsp;is defined, you will be able to build your custom docker image.</p>



<h3 class="wp-block-heading">Build the Docker image from the Dockerfile</h3>



<p>First, you can launch the following command from the&nbsp;<code>Dockerfile</code>&nbsp;directory to build your application image.</p>



<pre class="wp-block-code"><code class="">docker build . -t fastapi-spam-classification:latest</code></pre>



<p>⚠️&nbsp;<strong><code>The dot . argument indicates that your build context (place of the Dockerfile and other needed files) is the current directory.</code></strong></p>



<p>⚠️&nbsp;<code><strong>The -t argument allows you to choose the identifier to give to your image. Usually image identifiers are composed of a name and a version tag &lt;name&gt;:&lt;version&gt;. For this example we chose fastapi-spam-classification:latest.</strong></code></p>



<h3 class="wp-block-heading">Test it locally</h3>



<p>Now, you can run the following&nbsp;<strong>Docker command</strong>&nbsp;to launch your application locally on your computer.</p>



<pre class="wp-block-code"><code class="">docker run --rm -it -p 8080:8080 --user=42420:42420 fastapi-spam-classification<span style="background-color: inherit;font-family: inherit;font-size: 1rem;font-weight: inherit">:latest</span></code></pre>



<p>⚠️&nbsp;<code><strong>The -p 8000:8000 argument indicates that you want to execute a port redirection from the port 8000 of your local machine into the port 8000 of the Docker container.</strong></code></p>



<p>⚠️<code><strong>&nbsp;Don't forget the --user=42420:42420 argument if you want to simulate the exact same behaviour that will occur on AI Deploy. It executes the Docker container as the specific OVHcloud user (user 42420:42420).</strong></code></p>



<p>Once started, your application should be available on&nbsp;<strong>http://localhost:8000</strong>.<br><br>Your Docker image seems to work? Good job&nbsp;👍 !<br><br>It’s time to push it and deploy it!</p>



<h3 class="wp-block-heading">Push the image into the shared registry</h3>



<p>❗&nbsp;The shared registry of AI Deploy should only be used for testing purpose. Please consider attaching your own Docker registry. More information about this can be found&nbsp;<a href="https://docs.ovh.com/asia/en/publiccloud/ai/training/add-private-registry/" data-wpel-link="exclude">here</a>.</p>



<p>Then, you have to find the address of your&nbsp;<code>shared registry</code>&nbsp;by launching this command.</p>



<pre class="wp-block-code"><code class="">ovhai registry list</code></pre>



<p>Next, log in on the shared registry with your usual&nbsp;<code>OpenStack</code>&nbsp;credentials.</p>



<pre class="wp-block-code"><code class="">docker login -u &lt;user&gt; -p &lt;password&gt; &lt;shared-registry-address&gt;</code></pre>



<p>To finish, you need to push the created image into the shared registry.</p>



<pre class="wp-block-code"><code class="">docker tag fastapi-spam-classification:latest &lt;shared-registry-address&gt;/fastapi-spam-classification:latest</code></pre>



<pre class="wp-block-code"><code class="">docker push &lt;shared-registry-address&gt;/fastapi-spam-classification:latest</code></pre>



<p>Once you have pushed your custom Docker image into the shared registry, you are ready to launch your app 🚀 !</p>



<h2 class="wp-block-heading">Launch the AI Deploy app</h2>



<p>The following command starts a new job running your <strong>FastAPI</strong> application.</p>



<pre class="wp-block-code"><code class="">ovhai app run \
      --default-http-port 8000 \
      --cpu 4 \
      &lt;shared-registry-address&gt;/fastapi-spam-classification:latest</code></pre>



<h3 class="wp-block-heading">Choose the compute resources</h3>



<p>First, you can either choose the number of GPUs or CPUs for your app.</p>



<p><code><strong>--cpu 4</strong></code>&nbsp;indicates that we request 4 CPUs for that app.</p>



<h3 class="wp-block-heading">Make the app public</h3>



<p>Finally, if you want your app to be accessible without the need to authenticate, specify it as follows.</p>



<p>Consider adding the&nbsp;<code><strong>--unsecure-http</strong></code>&nbsp;attribute if you want your application to be reachable without any authentication.</p>



<figure class="wp-block-video"></figure>



<h2 class="wp-block-heading">Conclusion</h2>



<p>Well done 🎉&nbsp;! You have learned how to build your&nbsp;<strong>own Docker image</strong>&nbsp;for a dedicated&nbsp;<strong>spam classification API</strong>!</p>



<p>You have also been able to deploy this app thanks to&nbsp;<strong>OVHcloud’s AI Deploy</strong>&nbsp;tool.</p>



<h3 class="wp-block-heading" id="want-to-find-out-more">Want to find out more?</h3>



<h5 class="wp-block-heading"><strong>Notebook</strong></h5>



<p>You want to access the notebook? Refer to the&nbsp;<a href="https://github.com/ovh/ai-training-examples/blob/main/notebooks/natural-language-processing/text-classification/miniconda/spam-classifier/notebook-spam-classifier.ipynb" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">GitHub repository</a>.</p>



<h5 class="wp-block-heading"><strong>App</strong></h5>



<p>You want to access to the full code to create the <strong>FastAPI</strong> API? Refer to the&nbsp;<a href="https://github.com/ovh/ai-training-examples/tree/main/apps/fastapi/spam-classifier-api" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">GitHub repository</a>.<br><br>To launch and test this app with&nbsp;<strong>AI Deploy</strong>, please refer to&nbsp;our&nbsp;<a href="https://docs.ovh.com/gb/en/publiccloud/ai/deploy/tuto-fastapi-spam-classifier/" data-wpel-link="exclude">documentation</a>.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li><a href="https://towardsdatascience.com/how-to-run-a-data-science-project-in-a-docker-container-2ab1a3baa889" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">How to Run a Data Science Project in a Docker Container</a></li>



<li><a href="https://towardsdatascience.com/step-by-step-approach-to-build-your-machine-learning-api-using-fast-api-21bd32f2bbdb" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">Step-by-step Approach to Build Your Machine Learning API Using Fast API</a></li>
</ul>
<img loading="lazy" decoding="async" src="//blog.ovhcloud.com/wp-content/plugins/matomo/app/matomo.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fblog.ovhcloud.com%2Fdeploy-a-custom-docker-image-for-data-science-project-a-spam-classifier-with-fastapi-part-3%2F&amp;action_name=Deploy%20a%20custom%20Docker%20image%20for%20Data%20Science%20project%20%E2%80%93%20A%20spam%20classifier%20with%20FastAPI%20%28Part%203%29&amp;urlref=https%3A%2F%2Fblog.ovhcloud.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
