In this tutorial, you will be introduced to the world of Machine Learning (ML) with Python. To understand ML practically, you will be using a well-known machine learning algorithm called K-Nearest Neighbor (KNN) with Python.
You will be implementing KNN on the famous Iris dataset.
Note: You might want to consider taking up the course on Machine Learning with Python or for a background on how ML evolved and a lot more consider reading this post.
Introduction
Machine Learning evolved from computer science that primarily studies the design of algorithms that can learn from experience. To learn, they need data that has certain attributes based on which the algorithms try to find some meaningful predictive patterns. Majorly, ML tasks can be categorized as concept learning, clustering, predictive modeling, etc. The ultimate goal of ML algorithms is to be able to take decisions without any human intervention correctly. Predicting the stocks or weather are a couple of applications of machine learning algorithms.
There are various machine learning algorithms like Decision trees, Naive Bayes, Random forest, Support vector machine, K-nearest neighbor, K-means clustering, etc.
From the class of machine learning algorithms, the one that you will be using today is k-nearest neighbor.
Now, the question is what exactly is K-Nearest Neighbor algorithm, so let us find out!
What is a k-Nearest Neighbor?
The KNN or k-nearest neighbor algorithm is a supervised learning algorithm, by supervise it means that it makes use of the class labels of training data during the learning phase. It is an instance-based machine learning algorithm, where new data points are classified based on stored, labeled instances (data points). KNN can be used both for classification and regression; however, it is more widely used for classification purposes.
The k in KNN is a crucial variable also known as a hyperparameter that helps in classifying a data point accurately. More, precisely, the k is the number of nearest neighbors you wish to take a vote from when classifying a new data point.
You can see as the value of k increases from 1 to 7, the decision boundary between two classes having some data points becomes more Smoother.
Now the question is how does all of this magic happen, wherein every time a new data point comes in, it is classified based on the stored data points?
So, let's quickly understand it in the following ways:
Firstly, you load all the data and initialize the value of k,
Then, the distance between the stored data points and a new data point that you want to classify is calculated using various similarity or distance metrics like Manhattan distance (L1), Euclidean distance (L2), Cosine similarity, Bhattacharyya distance, Chebyshev distance, etc.
Next, the distance values are sorted either in descending or ascending order and top or lower k-nearest neighbors are determined.
The labels of the k-nearest neighbors are gathered, and a majority vote or a weighted vote is used for classifying the new data point. The new data point is assigned a class label based on a certain data point that has the highest score out of all the stored data points.
Finally, the predicted class for the new instance is returned.
The prediction can be of two types: either classification in which a class label is assigned to a new data point or regression wherein a value is assigned to the new data point. Unlike classification, in regression, the mean of all the k-nearest neighbors is assigned to the new data point.
Drawback of KNN: Firstly, complexity in searching the nearest neighbor for each new data point. Secondly, determining the value of k sometimes becomes a tedious task. Finally, it is also not clear which type of distance metric one should use while computing the nearest neighbors.
Enough of theory right? So, let's load, analyze and understand the data that you will be using in today's small tutorial.
Loading the Iris Data
Iris data set consists of 150 samples having three classes namely Iris-Setosa, Iris-Versicolor, and Iris-Virginica. Four features/attributes contribute to uniquely identifying as one of the three classes are sepal-length, sepal-width, petal-length and petal-width.
Feel free to use some other public dataset or your private dataset.
Sklearn is a machine learning python library that is widely used for data-science related tasks. It features various classification, regression and clustering algorithms including support vector machines, random forests, gradient boosting, k-means, KNN, etc.. Under sklearn you have a library called datasets in which you have multiple datasets that can be used for different tasks including the Iris dataset, all these datasets can be loaded out of the box. It is pretty intuitive and straightforward. So, let's quickly load the iris dataset.
Next, you have to combine the data and the class labels, and for that, you will use an excellent python library called NumPy. NumPy adds support for large, multi-dimensional arrays and matrices, along with an extensive collection of high-level mathematical functions to operate on these arrays. So, let's quickly import it!
Now, you will use the concatenate function available in the numpy library, and you will use axis=-1 which will concatenate based on the second dimension.
Next, you will import python's data analysis library called pandas which is useful when you want to arrange your data in a tabular fashion and perform some operations and manipulations on the data. In particular, it offers data structures and operations for manipulating numerical tables and time series.
In today's tutorial, you will use pandas quite extensively.
Now, you have the dataset data frame that has both data & the class labels that you need!
Before you dive any further, remember that the labels variable has class labels as numeric values, but you will convert the numeric values as the flower names or species.
For doing this, you will select only the class column and replace each of the three numeric values with the corresponding species. You will use inplace=True which will modify the data frame dataset.
Let's quickly find out how all the three flowers look like when visualized and how different they are from each other not just in numbers but also in real!
Let's visualize the data that you loaded above using a scatterplot to find out how much one variable is affected by the other variable or let's say how much correlation is between the two variables.
You will use matplotlib library to visualize the data using a scatterplot.
From the above plot, it is very much apparent that there is a high correlation between the Iris setosa flowers w.r.t the sepal length and sepal width. On the other hand, there is less correlation between Iris versicolor and Iris virginica. The data points in versicolor & virginica are more spread out compared to setosa that are dense.
Let's just quickly also plot the graph for petal-length and petal-width.
Even when it comes to petal-length and petal-width, the above graph indicates a strong correlation for setosa flowers which are densely clustered together.
Next, to further validate the claim of how petal-length and petal-width are correlated, let's plot a correlation matrix for all the three species.
From the above three tables, it is pretty much clear that the correlation between petal-length and petal-width of setosa and virginica is 0.33 and 0.32 respectively. Whereas, for versicolor it is 0.78.
Next, let's visualize the feature distribution by plotting the histograms:
The petal-length, petal-width, and sepal-length shows a unimodal distribution, whereas sepal-width shows a kind of Gaussian distribution. All these are useful analysis because then you can think of using an algorithm that works well with this kind of distribution.
Next, you will analyze whether all the four attributes are on the same scale or not; this is an essential aspect of ML. pandas data frame has an inbuilt function called describe that gives you the count, mean, max, min of the data in a tabular format.
You can see that all the four attributes have a similar scale between 0 & 8 and are in centimeters if you want you can further scale it down to between 0 and 1.
Even though you all know that there are 50 samples per class, i.e., ~33.3% of the total distribution, but still let's recheck it!
After having loaded the data and analyzed it extensively, it is time to prepare your data which you can then feed to your ML model. In this section, you will preprocess your data in two ways: normalizing your data and splitting your data into training and testing sets.
Normalizing your data
There can be two ways by which you can normalize your data:
Example normalization wherein you normalize each sample individually,
Feature normalization in which you normalize each feature in the same way across all samples.
Now the question is why or when do you need to normalize your data? And do you need to standardize the Iris data?
Well, the answer is pretty much all the time. It is a good practice to normalize your data as it brings all the samples in the same scale and range. Normalizing the data is crucial when the data you have is not consistent. You can check for inconsistency by using the describe() function that you studied above which will give you max and min values. If the max and min values of one feature are significantly larger than the other feature then normalizing both the features to the same scale is very important.
Let's say X is one feature having a larger range and Y being the second feature with a smaller range. Then, the influence of feature Y can be overpowered by feature X's influence. In such a case, it becomes important to normalize both the features X and Y.
In Iris data, normalization is not required.
Let's print the describe() function again and see why you do not need any normalization.
The sepal-length attribute has values that go from 4.3 to 7.9 and sepal-width contains values from 2 to 4.4, while petal-length values range from 1 to 6.9 and petal-width ranges from 0.1 to 2.5. The values of all the features are within the range of 0.1 and 7.9, which you can consider acceptable. Hence, you do not need to apply any normalization to the Iris dataset.
Splitting the data
This is another significant aspect of machine learning since your goal is to make a model capable enough to be able to take decisions or classify data in a test environment without any human intervention. Hence, before deploying your ML model in the industry, you need to make sure that the model can generalize well on the testing data.
For this purpose, you need a training and testing set. Coming back to the Iris data, you have 150 samples, you will be training your ML model on 80% of the data and the remaining 20% of the data will be used for testing.
In data-science, you will often come across a term called Overfitting which means that your model has learned the training data very well but fails to perform on the testing data. So, splitting the data into training and testing or validation set will often help you to know whether your model is overfitting or not.
For training and testing set split, you will use the sklearn library which has an in-built splitting function called train_test_split. So, let's split the data.
Note that the random_state is a seed that takes a random_state as input if you change the number the split of the data will also change. However, if you keep the random_state same and run the cell multiple times the data splitting will remain unchanged.
Let's quickly print the shape of training and testing data along with its labels.
Finally, it's time to feed the data to the k-nearest neighbor algorithm!
The KNN Model
After all the loading, analyzing and preprocessing of the data, it is now time when you will feed the data into the KNN model. To do this, you will use sklearn's inbuilt function neighbors which has a class called KNeigborsClassifier in it.
Let's start by importing the classifier.
from sklearn.neighbors import KNeighborsClassifier
Note: the k (n_neighbors) parameter is often an odd number to avoid ties in the voting scores.
In order to decide the best value for hyperparameter k, you will do something called grid-search. You will train and test your model on 10 different k values and finally use the one that gives you the best results.
Let's initialize a variable neighbors(k) which will have values ranging from 1-9 and two numpy zero matrices namely train_accuracy and test_accuracy each for training and testing accuracy. You will need them later to plot a graph to choose the best neighbor value.
Next piece of code is where all the magic will happen. You will enumerate over all the nine neighbor values and for each neighbor you will then predict both on training and testing data. Finally, store the accuracy in the train_accuracy and test_accuracy numpy arrays.
for i,k inenumerate(neighbors):
knn = KNeighborsClassifier(n_neighbors=k)#Fit the model
knn.fit(train_data, train_label)#Compute accuracy on the training set
train_accuracy[i]= knn.score(train_data, train_label)#Compute accuracy on the test set
test_accuracy[i]= knn.score(test_data, test_label)
Next, you will plot the training and testing accuracy using matplotlib, with accuracy vs. varying number of neighbors graph you will be able to choose the best k value at which your model performs the best.
plt.figure(figsize=(10,6))
plt.title('KNN accuracy with varying number of neighbors',fontsize=20)
plt.plot(neighbors, test_accuracy, label='Testing Accuracy')
plt.plot(neighbors, train_accuracy, label='Training accuracy')
plt.legend(prop={'size':20})
plt.xlabel('Number of neighbors',fontsize=20)
plt.ylabel('Accuracy',fontsize=20)
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.show()
Well, by looking at the above graph, it looks like when n_neighbors=3, both the model performs the best. So, let's stick with n_neighbors=3 and re-run the training once again.
knn = KNeighborsClassifier(n_neighbors=3)#Fit the model
knn.fit(train_data, train_label)#Compute accuracy on the training set
train_accuracy = knn.score(train_data, train_label)#Compute accuracy on the test set
test_accuracy = knn.score(test_data, test_label)
In the last segment of this tutorial, you will be evaluating your model on the testing data using a couple of techniques like confusion_matrix and classification_report.
Let's first check the accuracy of the model on the testing data.
Viola! It looks like the model was able to classify 96.66% of the testing data correctly. Isn't that amazing? With just a few lines of code, you were able to train an ML model that is now able to tell you the flower name by using only four features with 96.66% accuracy. Who knows maybe it performed way better than a human can.
Confusion Matrix
A confusion matrix is mainly used to describe the performance of your model on the test data for which the true values or labels are known.
Scikit-learn provides a function that calculates the confusion matrix for you.
From the above confusion_matrix plot, you can observe that the model classified all the flowers correctly except one virginica flower which is classified as a versicolor flower.
Classification Report
Classification report helps you in identifying the misclassified classes in much more detail by giving precision, recall and F1 score for each class. You will use the sklearn library to visualize the classification report.
First of all congratulations to all those who successfully made it till the end! But this was just the start. There is still a long way to go!
This tutorial majorly dealt with the basics of machine learning and the implementation of one kind of ML algorithm known as KNN with Python. The Iris data set that you used was pretty small and a little simple.
If this tutorial ignited an interest in you to learn more, you can try using some other datasets or try learning about some more ML algorithms and maybe apply on the Iris dataset to observe the effect on the accuracy. This way you will learn a lot more than just understanding the theory!
If you have experimented enough with the basics presented in this tutorial and other machine learning algorithms, you might want to go further into python and data analysis.
This article covers how and when to use k-nearest neighbors classification with scikit-learn. Focusing on concepts, workflow, and examples. We also cover distance metrics and how to select the best value for k using cross-validation.
You will be implementing KNN on the famous Iris dataset.
Note: You might want to consider taking up the course on Machine Learning with Python or for a background on how ML evolved and a lot more consider reading this post.
Introduction
Machine Learning evolved from computer science that primarily studies the design of algorithms that can learn from experience. To learn, they need data that has certain attributes based on which the algorithms try to find some meaningful predictive patterns. Majorly, ML tasks can be categorized as concept learning, clustering, predictive modeling, etc. The ultimate goal of ML algorithms is to be able to take decisions without any human intervention correctly. Predicting the stocks or weather are a couple of applications of machine learning algorithms.
There are various machine learning algorithms like Decision trees, Naive Bayes, Random forest, Support vector machine, K-nearest neighbor, K-means clustering, etc.
From the class of machine learning algorithms, the one that you will be using today is k-nearest neighbor.
Now, the question is what exactly is K-Nearest Neighbor algorithm, so let us find out!
What is a k-Nearest Neighbor?
The KNN or k-nearest neighbor algorithm is a supervised learning algorithm, by supervise it means that it makes use of the class labels of training data during the learning phase. It is an instance-based machine learning algorithm, where new data points are classified based on stored, labeled instances (data points). KNN can be used both for classification and regression; however, it is more widely used for classification purposes.
The k in KNN is a crucial variable also known as a hyperparameter that helps in classifying a data point accurately. More, precisely, the k is the number of nearest neighbors you wish to take a vote from when classifying a new data point.
You can see as the value of k increases from 1 to 7, the decision boundary between two classes having some data points becomes more Smoother.
Now the question is how does all of this magic happen, wherein every time a new data point comes in, it is classified based on the stored data points?
So, let's quickly understand it in the following ways:
The prediction can be of two types: either classification in which a class label is assigned to a new data point or regression wherein a value is assigned to the new data point. Unlike classification, in regression, the mean of all the k-nearest neighbors is assigned to the new data point.
Drawback of KNN: Firstly, complexity in searching the nearest neighbor for each new data point. Secondly, determining the value of k sometimes becomes a tedious task. Finally, it is also not clear which type of distance metric one should use while computing the nearest neighbors.
Enough of theory right? So, let's load, analyze and understand the data that you will be using in today's small tutorial.
Loading the Iris Data
Iris data set consists of 150 samples having three classes namely
Iris-Setosa,Iris-Versicolor, andIris-Virginica. Four features/attributes contribute to uniquely identifying as one of the three classes aresepal-length,sepal-width,petal-lengthandpetal-width.Feel free to use some other public dataset or your private dataset.
Sklearnis a machine learning python library that is widely used for data-science related tasks. It features various classification, regression and clustering algorithms includingsupport vector machines,random forests,gradient boosting,k-means,KNN, etc.. Undersklearnyou have a library calleddatasetsin which you have multiple datasets that can be used for different tasks including theIrisdataset, all these datasets can be loaded out of the box. It is pretty intuitive and straightforward. So, let's quickly load theirisdataset.load_irishas both the data and the class labels for each sample. Let's quickly extract all of it.datavariable will be a numpy array of shape (150,4) having 150 samples each having four different attributes. Each class has 50 samples each.Let's extract the class labels.
Next, you have to combine the data and the class labels, and for that, you will use an excellent python library called
NumPy.NumPyadds support for large, multi-dimensional arrays and matrices, along with an extensive collection of high-level mathematical functions to operate on these arrays. So, let's quickly import it!Since
datais a 2-d array, you will have to reshape thelabelsalso to a 2-d array.Now, you will use the
concatenatefunction available in thenumpylibrary, and you will useaxis=-1which will concatenate based on the second dimension.Next, you will import python's data analysis library called
pandaswhich is useful when you want to arrange your data in a tabular fashion and perform some operations and manipulations on the data. In particular, it offers data structures and operations for manipulating numerical tables and time series.In today's tutorial, you will use
pandasquite extensively.Now, you have the
datasetdata frame that has both data & the class labels that you need!Before you dive any further, remember that the
labelsvariable has class labels as numeric values, but you will convert the numeric values as the flower names or species.For doing this, you will select only the
classcolumn and replace each of the three numeric values with the corresponding species. You will useinplace=Truewhich will modify the data framedataset.Let's print the first five rows of the
datasetand see what it looks like!Analyze your Data
Let's quickly find out how all the three flowers look like when visualized and how different they are from each other not just in numbers but also in real!
Let's visualize the data that you loaded above using a
scatterplotto find out how much one variable is affected by the other variable or let's say how much correlation is between the two variables.You will use
matplotliblibrary to visualize the data using a scatterplot.Tip: Are you keen on learning different ways of visualizing the data in python? Then check out Introduction to data visualization with matplotlib course.
From the above plot, it is very much apparent that there is a high correlation between the Iris setosa flowers w.r.t the sepal length and sepal width. On the other hand, there is less correlation between Iris versicolor and Iris virginica. The data points in versicolor & virginica are more spread out compared to setosa that are dense.
Let's just quickly also plot the graph for
petal-lengthandpetal-width.Even when it comes to
petal-lengthandpetal-width, the above graph indicates a strong correlation for setosa flowers which are densely clustered together.Next, to further validate the claim of how
petal-lengthandpetal-widthare correlated, let's plot a correlation matrix for all the three species.The above table signifies a strong correlation of
0.96forpetal-lengthandpetal-widthwhen all three species are combined.Let's also analyze the correlation between all three species separately.
From the above three tables, it is pretty much clear that the correlation between
petal-lengthandpetal-widthofsetosaandvirginicais0.33and0.32respectively. Whereas, forversicolorit is0.78.Next, let's visualize the feature distribution by plotting the histograms:
The
petal-length,petal-width, andsepal-lengthshows a unimodal distribution, whereassepal-widthshows a kind of Gaussian distribution. All these are useful analysis because then you can think of using an algorithm that works well with this kind of distribution.Next, you will analyze whether all the four attributes are on the same scale or not; this is an essential aspect of ML.
pandasdata frame has an inbuilt function calleddescribethat gives you thecount,mean,max,minof the data in a tabular format.You can see that all the four attributes have a similar scale between 0 & 8 and are in centimeters if you want you can further scale it down to between 0 and 1.
Even though you all know that there are 50 samples per class, i.e., ~33.3% of the total distribution, but still let's recheck it!
Preprocessing your Data
After having loaded the data and analyzed it extensively, it is time to prepare your data which you can then feed to your ML model. In this section, you will preprocess your data in two ways: normalizing your data and splitting your data into training and testing sets.
Normalizing your data
There can be two ways by which you can normalize your data:
Now the question is why or when do you need to normalize your data? And do you need to standardize the
Irisdata?Well, the answer is pretty much all the time. It is a good practice to normalize your data as it brings all the samples in the same scale and range. Normalizing the data is crucial when the data you have is not consistent. You can check for inconsistency by using the
describe()function that you studied above which will give youmaxandminvalues. If themaxandminvalues of one feature are significantly larger than the other feature then normalizing both the features to the same scale is very important.Let's say X is one feature having a larger range and Y being the second feature with a smaller range. Then, the influence of feature Y can be overpowered by feature X's influence. In such a case, it becomes important to normalize both the features X and Y.
In
Irisdata, normalization is not required.Let's print the
describe()function again and see why you do not need any normalization.The
sepal-lengthattribute has values that go from 4.3 to 7.9 andsepal-widthcontains values from 2 to 4.4, whilepetal-lengthvalues range from 1 to 6.9 andpetal-widthranges from 0.1 to 2.5. The values of all the features are within the range of 0.1 and 7.9, which you can consider acceptable. Hence, you do not need to apply any normalization to theIrisdataset.Splitting the data
This is another significant aspect of machine learning since your goal is to make a model capable enough to be able to take decisions or classify data in a test environment without any human intervention. Hence, before deploying your ML model in the industry, you need to make sure that the model can generalize well on the testing data.
For this purpose, you need a training and testing set. Coming back to the
Irisdata, you have 150 samples, you will be training your ML model on 80% of the data and the remaining 20% of the data will be used for testing.In data-science, you will often come across a term called
Overfittingwhich means that your model has learned the training data very well but fails to perform on the testing data. So, splitting the data into training and testing or validation set will often help you to know whether your model is overfitting or not.For training and testing set split, you will use the
sklearnlibrary which has an in-built splitting function calledtrain_test_split. So, let's split the data.Note that the
random_stateis a seed that takes arandom_stateas input if you change the number the split of the data will also change. However, if you keep therandom_statesame and run the cell multiple times the data splitting will remain unchanged.Let's quickly print the shape of training and testing data along with its labels.
Finally, it's time to feed the data to the k-nearest neighbor algorithm!
The KNN Model
After all the loading, analyzing and preprocessing of the data, it is now time when you will feed the data into the KNN model. To do this, you will use
sklearn'sinbuilt functionneighborswhich has a class calledKNeigborsClassifierin it.Let's start by importing the classifier.
Note: the k (n_neighbors) parameter is often an odd number to avoid ties in the voting scores.
In order to decide the best value for hyperparameter k, you will do something called
grid-search. You will train and test your model on 10 different k values and finally use the one that gives you the best results.Let's initialize a variable
neighbors(k)which will have values ranging from 1-9 and two numpy zero matrices namelytrain_accuracyandtest_accuracyeach for training and testing accuracy. You will need them later to plot a graph to choose the bestneighborvalue.Next piece of code is where all the magic will happen. You will
enumerateover all the nine neighbor values and for each neighbor you will then predict both on training and testing data. Finally, store the accuracy in thetrain_accuracyandtest_accuracynumpy arrays.Next, you will plot the training and testing accuracy using
matplotlib, withaccuracy vs. varying number of neighborsgraph you will be able to choose the best k value at which your model performs the best.Well, by looking at the above graph, it looks like when
n_neighbors=3, both the model performs the best. So, let's stick withn_neighbors=3and re-run the training once again.Evaluating your Model
In the last segment of this tutorial, you will be evaluating your model on the testing data using a couple of techniques like
confusion_matrixandclassification_report.Let's first check the accuracy of the model on the testing data.
Viola! It looks like the model was able to classify 96.66% of the testing data correctly. Isn't that amazing? With just a few lines of code, you were able to train an ML model that is now able to tell you the flower name by using only four features with 96.66% accuracy. Who knows maybe it performed way better than a human can.
Confusion Matrix
A confusion matrix is mainly used to describe the performance of your model on the test data for which the true values or labels are known.
Scikit-learnprovides a function that calculates the confusion matrix for you.The following
plot_confusion_matrix()function has been modified and acquired from this source.From the above
confusion_matrixplot, you can observe that the model classified all the flowers correctly except one virginica flower which is classified as a versicolor flower.Classification Report
Classification report helps you in identifying the misclassified classes in much more detail by giving
precision,recallandF1 scorefor each class. You will use thesklearnlibrary to visualize the classification report.Go Further!
First of all congratulations to all those who successfully made it till the end! But this was just the start. There is still a long way to go!
This tutorial majorly dealt with the basics of machine learning and the implementation of one kind of ML algorithm known as KNN with Python. The Iris data set that you used was pretty small and a little simple.
If this tutorial ignited an interest in you to learn more, you can try using some other datasets or try learning about some more ML algorithms and maybe apply on the Iris dataset to observe the effect on the accuracy. This way you will learn a lot more than just understanding the theory!
If you have experimented enough with the basics presented in this tutorial and other machine learning algorithms, you might want to go further into python and data analysis.