"""
# <center>Iris Species Classification</center>
<div style="width:100%;text-align: center;"> <img align = middle src="https://hellor.netlify.app/slides/iris_flower_dataset.png" style="height:300px;"> </div>
"""
"""
# About the Dataset
Description of the data given:
- **Id**: Unique number for each row
- **SepalLengthCm**: Length of the sepal (in cm)
- **SepalWidthCm**: Width of the sepal (in cm)
- **PetalLengthCm**: Length of the petal (in cm)
- **PetalWidthCm**: Width of the petal (in cm)
- **Species**: Name of the species
"""
"""
# Importing the Necessary Libraries
"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
import graphviz
import seaborn as sns
import os
import plotly_express as px
from plotly.subplots import make_subplots
import plotly.graph_objects as go

from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import StandardScaler

from sklearn.model_selection import train_test_split

from sklearn.linear_model import LogisticRegression

from sklearn.neighbors import KNeighborsClassifier
from sklearn.neighbors import RadiusNeighborsClassifier

from sklearn.naive_bayes import GaussianNB

from sklearn.svm import SVC

from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis

from sklearn import tree
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.ensemble import BaggingClassifier
from sklearn.ensemble import GradientBoostingClassifier

from xgboost import XGBClassifier

from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix

import warnings
warnings.filterwarnings('ignore')
"""
<h3>Taking a look at the input files</h3>
"""
for dirname, _, filenames in os.walk('/kaggle/input'):
    for filename in filenames:
        print(os.path.join(dirname, filename))
"""
<h3>Reading the input file</h3>
"""
df = pd.read_csv('/kaggle/input/iris/Iris.csv')
df
"""
<h3>Lets take a look at the information in our dataset</h3>
"""
df.info()
"""
<h3>Looking at the statistics of our dataset</h3>
"""
df.describe()
"""
<h3>Lets check for any missing values in the dataset</h3>
"""
print("Total number of missing values")
print(30 * "-")
print(df.isna().sum())
print(30 * "-")
print("Total missing values are:", df.isna().sum().sum())
print(30 * "-")
"""
Removing the `Id` column from our dataset as it is not needed to peform EDA (Exploratory Data Analysis).
"""
df.drop(columns = ['Id'], axis = 1, inplace = True)
df
"""
Taking a look at the different types of `Species` and counting the total number of unique values so that we can look the class distribution of our dataset.
"""
print("The different Species in the dataset are:", df['Species'].unique())
print("The total number of unique species are:", df['Species'].nunique())
"""
# Exploratory Data Analysis
We should try to visualize the distribution of the `Species` in our dataset to see if the classes are balanced.
"""
count_list = [(df.Species == 'Iris-setosa').sum(), (df.Species == 'Iris-versicolor').sum(), (df.Species == 'Iris-virginica').sum()]
label_list = list(df['Species'].unique())
plt.figure(figsize = (10, 7))
plt.pie(count_list, labels = label_list, autopct = "%.2f %%", startangle = 90, explode = (0.1, 0.1, 0.0), textprops = {'fontsize': 12})
plt.title('Distribution of Classes', fontsize = 20)
plt.show()
"""
The classes are equally balanced. Now, let us look at the count of each flower type in our dataset.
"""
print("The distribution of the classes is:\n", df['Species'].value_counts(), sep = "")
"""
# Univariate Analysis
Univariate analysis is the simplest form of analyzing data. We only take a single variable into consideration and try to find relations based on that. 
"""
fig = plt.figure(figsize = (15, 10))

ax1 = fig.add_subplot(2, 2, 1)
ax2 = fig.add_subplot(2, 2, 2)
ax3 = fig.add_subplot(2, 2, 3)
ax4 = fig.add_subplot(2, 2, 4)

ax1.plot((df[df['Species'] == 'Iris-setosa'])['SepalLengthCm'], np.zeros_like((df[df['Species'] == 'Iris-setosa'])['SepalLengthCm']), 'ro')
ax1.plot((df[df['Species'] == 'Iris-virginica'])['SepalLengthCm'], np.zeros_like((df[df['Species'] == 'Iris-virginica'])['SepalLengthCm']), 'go')
ax1.plot((df[df['Species'] == 'Iris-versicolor'])['SepalLengthCm'], np.zeros_like((df[df['Species'] == 'Iris-versicolor'])['SepalLengthCm']), 'bo')
ax1.set_title('Analysis of Sepal Length', size = 20)
ax1.get_yaxis().set_visible(False)

ax2.plot((df[df['Species'] == 'Iris-setosa'])['SepalWidthCm'], np.zeros_like((df[df['Species'] == 'Iris-setosa'])['SepalWidthCm']), 'ro')
ax2.plot((df[df['Species'] == 'Iris-virginica'])['SepalWidthCm'], np.zeros_like((df[df['Species'] == 'Iris-virginica'])['SepalWidthCm']), 'go')
ax2.plot((df[df['Species'] == 'Iris-versicolor'])['SepalWidthCm'], np.zeros_like((df[df['Species'] == 'Iris-versicolor'])['SepalWidthCm']), 'bo')
ax2.set_title('Analysis of Sepal Width', size = 20)
ax2.get_yaxis().set_visible(False)

ax3.plot((df[df['Species'] == 'Iris-setosa'])['PetalLengthCm'], np.zeros_like((df[df['Species'] == 'Iris-setosa'])['PetalLengthCm']), 'ro')
ax3.plot((df[df['Species'] == 'Iris-virginica'])['PetalLengthCm'], np.zeros_like((df[df['Species'] == 'Iris-virginica'])['PetalLengthCm']), 'go')
ax3.plot((df[df['Species'] == 'Iris-versicolor'])['PetalLengthCm'], np.zeros_like((df[df['Species'] == 'Iris-versicolor'])['PetalLengthCm']), 'bo')
ax3.set_title('Analysis of Petal Length', size = 20)
ax3.get_yaxis().set_visible(False)

ax4.plot((df[df['Species'] == 'Iris-setosa'])['PetalWidthCm'], np.zeros_like((df[df['Species'] == 'Iris-setosa'])['PetalWidthCm']), 'ro')
ax4.plot((df[df['Species'] == 'Iris-virginica'])['PetalWidthCm'], np.zeros_like((df[df['Species'] == 'Iris-virginica'])['PetalWidthCm']), 'go')
ax4.plot((df[df['Species'] == 'Iris-versicolor'])['PetalWidthCm'], np.zeros_like((df[df['Species'] == 'Iris-versicolor'])['PetalWidthCm']), 'bo')
ax4.set_title('Analysis of Petal Width', size = 20)
ax4.get_yaxis().set_visible(False)

plt.subplots_adjust(left = 0.1,
                    bottom = 0.1, 
                    right = 0.9, 
                    top = 0.9, 
                    wspace = 0.4, 
                    hspace = 0.4)
plt.show()
"""
**Observations**:
 - `SepalLengthCm`: Iris-setosa has the smallest sepal length. We can see an outlier (red dot) in the graph. Iris-versicolor has a sepal length of about 5 cm to 7 cm. Iris-virginica has the largest sepal length (above 7 cm).
 - `SepalWidthCm`: Iris-versicolor has the smallest sepal width. The distinction between setosa and virginica is not so prominent in the range of 3.5 cm to 4 cm. However for a sepal width equal to or greater than 4 cm all the flowers belong to the Iris-setosa species.
 - `PetalLengthCm`: Iris-setosa has the smallest petal length. The length of the petals do not exceed 2 cm. For Iris-versicolor the petal length is in the range of 3 cm to 5 cm. Iris-virginica has the largest petal length (5 cm or greater).
 - `PetalWidthCm`: Iris-setosa has the smallest petal width. Iris-versicolor has a petal length from 1 cm to slightly less than 2 cm. Iris-virginica has a petal width that is approximately greater than 1.8 cm.
"""
"""
Boxplots are a standardized way of displaying the distribution of data.
**To know more about boxplots you can visit this link: https://towardsdatascience.com/understanding-boxplots-5e2df7bcbd51**
<div style="width:100%;text-align: center;"> <img align = left src="https://datavizcatalogue.com/methods/images/anatomy/box_plot.png" style="height:600px;"> </div>
"""
plt.figure(figsize=(15, 20))

def create_boxplot(feature):
    sns.boxplot(data = df, x = 'Species', y = feature)
    if(feature == 'SepalLengthCm'):
        feature = 'Sepal Length'
    if(feature == 'SepalWidthCm'):
        feature = 'Sepal Width'
    if(feature == 'PetalLengthCm'):
        feature = 'Petal Length'
    if(feature == 'PetalWidthCm'):
        feature = 'Petal Width'
    plt.title('Boxplot for ' + feature, fontsize = 20)
    plt.xlabel('Species', fontsize = 15)
    plt.ylabel(feature, fontsize = 15)
      
plt.subplot(221)
create_boxplot('SepalLengthCm')
  
plt.subplot(222)
create_boxplot('SepalWidthCm')
  
plt.subplot(223)
create_boxplot('PetalLengthCm')
  
plt.subplot(224)
create_boxplot('PetalWidthCm')
  
plt.show()
"""
**Observations**:
 - `SepalLengthCm`: The median value for sepal length is the least for Iris-setosa and the most for Iris-virginica.
 - `SepalWidthCm`: The median value for sepal width is the least for Iris-versicolor and the largest for Iris-setosa. Based on the sepal width of the flowers it might be tough to differentiate between the 3 species.
 - `PetalLengthCm`: Visually it is very evident that Iris-setosa has the least petal length. Even though there are a few outliers all of them are less than 2 cm. Iris-versicolor has the second largest median petal length, whereas Iris-virginica has the largest median petal length.
 - `PetalWidthCm`: Similar to the petal lengths of the species, we can see that Iris-setosa has the lowest median petal width, whereas Iris-virginica has the largest median petal width.
"""
"""
A violin plot is a hybrid of a box plot and a kernel density plot, which shows peaks in the data. It is used to visualize the distribution of numerical data. Unlike a box plot that can only show summary statistics, violin plots depict summary statistics and the density of each variable. On each side of the gray line is a kernel density estimation to show the distribution shape of the data. Wider sections of the violin plot represent a higher probability that members of the population will take on the given value, the skinnier sections represent a lower probability. **To learn more about violinplots you can visit this link: https://mode.com/blog/violin-plot-examples/**
<span style="width:100%;text-align: center;"><img align = left src="https://images.ctfassets.net/fi0zmnwlsnja/sdfgtcRp16wTNOcRceGQm/5bfcb73d2261d49ff20dd7857e0152b1/Screen_Shot_2019-03-01_at_11.36.10_AM.png" style="height:550px;"></span>
"""
plt.figure(figsize=(15, 20))

def create_violinplot(feature):
    sns.violinplot(data = df, x = 'Species', y = feature)
    if(feature == 'SepalLengthCm'):
        feature = 'Sepal Length'
    if(feature == 'SepalWidthCm'):
        feature = 'Sepal Width'
    if(feature == 'PetalLengthCm'):
        feature = 'Petal Length'
    if(feature == 'PetalWidthCm'):
        feature = 'Petal Width'
    plt.title('Violinplot for ' + feature, fontsize = 20)
    plt.xlabel('Species', fontsize = 15)
    plt.ylabel(feature, fontsize = 15)
      
plt.subplot(221)
create_violinplot('SepalLengthCm')
  
plt.subplot(222)
create_violinplot('SepalWidthCm')
  
plt.subplot(223)
create_violinplot('PetalLengthCm')
  
plt.subplot(224)
create_violinplot('PetalWidthCm')
  
plt.show()
"""
**Observations**:
In terms of the median the observations from the violin-plot are similar to that of the box-plot.
 - `SepalLengthCm`: There is a high probability that Iris-setosa will have a sepal length of 5 cm.
 - `SepalWidthCm`: For Iris-versicolor and Iris-virginica there is a high probability that they will have approximately the same sepal width. Thus identification of the species based on this feature only might not yield good results.
 - `PetalLengthCm`: Most of petal lengths for Iris-setosa are about 1.5 cm.
 - `PetalWidthCm`: There is a high probability that the petal width for Iris-setosa species would be approximately 0.25 cm. The violin plots for Iris-versicolor and Iris-virginica are not as broad as that of Iris-setosa.
"""
"""
# Bivariate Analysis
Bivariate analysis is a form of statistical analysis. It involves the analysis of two variables for the purpose of determining the relationship between them.
"""
plt.figure(figsize = (10, 7))
sns.scatterplot(x = 'PetalLengthCm', y = 'PetalWidthCm', hue = 'Species', data = df, s = 65)
plt.legend(bbox_to_anchor = (1, 1), loc = 2, fontsize = 15)
plt.title('Petal Length VS Petal Width', fontsize = 20)
plt.xlabel('Petal Length', fontsize = 15)
plt.ylabel('Petal Width', fontsize = 15)
plt.show()
"""
We can see that the petal length and petal width is the least for Iris-setosa. The petal width and length for Iris-versicolor lies in an intermediate range, between that of setosa and virginica. Iris-virginica has the largest petal length and width. A few outliers exist in the case of both versicolor and virginica.
"""
plt.figure(figsize = (10, 7))
sns.scatterplot(x = 'SepalLengthCm', y = 'SepalWidthCm', hue = 'Species', data = df, s = 65)
plt.legend(bbox_to_anchor = (1, 1), loc = 2, fontsize = 15)
plt.title('Sepal Length VS Sepal Width', fontsize = 20)
plt.xlabel('Sepal Length', fontsize = 15)
plt.ylabel('Sepal Width', fontsize = 15)
plt.show()
"""
We can observe that Iris-setosa has a relatively lower sepal length (as compared to versicolor or virginica). Iris-setosa has a large sepal width. It is hard to distinguish between versicolor and virginica based on sepal length and width. 
"""
"""
# Multivariate Analysis
It refers to an analysis involving multiple dependent variables resulting in one outcome. Creating different graphs for all the features to perform bivariate analysis would be extremely tedious. Seaborn provides a convenient way to perform multivariate analysis using the `pairplot` function.
"""
sns.pairplot(df, hue = 'Species', height = 5)
plt.show()
"""
# 3D Visualization
3D scatter plots are used to plot data points on three axes in the attempt to show the relationship between three variables. Each row in the data table is represented by a marker whose position depends on its values in the columns set on the X, Y, and Z axes. **To learn about plotting 3D scatter plots using matplot you can visit this link: https://pythonguides.com/matplotlib-3d-scatter/**
"""
fig = plt.figure(figsize=(20, 20))

def create_3d(feature1, feature2, feature3):
    
    ax.scatter3D((df[df['Species'] == 'Iris-setosa'])[feature1], 
                 (df[df['Species'] == 'Iris-versicolor'])[feature1], 
                 (df[df['Species'] == 'Iris-virginica'])[feature1], 
                 color = 'r')
    
    ax.scatter3D((df[df['Species'] == 'Iris-setosa'])[feature2], 
                 (df[df['Species'] == 'Iris-versicolor'])[feature2], 
                 (df[df['Species'] == 'Iris-virginica'])[feature2], 
                 color = 'g')
    
    ax.scatter3D((df[df['Species'] == 'Iris-setosa'])[feature3], 
                 (df[df['Species'] == 'Iris-versicolor'])[feature3], 
                 (df[df['Species'] == 'Iris-virginica'])[feature3],
                 color = 'b')
    
    if(feature1 == 'SepalLengthCm'):
        feature1 = 'Sepal Length'
    if(feature1 == 'SepalWidthCm'):
        feature1 = 'Sepal Width'
    if(feature1 == 'PetalLengthCm'):
        feature1 = 'Petal Length'
    if(feature1 == 'PetalWidthCm'):
        feature1 = 'Petal Width'
    if(feature2 == 'SepalLengthCm'):
        feature2 = 'Sepal Length'
    if(feature2 == 'SepalWidthCm'):
        feature2 = 'Sepal Width'
    if(feature2 == 'PetalLengthCm'):
        feature2 = 'Petal Length'
    if(feature2 == 'PetalWidthCm'):
        feature2 = 'Petal Width'
    if(feature3 == 'SepalLengthCm'):
        feature3 = 'Sepal Length'
    if(feature3 == 'SepalWidthCm'):
        feature3 = 'Sepal Width'
    if(feature3 == 'PetalLengthCm'):
        feature3 = 'Petal Length'
    if(feature3 == 'PetalWidthCm'):
        feature3 = 'Petal Width'
        
    plt.title(feature1 + ' VS ' + feature2 + ' VS ' + feature3, fontweight = 'bold', size = 20)
    ax.set_xlabel(feature1, fontweight = 'bold', size = 15)
    ax.set_ylabel(feature2, fontweight = 'bold', size = 15)
    ax.set_zlabel(feature3, fontweight = 'bold', size = 15)
    
ax = fig.add_subplot(2, 2, 1, projection='3d')
create_3d('SepalWidthCm', 'SepalLengthCm', 'PetalWidthCm')

ax = fig.add_subplot(2, 2, 2, projection='3d')
create_3d('SepalWidthCm', 'SepalLengthCm', 'PetalLengthCm')

ax = fig.add_subplot(2, 2, 3, projection='3d')
create_3d('PetalWidthCm', 'PetalLengthCm', 'SepalWidthCm')

ax = fig.add_subplot(2, 2, 4, projection='3d')
create_3d('PetalWidthCm', 'PetalLengthCm', 'SepalLengthCm')

fig.tight_layout()
plt.show()
"""
# Checking Correlations
"""
plt.figure(figsize = (15, 10))
sns.heatmap(df.corr(), cmap = 'Blues', square = True, annot = True)
plt.title("Visualizing Correlations", size = 20)
plt.show()
X = df.drop(['Species'], axis = 1)
y = df['Species']
print(X, "\n\n", y)
"""
# Scaling the Data
"""
scaler = StandardScaler()
X = scaler.fit_transform(X)
"""
# Encoding the Categories for the Label
"""
label_encoder = LabelEncoder()
y = label_encoder.fit_transform(y)
"""
# Splitting the Data
"""
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, stratify = y, random_state = 0)
"""
# Classification Report
 > A classification report is a performance evaluation metric in machine learning. It is used to show the precision, recall, F1 Score, and support of your trained    classification model. Some of the common terms associated with a classification report are as follows:
> - **Precision**: Precision is defined as the ratio of true positives to the sum of true and false positives.
> - **Recall**: Recall is defined as the ratio of true positives to the sum of true positives and false negatives.
> - **F1 Score**: The F1 Score is the weighted harmonic mean of precision and recall. The closer the value of the F1 score is to 1.0, the better the expected performance of the model is.
> - **Support**: Support is the number of actual occurrences of the classes in the dataset. It doesn’t vary between models, it just diagnoses the performance evaluation process. 

**Credits for the ML algorithms**: https://www.kaggle.com/marcovasquez/top-machine-learning-algorithms-beginner#Machine-Learning-with-Scikit-Learn--
"""
def generate_results(model, predictions, name):
    cl_rep = classification_report(y_test, predictions)
    print("\nThe classification report for " + name + " is:", cl_rep, sep = "\n")
    cm_model = confusion_matrix(y_test, predictions)
    plt.figure(figsize = (8, 6))
    sns.heatmap(cm_model, annot = True, cmap = 'Blues', annot_kws = {'size': 15}, square = True)
    plt.title('Confusion Matrix for ' + name, size = 15)
    plt.xticks(size = 15)
    plt.yticks(size = 15)
    plt.show()    
"""
# Logistic Regression
Logistic regression, despite its name, is a classification model rather than regression model. It is a process of modeling the probability of a discrete outcome given input variables. 
"""
lr = LogisticRegression()
lr.fit(X_train, y_train)
y_pred = lr.predict(X_test)
acc_lr = lr.score(X_test, y_test)
print("The accuracy for Logistic Regression is:", acc_lr * 100, "%")
generate_results(lr, y_pred, 'Logistic Regression')
"""
# KNN
KNN works by finding the distances between a query and all the examples in the data, selecting the specified number examples (K) closest to the query, then votes for the most frequent label.
"""
knn = KNeighborsClassifier()
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
acc_knn = knn.score(X_test, y_test)
print("The accuracy for KNN is:", acc_knn * 100, "%")
"""
# KNN Model Performance
On the default KNN model we are getting a score of 96.67%. The default value for `n_neighbors` is 5 in KNN. Lets look at the score for different values of `n_neighbors` and select the value that gives us the best results.
"""
store_acc = []
neighbors = [i for i in range(1, 11)]
for i in range(len(neighbors)):
    knn_improved = KNeighborsClassifier(n_neighbors = neighbors[i])
    knn_improved.fit(X_train, y_train)
    y_pred = knn_improved.predict(X_test)
    acc_knn_for_diff_values = round((knn_improved.score(X_test, y_test)) * 100, 2)
    store_acc.append(acc_knn_for_diff_values)
plt.figure(figsize = (10, 7))
plt.plot(neighbors, store_acc, color = 'blue', marker = 'o')
plt.title('N Neighbors VS Score', fontsize = 20)
plt.xlabel('N Neighbors', fontsize = 15)
plt.ylabel('Score', fontsize = 15)
plt.grid(True)
plt.show()
"""
From the graph above we can clearly observe that for all values of `n_neighbors` above 6, the accuracy is a 100%. Lets select the smallest value of `n_neighbors` that gives us the highest accuracy which is 7.
"""
knn_improved = KNeighborsClassifier(n_neighbors = 7)
knn_improved.fit(X_train, y_train)
y_pred = knn_improved.predict(X_test)
acc_knn_imp = knn_improved.score(X_test, y_test)
print("The accuracy for KNN is:", acc_knn_imp * 100, "%")
generate_results(knn_improved, y_pred, 'KNN (n_neighbors = 7)')
"""
# Radius Neighbors Classifier
Radius Neighbors Classifier is a classification machine learning algorithm. It is an extension to the k-nearest neighbors algorithm that makes predictions using all examples in the radius of a new example rather than the k-closest neighbors. As such, the radius-based approach to selecting neighbors is more appropriate for sparse data, preventing examples that are far away in the feature space from contributing to a prediction.
"""
rnc = RadiusNeighborsClassifier()
rnc.fit(X_train, y_train)
y_pred = rnc.predict(X_test)
acc_rnc = rnc.score(X_test, y_test)
print('The accuracy for Radius Neighbors Classifier is:', acc_rnc * 100, "%")
generate_results(rnc, y_pred, 'Radius Neighbors Classifier')
"""
# Gaussian Naive Bayes
This is a variant of Naive Bayes which supports continuous values and has an assumption that each class is normally distributed.
"""
gnb = GaussianNB()
gnb.fit(X_train, y_train)
y_pred = gnb.predict(X_test)
acc_gnb = gnb.score(X_test, y_test)
print('The accuracy for Gaussian Naive Bayes is:', acc_gnb * 100, '%')
generate_results(gnb, y_pred, 'Gaussian Naive Bayes')
"""
# Support Vector Classifier
It is a supervised classification algorithm. The idea of SVM is simple. It creates a line or a hyperplane which separates the data into classes.
"""
svc = SVC()
svc.fit(X_train, y_train)
y_pred = svc.predict(X_test)
acc_svc = svc.score(X_test, y_test)
print('The accuracy for SVC is:', acc_svc * 100, '%')
generate_results(svc, y_pred, 'Support Vector Classifier')
"""
# Quadratic Discriminant Analysis
QDA is a variant of LDA (Linear Discriminant Analysis) in which an individual covariance matrix is estimated for every class of observations. QDA is particularly useful if there is prior knowledge that individual classes exhibit distinct covariances.
"""
qda = QuadraticDiscriminantAnalysis()
qda.fit(X_train, y_train)
y_pred = qda.predict(X_test)
acc_qda = qda.score(X_test, y_test)
print('The accuracy for Quadratic Discriminant Analysis is:', acc_qda * 100, '%')
generate_results(qda, y_pred, 'QDA')
"""
# Decision Tree Classifier
A decision tree is a graphical representation of all possible solutions to a decision based on certain conditions. On each step or node of a decision tree, used for classification, we try to form a condition on the features to separate all the labels or classes contained in the dataset to the fullest purity.
"""
dtc = DecisionTreeClassifier()
dtc.fit(X_train, y_train)
y_pred = dtc.predict(X_test)
acc_dtc = dtc.score(X_test, y_test)
print('The accuracy of the Decision Tree Classifier is:', acc_dtc * 100, '%')
generate_results(dtc, y_pred, 'Decision Tree Classifier')
"""
# Random Forest Classifier
The term “Random Forest Classifier” refers to the classification algorithm made up of several decision trees. The algorithm uses randomness to build each individual tree to promote uncorrelated forests, which then uses the forest's predictive powers to make accurate decisions.
"""
rfc = RandomForestClassifier()
rfc.fit(X_train, y_train)
y_pred = rfc.predict(X_test)
acc_rfc = rfc.score(X_test, y_test)
print('The accuracy of the Random Forest Classifier is:', acc_rfc * 100, '%')
generate_results(rfc, y_pred, 'Random Forest Classifier')
"""
# Ada Boost Classifier
It combines multiple classifiers to increase the accuracy of classifiers. AdaBoost is an iterative ensemble method. AdaBoost classifier builds a strong classifier by combining multiple poorly performing classifiers so that you will get high accuracy strong classifier.
"""
abc = AdaBoostClassifier()
abc.fit(X_train, y_train)
y_pred = abc.predict(X_test)
acc_abc = abc.score(X_test, y_test)
print('The accuracy for Ada Boost Classifier is:', acc_abc * 100, '%')
generate_results(abc, y_pred, 'Ada Boost Classifier')
"""
# Extra Trees Classifier
This is a type of ensemble learning technique which aggregates the results of multiple de-correlated decision trees collected in a “forest” to output it's classification result.
"""
etc = ExtraTreesClassifier(random_state = 0)
etc.fit(X_train, y_train)
y_pred = etc.predict(X_test)
acc_etc = etc.score(X_test, y_test)
print('The accuracy for Etra Trees Classifier is:', acc_etc * 100, '%')
generate_results(etc, y_pred, 'Extra Tress Classifier')
"""
# Bagging Classifier
Bagging classifier is an ensemble technique that fits base classifiers each on random subsets of the original dataset and then aggregates their individual predictions to form a final prediction.
"""
bc = BaggingClassifier()
bc.fit(X_train, y_train)
y_pred = bc.predict(X_test)
acc_bc = bc.score(X_test, y_test)
print('The accuracy for Bagging Classifier is:', acc_bc * 100, '%')
generate_results(bc, y_pred, 'Bagging Classifier')
"""
# Gradient Boosting Classifier
Gradient boosting classifiers are a group of machine learning algorithms that combine many weak learning models together to create a strong predictive model.
"""
gbc = GradientBoostingClassifier()
gbc.fit(X_train, y_train)
y_pred = gbc.predict(X_test)
acc_gbc = gbc.score(X_test, y_test)
print('The accuracy for the Gradient Boosting Classifier is:', acc_gbc * 100, '%')
generate_results(gbc, y_pred, 'Gradient Boosting Classifier')
"""
# XGBoost Classifier
XGBoost is a decision-tree-based ensemble Machine Learning algorithm that uses a gradient boosting framework. XGBoost provides a highly efficient implementation of the stochastic gradient boosting algorithm and access to a suite of model hyperparameters designed to provide control over the model training process.
"""
xgbc = XGBClassifier(n_jobs = -1, silent = True, verbosity = 0)
xgbc.fit(X_train, y_train)
y_pred = xgbc.predict(X_test)
acc_xgbc = xgbc.score(X_test, y_test)
print('The accuracy for XGB Classifier is:', acc_xgbc * 100, '%')
generate_results(xgbc, y_pred, 'XGB Classifier')
"""
# Final Results
"""
data = {'Logistic Regression': acc_lr * 100, 
        'KNN (default parameters)': acc_knn * 100, 
        'KNN (n_neighbors = 7)': acc_knn_imp * 100, 
        'Radius Neighbors Classifier': acc_rnc * 100, 
        'Gaussian Naive Bayes': acc_gnb * 100,
        'Support Vector Classifier': acc_svc * 100, 
        'Quadratic Discriminant Analysis': acc_qda * 100, 
        'Decision Tree Classifier': acc_dtc * 100, 
        'Random Forest Classifier': acc_rfc * 100,
        'Ada Boost Classifier': acc_abc * 100, 
        'Extra Trees Classifier': acc_etc * 100,
        'Bagging Classifier': acc_bc * 100, 
        'Gradient Boosting Classifier': acc_gbc * 100,
        'XGBoost Classifier': acc_xgbc * 100}
data = dict(sorted(data.items(), key = lambda x: x[1], reverse = True))
models = list(data.keys())
score = list(data.values())
fig = plt.figure(figsize = (15, 10))
sns.barplot(x = score, y = models)
plt.xlabel("Models Used", size = 20)
plt.xticks(size = 12)
plt.ylabel("Score", size = 20)
plt.yticks(size = 12)
plt.title("Score for Different Models", size = 25)
plt.show()