Today, the marvels of Artificial Intelligence (AI) are transforming the landscape of various classification tasks. From identifying objects in images to categorizing data in complex datasets, AI has become a driving force in solving numerous classification challenges.
This tutorial will create a powerful Iris Flower Classification app using DelphiFMX and Support Vector Machines (SVM). Harnessing the prowess of machine learning and the Delphi ecosystem, we will enable users to classify iris flowers accurately and efficiently. Experience the excitement of building an ML-powered app with DelphiFMX and providing users with real-time insights into flower species right at their fingertips.
Table of Contents
Why Are Support Vector Machines Gaining Popularity?
Support Vector Machines (SVM) have become increasingly popular in machine learning due to their remarkable effectiveness in classification tasks. They exhibit versatility in handling binary and multi-class classification problems, making them suitable for various applications. SVMs thrive in high-dimensional feature spaces, making them well-suited for complex datasets, including text classification, image recognition, and bioinformatics. One of their key strengths lies in their robustness against overfitting leading to reliable generalization.
Additionally, SVMs utilize the kernel trick to efficiently deal with non-linearly separable data by transforming the feature space into a higher-dimensional space. This attribute and their memory efficiency ensure practical applicability with large datasets. Moreover, SVMs provide clear decision boundaries, contributing to their interpretability and explainability, which are essential in scenarios where understanding model reasoning is crucial.
How to Create the Iris Flower Classification App with DelphiFMX?
Creating a flower classification app involves several steps. Before we get into the detailed tutorial, let’s check the requirements for this project.
Install the RAD Studio with Delphi IDE and the DelphiFMX on your device to create the flower classification app. You will need a text editor or IDE that supports Python, such as PyScripter and the Delphi4PythonExporter tool. If you don’t have these tools installed, checking out the article “Powerful Python GUI Project Setup” is recommended.
You should also install Python’s scikit-learn library by running the following command in the cmd:
1 2 |
pip install -U scikit-learn |
You can retrieve the project code from the following GitHub link:
https://github.com/Embarcadero/PythonBlogExamples/tree/main/Iris_Flower_Classifier
Which Dataset Can be Used for Such a Task?
For the Iris Flower Classification app, the ideal dataset to use is the famous Iris dataset from the scikit-learn library. The Iris dataset is a well-known and widely used dataset in the field of machine learning. It contains 150 samples of iris flowers, with each sample representing a different iris species: setosa, versicolor, or virginica. For each sample, four features are recorded: sepal length, sepal width, petal length, and petal width.
How to Train a Support Vector Machine Classifier?
Training an SVM classifier is very simple in Python:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.svm import SVC # Load the Iris dataset iris = load_iris() X, y = iris.data, iris.target # Split the data into training and testing sets X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # Train the Support Vector Machine Classifier svm = SVC() svm.fit(X_train, y_train) |
The above code utilizes scikit-learn to train an SVM classifier for Iris flower classification. The Iris dataset is loaded, containing features and target labels representing different iris species. The data is split into training and testing sets, and an SVM classifier is instantiated. The classifier is then trained on the training data, learning to separate the iris species based on their features. The SVM algorithm aims to find the optimal decision boundary with the maximum margin between classes, making it a powerful tool for classification tasks like iris flower classification.
How to Design the User Interface with DelphiFMX?
Now that we know how to create our train our classifier let’s start creating our Delphi app.
Start by opening up Delphi CE and create a new project by navigating to File > New > Multi-Device Application > Blank Application > Ok
. For this tutorial, we are naming our project IrisFlowerClassifier
.
If you are unfamiliar with the various sections of the Delphi IDE, we recommend consulting our complimentary eBook bundle, which covers the Delphi Python Ecosystem and provides insights into all Python GUI offerings.
Next, we will rename our form. To do this, right-click on your form and select QuickEdit. This will open up your edit box. Here we will set our form name as MainForm
with the caption Iris Flower Classifier App
.
Now head over to the Projects tab on the top-right corner of your screen and locate the Unit1.pas
file. This is the source file of your form. We will rename it to Main.pas
to help us keep track of our form.
Finally, we will resize our form to make it more appealing. Select your form and head over to the Object Inspector. Here click on the properties tab and search for the ClientWidth
and ClientHeight
properties. We will resize our form by setting them to 360
and 500
, respectively.
With the basics out of the way, we can start by adding elements to our form. Head to the Palette in the bottom-right corner and search for the TLabel component. Now drag and drop this component on your form. We will add six labels to our form. Five of our Labels will be static, i.e. they will not change and will be used as indicators. This includes our title, sepal length, sepal width, petal length, and petal width labels which we’ve named as Title, SLength, SWidth, PLength
, and PWidth
. One of our labels which we’ve named Result
will be used to show the prediction of the flower.
Next, we will select each label and head over to the Object Inspector. Here we’ll customize the text style for each label using the TextSettings
property. Click on the ellipsis button (…) next to the Font
property to explore various options for modifying the label. As always, we will use the SemiBold Segue UI font family and distinct font sizes for each label. Additionally, we’ll set our labels’ HorzAlign
and VertAlign
properties to Center
.
Here is what our form looks like:
Next, let’s add a button to our form. This button will be used to trigger the prediction function. For this, we will use the TButton
component, so navigate to the Palette and search for the component.
Next, modify the button using its Text Settings property. Finally, rename the button and set its caption. Here we’ve named our button Predict
with the caption Classify Flower
. Here is what our form looks like:
Finally, let’s add text boxes before our labels to allow the user to input some text. To do this, open up the Palette and search for TEdit
. Add this component to your form. We will follow the same naming convention as our labels but add an Edit
to the end. For example, our sepal length edit box will be named as SLengthEdit
. Here is what our form looks like:
Now that our form is ready, we can add a few final touches by adding styles. To do this, download the free ebook bundle, which comes shipped with a multitude of styles that you can choose from.
Once your ebook has been downloaded, extract the FMX styles zip in your chosen directory. Next, select the style you want to use. Here we will be using AquaGraphite.style
available in the bundle.
To use this style, head to the Palette and add a TStyleBook
component to your form. The placement does not matter for this component, as it will be invisible.
Next, double-click on the StyleBook1
component. This will open up your Style Designer. Next, click on the open button to open up a dialog box.
Now navigate to the AquaGraphite.style
file in your styles directory, select your file, and click exit and save.
Now select your form and head over to the Object Inspector. Here search for the StyleBook property. Next, select the drop-down menu and select StyleBook1. This will add style to your form.
Here is what our final form looks like:
How to Put it Altogether?
Now that our form is ready, we need to add some functionality to the Predict
button so that we don’t lose it when we export it in Python. To do this, double-click the button on the form. This will add an OnClick
method to that button, creating a procedure in the .pas
file of the form. This allows you to add unique functionality to each button when clicked.
Because the Delphi4PythonExporter does not use run-time implementation, we must add at least one comment (//
) to each procedure to preserve the function when we export the form.
With this, we are ready to export our project. Select Tools > Export To Python > Export Current Entire Project
to export the project.
Here we will give the project the title Iris Flower Classifier App
. Next, select the directory of your choosing and click on Export:
Once the export is complete, head over to the project directory. Because we only had a single form, Delphi will generate two Python files and one .pyfmx
file. The IrisFlowerClassifier.py
file will be used to run the application, whereas the Main.py
file contains the class for the MainForm. The Main.pyfmx
file contains the visual information for the MainForm
. Here are the contents for each file.
IrisFlowerClassifier.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from delphifmx import * from Main import Form1 def main(): Application.Initialize() Application.Title = 'Iris Flower Classifier App' Application.MainForm = MainForm(Application) Application.MainForm.Show() Application.Run() Application.MainForm.Destroy() if __name__ == '__main__': main() |
Main.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import os from delphifmx import * class MainForm(Form): def __init__(self, owner): self.Title = None self.SLength = None self.SWidth = None self.PLength = None self.PWidth = None self.Result = None self.SLengthEdit = None self.SWidthEdit = None self.PLengthEdit = None self.PWidthEdit = None self.Predict = None self.StyleBook1 = None self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "Main.pyfmx")) def PredictClick(self, Sender): pass |
Now, let’s begin adding functionality to our code. Start by opening up Main.py
and importing the relevant libraries.
1 2 3 4 5 |
# Additional imports from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier |
Next, head over to the __init__
function. Here we will start by loading the Iris dataset, splitting the data set into testing and training sets, and finally, training the SVC model. Here is what our __init__
function will look like:
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 |
def __init__(self, owner): self.Title = None self.SLength = None self.SWidth = None self.PLength = None self.PWidth = None self.Result = None self.SLengthEdit = None self.SWidthEdit = None self.PLengthEdit = None self.PWidthEdit = None self.Predict = None self.StyleBook1 = None self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "Main.pyfmx")) # Load the Iris dataset self.iris = load_iris() X, y = self.iris.data, self.iris.target # Split the data into training and testing sets X_train, _, y_train, _ = train_test_split(X, y, test_size=0.2, random_state=42) # Train the SVC model self.knn = SVC() self.knn.fit(X_train, y_train) |
Next, lets move to the PredictButton
click function. This function will only be triggered when we click on the Classify Flower
button. To predict our flowers, we will first need to retrieve the values from our TEdit
boxes. So we will use a try-except
block so that our app does not crash.
Start by taking out the length and width values for the petal and sepal and convert them into floating point numbers inside the try
block. Next, convert these values into a nested list and pass them into the classifiers predict
function:
1 2 3 4 5 6 7 8 9 10 |
def PredictClick(self, Sender): # User input for flower measurements try: sepal_length = float(self.SLengthEdit.Text) sepal_width = float(self.SWidthEdit.Text) petal_length = float(self.PLengthEdit.Text) petal_width = float(self.PWidthEdit.Text) new_flower = [[sepal_length, sepal_width, petal_length, petal_width]] predicted_species = self.knn.predict(new_flower) |
Now map the predicted label to the corresponding name of the species, and show the result in the Result
label:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
def PredictClick(self, Sender): # User input for flower measurements try: sepal_length = float(self.SLengthEdit.Text) sepal_width = float(self.SWidthEdit.Text) petal_length = float(self.PLengthEdit.Text) petal_width = float(self.PWidthEdit.Text) new_flower = [[sepal_length, sepal_width, petal_length, petal_width]] predicted_species = self.knn.predict(new_flower) # Map the predicted label to the corresponding species name species_names = self.iris.target_names predicted_species_name = species_names[predicted_species[0]] self.Result.Text = "Species name: {}".format(predicted_species_name.capitalize()) |
Finally, if any of the fields are missing, we will return an error in our Result
label using the except
block. Here is what our PredictClick
function looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
def PredictClick(self, Sender): # User input for flower measurements try: sepal_length = float(self.SLengthEdit.Text) sepal_width = float(self.SWidthEdit.Text) petal_length = float(self.PLengthEdit.Text) petal_width = float(self.PWidthEdit.Text) new_flower = [[sepal_length, sepal_width, petal_length, petal_width]] predicted_species = self.knn.predict(new_flower) # Map the predicted label to the corresponding species name species_names = self.iris.target_names predicted_species_name = species_names[predicted_species[0]] self.Result.Text = "Species Name: {}".format(predicted_species_name.capitalize()) except: self.Result.Text = "Error! Incomplete or invalid input fields." |
Here is what our final Main.py
file looks like:
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 |
import os from delphifmx import * # Additional imports from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.svm import SVC class MainForm(Form): def __init__(self, owner): self.Title = None self.SLength = None self.SWidth = None self.PLength = None self.PWidth = None self.Result = None self.SLengthEdit = None self.SWidthEdit = None self.PLengthEdit = None self.PWidthEdit = None self.Predict = None self.StyleBook1 = None self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "Main.pyfmx")) # Load the Iris dataset self.iris = load_iris() X, y = self.iris.data, self.iris.target # Split the data into training and testing sets X_train, _, y_train, _ = train_test_split(X, y, test_size=0.2, random_state=42) # Train the SVC model self.knn = SVC() self.knn.fit(X_train, y_train) def PredictClick(self, Sender): # User input for flower measurements try: sepal_length = float(self.SLengthEdit.Text) sepal_width = float(self.SWidthEdit.Text) petal_length = float(self.PLengthEdit.Text) petal_width = float(self.PWidthEdit.Text) new_flower = [[sepal_length, sepal_width, petal_length, petal_width]] predicted_species = self.knn.predict(new_flower) # Map the predicted label to the corresponding species name species_names = self.iris.target_names predicted_species_name = species_names[predicted_species[0]] self.Result.Text = "Species Name: {}".format(predicted_species_name.capitalize()) except: self.Result.Text = "Error! Incomplete or invalid input fields." |
Does the App Meet Expectations When Tested?
Now that our application is ready, let’s test it out. Head over to IrisFlowerClassifier.py
and run the file.
Let’s add a few values to our app that satisfy the values for the Setosa flower:
Finally, click on the Classify button to get the prediction:
Now, let’s test it out for another random flower:
Clicking on the Classify button, we get the prediction that our random flower is actually Verginica:
Are You Ready to Create ML-Powered Apps of Your Own?
Building image classification apps is both a fascinating and rewarding endeavor. It empowers developers to accurately identify and classify objects within images, opening up a world of possibilities for diverse applications. We recommend exploring the Delphi ecosystem to streamline your development journey and unlock enhanced potential. With DelphiFMX at its core, alongside Delphi IDE and Delphi4PythonExporter, you gain access to a comprehensive suite of tools and frameworks for GUI development, seamlessly integrating with Python ML backends.
What Are Some FAQs Related to this Topic?
What is a Support Vector Machine (SVM)?
A Support Vector Machine is a supervised machine learning algorithm used for classification and regression tasks. It aims to find the optimal hyperplane that best separates different classes in the data.
Can SVM handle imbalanced datasets?
SVMs can be sensitive to imbalanced datasets. Techniques like class weighting or using different cost functions can be applied to address this issue.
What are the advantages of using SVM over other classifiers?
SVMs are effective in high-dimensional spaces, robust against overfitting, and have good generalization properties. They work well with both small and large datasets.
What is DelphiFMX (FireMonkey)?
DelphiFMX (FireMonkey) is a powerful cross-platform GUI (Graphical User Interface) framework provided by Embarcadero’s Delphi IDE. It enables developers to create visually stunning and responsive user interfaces for applications running on multiple platforms, such as Windows, macOS, iOS, and Android, using a single codebase.
What are the key advantages of using DelphiFMX?
DelphiFMX offers several advantages, including cross-platform support, native performance on different operating systems, access to native controls, and the ability to create visually appealing apps with rich animations and effects.
Can I use third-party components with DelphiFMX?
Yes, DelphiFMX allows developers to use third-party components and libraries to extend the functionality of their applications. This flexibility enables developers to integrate additional features and tools into their projects.