text_plain_output_1.png image_output_1.png
from matplotlib.ticker import MaxNLocator

from sklearn.mixture import GaussianMixture

import matplotlib.pyplot as plt

import numpy as np

import pandas as pd

import seaborn as sns

data = pd.read_csv('../input/Iris.csv')
data

features = ['PetalLengthCm', 'PetalWidthCm']

color_dict = {'Iris-setosa': 'darkred', 'Iris-versicolor': 'Yellow', 'Iris-virginica': 'Green'}
names_dict = {'Iris-setosa': 'Setosa', 'Iris-versicolor': 'Versicolor', 'Iris-virginica': 'Virginica'}

def get_outliers(log_prob, epsilon):
    outliners = np.where(log_prob <= epsilon, 1, 0)
    return outliners

def make_density_plot(data, features, model, outliers):
    
    x = np.linspace(data[features[0]].min(), data[features[0]].max())
    y = np.linspace(data[features[1]].min(), data[features[1]].max())
    X, Y = np.meshgrid(x, y)

    XX = np.array([X.ravel(), Y.ravel()]).T
    Z = model.score_samples(XX)
    Z = Z.reshape(X.shape)

    levels = MaxNLocator(nbins=100).tick_values(Z.min(), Z.max()) 
    cmap = plt.get_cmap('BuGn')

    plt.figure(figsize=(10,10))
    plt.contourf(X, Y, Z.reshape(X.shape), cmap=cmap, levels=levels) 
    plt.scatter(model.means_[:,0], model.means_[:,1], color="Blue")
    g1 = plt.scatter(data[data.Outlier==0][features[0]].values,
    data[data.Outlier==0][features[1]].values, label="Normal",s=4.0,c="Pink")
    g2 = plt.scatter(data[data.Outlier==1][features[0]].values,
    data[data.Outlier==1][features[1]].values, label="Abnormal",s=4.5,c="Black")
    plt.legend(handles=[g1,g2]) 
    
    plt.xlabel(features[0])
    plt.ylabel(features[1])
    return plt

X_train = data[features].values
model = GaussianMixture(n_components=3, covariance_type='full')
model.fit(X_train)
log_prob = model.score_samples(X_train)
outliers = get_outliers(log_prob, 0.15)
data['Outlier'] = outliers

plt.figure(figsize=(20,5))

sns.distplot(log_prob, kde=False, bins=50, color="Green")
g1 = plt.axvline(np.quantile(log_prob, 0.25), color="Red", label="Q_25")
g2 = plt.axvline(np.quantile(log_prob, 0.5), color="Blue", label="Q_50 - Median")
g3 = plt.axvline(np.quantile(log_prob, 0.75), color="Violet", label="Q_75")
g4 = plt.axvline(np.quantile(log_prob, 0.05), color="Brown", label="Q_5")
handles = [g1, g2, g3, g4]
plt.xlabel("log-probabilities of the data spots")
plt.ylabel("frequency")
plt.legend(handles) 

epsilon = np.quantile(log_prob, 0.05)

data.Outlier.value_counts()

species_probas = np.round(model.predict_proba(X_train), 2)
best_species_idx = np.argmax(species_probas, axis=1)
data['Predicted'] = best_species_idx

def map_to_species(data, features):
    grouped = data.groupby('Species')[features].mean()
    feature_means = grouped.values
    names_map = {}
    for m in data.Predicted.unique():
        predicted_mean = data[data.Predicted == m][features].mean().values
        distances = np.zeros(feature_means.shape[0])
        for f in range(feature_means.shape[0]):
            distances[f] = np.linalg.norm(predicted_mean - feature_means[f])
        name = grouped.index.values[np.argmin(distances)]
        names_map[m] = name
    return names_map

ig, ax = plt.subplots(1, 2, figsize=(20, 5))
for species in color_dict.keys():
    ax[0].scatter(data[data.Species == species][features[0]], data[data.Species == species][features[1]], c=color_dict[species], label=names_dict[species])
    ax[1].scatter(data[data.Predicted_Species == species][features[0]], data[data.Predicted_Species == species][features[1]], c=color_dict[species], label=names_dict[species])
ax[0].set_xlabel(features[0])
ax[0].set_ylabel(features[1])
ax[0].set_title('True species')
ax[0].legend()
ax[1].set_xlabel(features[0])
ax[1].set_ylabel(features[1])
ax[1].set_title('Predicted species')
ax[1].legend()