Challenge

Project 2

Project_02:Implement Clustering and then predict the class of car from “Car dataset”.

Attributes imformation:

1.symboling: -3, -2, -1, 0, 1, 2, 3

2.normalized-losses: continuous from 65 to 256

3.make: alfa-romero, audi, bmw, chevrolet, dodge, honda, isuzu, jaguar, mazda, mercedes-benz, mercury, mitsubishi, nissan, peugot, plymouth, porsche, renault, saab, subaru, toyota, volkswagen, volvo.

4.fuel-type: diesel, gas

5.aspiration: std, turbo

6.num-of-doors: four, two

7.body-style: hardtop, wagon, sedan, hatchback, convertible

8.drive-wheels: 4wd, fwd, rwd

9.engine-location: front, rear

10.wheel-base: continuous from 86.6 120.9

11.length: continuous from 141.1 to 208.1

12.width: continuous from 60.3 to 72.3

13.height: continuous from 47.8 to 59.8

14.curb-weight: continuous from 1488 to 4066

15.engine-type: dohc, dohcv, l, ohc, ohcf, ohcv, rotor

16.num-of-cylinders: eight, five, four, six, three, twelve, two

17.engine-size: continuous from 61 to 326

18.fuel-system: 1bbl, 2bbl, 4bbl, idi, mfi, mpfi, spdi, spfi

19.bore: continuous from 2.54 to 3.94

20.stroke: continuous from 2.07 to 4.17

21.compression-ratio: continuous from 7 to 23

22.horsepower: continuous from 48 to 288

23.peak-rpm: continuous from 4150 to 6600

24.city-mpg: continuous from 13 to 49

25.highway-mpg: continuous from 16 to 54

26.price: continuous from 5118 to 45400.

Importing neccessary libraries

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')

Reading data

df1 = pd.read_csv('auto.csv')
df1.head()

  • In above dataframe the column names are not meaningfull and dadaset contains special characters.

Data Cleaning

Reading the data with proper column name and replacing special characters with NaN values

df = pd.read_csv('auto.csv',header = None,names = ['symboling','normalized-losses','make','fuel-type','aspiration','num-of-doors','body-style','drive-wheels','engine-location','wheel-base','length','width','height','curb-weight','engine-type','num-of-cylinders','engine-size','fuel-system','bore','stroke','compression-ratio','horsepower','peak-rpm','city-mpg','highway-mpg','price'],na_values=['?','??'])

df.head()
print(list(df.columns)) #Ckecking column names
['symboling', 'normalized-losses', 'make', 'fuel-type', 'aspiration', 'num-of-doors', 'body-style', 'drive-wheels', 'engine-location', 'wheel-base', 'length', 'width', 'height', 'curb-weight', 'engine-type', 'num-of-cylinders', 'engine-size', 'fuel-system', 'bore', 'stroke', 'compression-ratio', 'horsepower', 'peak-rpm', 'city-mpg', 'highway-mpg', 'price']
df.info() #checking info 

Handling missing values

#check missing values
df.isnull().sum()

Replacing Missing Values with respective column mean

df['normalized-losses'].fillna(df['normalized-losses'].mean(),inplace=True)
df['bore'].fillna(df['bore'].mean(),inplace=True)
df['stroke'].fillna(df['stroke'].mean(),inplace=True)
df['horsepower'].fillna(df['horsepower'].mean(),inplace=True)
df['peak-rpm'].fillna(df['peak-rpm'].mean(),inplace=True)
df['price'].fillna(df['price'].mean(),inplace=True)

Replacing all null values in num-of-doors with four(majority) because categorical column.

df['num-of-doors'].value_counts()
df['num-of-doors'].fillna('four',inplace=True)

four 114 two 89 Name: num-of-doors, dtype: int64

Correcting datatypes

1.If we check in above Dtypes of all attribues,Some of attributes such as num-of- doors,num-of cylinder.
they should be 'int'or 'float' format instead of 'object'
2.So let's first convert the str to number using replace() and then convert the object to int or float uaing astype().

#Checking unique values of num-of-doors

df['num-of-doors'].unique()
array(['two', 'four'], dtype=object)
#replacing str to number
df['num-of-doors'].replace('two',2,inplace=True)
df['num-of-doors'].replace('four',4,inplace=True)
#converting object dtype value into int64
df['num-of-doors']=df['num-of-doors'].astype('int64')
df['num-of-cylinders'].unique()
array(['four', 'six', 'five', 'three', 'twelve', 'two', 'eight'],
      dtype=object)
df['num-of-cylinders'].replace('two',2,inplace=True)
df['num-of-cylinders'].replace('three',3,inplace=True)
df['num-of-cylinders'].replace('four',4,inplace=True)
df['num-of-cylinders'].replace('five',5,inplace=True)
df['num-of-cylinders'].replace('six',6,inplace=True)
df['num-of-cylinders'].replace('eight',8,inplace=True)
df['num-of-cylinders'].replace('twelve',12,inplace=True)

df['num-of-cylinders']=df['num-of-cylinders'].astype('int64')

Binning:

  • Binning:Binning is a process of transforming continuous numerical variables into discrete categorical 'bins', for grouped analysis.
df['horsepower'].describe()
df["horsepower"] = df["horsepower"].astype(int, copy=True) 

#Copy = True willl create the another copy of column including changes to it.
#int is Dtype we want apply.

df["horsepower"] 

Histogram of horsepower

plt.hist(df['horsepower'])
#Setting x&y labels
plt.xlabel("horsepower")
plt.ylabel("count")
plt.title("horsepower bins")

  • 3 bins of equal size bandwidth so we use numpy's linspace(start_value, end_value, numbers_generated function.
  • Since we are building 3 bins of equal length, there should be 4 dividers, so numbers_generated=4.
bins = np.linspace(min(df["horsepower"]),max(df["horsepower"]),4)
bins
array([ 48., 128., 208., 288.])
bins_names = ['Low', 'Medium', 'High']
df['horsepower-binned'] = pd.cut(df['horsepower'], bins, labels=bins_names ,include_lowest = True)
#df[['horsepower','horsepower-binned']].head(5)

df['horsepower-binned']=df['horsepower-binned'].astype('object')

#df["horsepower-binned"].value_counts()

#let's drop the horsepower column
df.drop(['horsepower'],axis=1,inplace=True)
df.head()

  • Till now we have cleaned data, by removing NaN values and special characters and proper naminng to columns

Exploring data with visvulization

df.shape
df.info()
(205, 26)
df.describe().T

Countplots

cat_list = ['symboling','num-of-doors', 'num-of-cylinders','fuel-type', 'aspiration', 'body-style', 'drive-wheels', 'engine-location', 'horsepower-binned'] 
fig, axs = plt.subplots(nrows=4,ncols=2,figsize =(15,20))
for col,ax in zip(cat_list[0:],axs.ravel()):
    sns.countplot(x=col,data=df,ax=ax)
    plt.xticks(rotation='vertical')
    plt.savefig("Countplot",facecolor='y',bbox_inches="tight",pad_inches=0.3, transparent=True)

  • 1.four doors are higher than the two doors cars.
  • 2.maximum numbers of cars having four number of cylinders in them followed by 6 number of cylinders and then 5.
  • 3.Most of the cars at working on gas.
  • 4.most of the cars are front wheel drive.
  • 5.Almost cars have engine located at front.

Barplot

df_make_count = df['make'].value_counts()

fig, ax = plt.subplots(1, 2, figsize=(20,10))
df_make_count_barplot = sns.barplot(y = df_make_count.index,x = df_make_count.values, ax = ax[0])
df_make_count_barplot.set_ylabel('count')
df_make_count_barplot.set_xlabel('Car brand')
df_make_count.plot.pie(autopct="%1.1f%%", ax=ax[1])
plt.savefig("vehicles count",facecolor='g', bbox_inches="tight",
            pad_inches=0.3, transparent=True)

  • we can see that most of the cars in the datasets is of toyota brand followed by nissan, mazda etc
df_make_count = df['fuel-system'].value_counts()

fig, ax = plt.subplots(1, 2, figsize=(20,10))
df_make_count_barplot = sns.barplot(x = df_make_count.index,y = df_make_count.values, ax = ax[0])
df_make_count_barplot.set_ylabel('count')
df_make_count_barplot.set_xlabel('fuel-system')
df_make_count.plot.pie(autopct="%1.1f%%", ax=ax[1])
plt.savefig("fuel-system",facecolor='g', bbox_inches="tight",
            pad_inches=0.3, transparent=True)

  • Most of the Vehicles uses 'mpfi' fuel-injection system
df_make_count = df['engine-type'].value_counts()

fig, ax = plt.subplots(1, 2, figsize=(20,10))
df_make_count_barplot = sns.barplot(x = df_make_count.index,y = df_make_count.values, ax = ax[0])
df_make_count_barplot.set_ylabel('count')
df_make_count_barplot.set_xlabel('engine-type')
df_make_count.plot.pie(autopct="%1.1f%%", ax=ax[1])
plt.savefig("engine-type",facecolor='g', bbox_inches="tight",
            pad_inches=0.3, transparent=True)

  • Most of the vehicles have 'Ohc' type engine

Boxplot to detect outliers

num = [ 'normalized-losses', 'wheel-base', 'length', 'width', 'height', 'curb-weight', 'engine-size', 'bore', 'stroke', 'peak-rpm', 'price', 'city-mpg', 'highway-mpg']
fig, axs = plt.subplots(nrows=5,ncols=3,figsize =(15,20))
for col,ax in zip(num[0:],axs.ravel()):
    sns.boxplot(x=col,data=df,ax=ax)
    plt.xticks(rotation='vertical')
    plt.savefig("boxplot", bbox_inches="tight",
            pad_inches=0.3, transparent=True)

Pairplot between price and all other attributes

sns.pairplot(df,x_vars=["price","num-of-cylinders","engine-size","length","width","height"],y_vars=["price","engine-size"],)

Boxplots

  • Categorical attributes and their correlation with price
sns.boxplot(x="body-style", y="price", data=df)
plt.savefig('body style vs price')

  • Above we can see,boxes overlap and their median lines are inside the overlap range.
  • As we mentioned above distributions of price between the different body-style categories have a significant overlap,and so body-style would not be a good predictor of price.
sns.boxplot(x="engine-location", y="price", data=df)
plt.savefig('location vs price')

  • two boxes are not overlaped and they are enough distinct, we can say engine location is the predictor of price
sns.boxplot(x="aspiration", y="price", data=df)
plt.savefig('aspiration vs price')

sns.boxplot(x="drive-wheels", y="price", data=df)
plt.savefig('Dw vs price')

Correlation and Heatmap

df.corr()

plt.figure(figsize=(20,10))
sns.heatmap(df.corr(),annot=True)
plt.savefig('Heatmap')

  • Compression-ratio has very strong negative correlation with fuel-type
  • Price has very strong positive relationship with curb-weight and engine size
  • Engine size has positive relationship with num-of cylider,leght,width,height

Converting Categorical columns into Numerical column using labelEncoder

#Creating catagorical list
objList = df.select_dtypes(include = "object").columns
print (objList)
Index(['make', 'fuel-type', 'aspiration', 'body-style', 'drive-wheels',
       'engine-location', 'engine-type', 'fuel-system', 'horsepower-binned'],
      dtype='object')

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()

for i in objList:
    df[i] = le.fit_transform(df[i].astype(str))

#print (df.info())

df.head()

Standardizing data

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df1= pd.DataFrame(scaler.fit_transform(df),columns=df.columns)

df1.head()

After standardization next step is to reduce some dimension using PCA technique

Implementing The Principal component analysis

from sklearn.decomposition import PCA
pca = PCA(n_components=3)
principalComponents = pca.fit_transform(df1)
Df = pd.DataFrame(data = principalComponents,columns = ['pc1','pc2','pc3'])
print(Df)

#Explained variance ratio

print(pca.explained_variance_ratio_)
[0.32361609 0.16496542 0.08762615] # It shows the percentage of variance that is attributed by each of the selected components i.e Pc1 has 32 %,pc2 %16.

Finding optimun value of K usinng elbow curve

from sklearn.cluster import KMeans

k_range = range(2,20)

sse = []
for k in k_range:
    km1=KMeans(n_clusters=k)
    km1.fit_predict(Df)
    sse.append(km1.inertia_)
plt.plot(k_range,sse,marker ='*')
plt.ylabel('SSE')
plt.xlabel('K_values')
plt.show()    

Applying KMean algorithm

km = KMeans(n_clusters=5)
print(km)
y= km.fit_predict(Df)
print(y)

Df['Class']=y
df0 = Df[Df.Class==0]
df1 = Df[Df.Class==1]
df2 = Df[Df.Class==2]
df3 = Df[Df.Class==3]
df4 = Df[Df.Class==4]

Df.head()

By using KMean we have created class,we can see in graph .

#Centroids

print(km.cluster_centers_)
[[-3.11498837  0.46531071  0.21172379]
 [ 3.90748089 -0.2902233  -1.22341231]
 [ 1.03594318  2.73158485  0.81878428]
 [-0.90740928 -1.02286722 -1.1820883 ]
 [ 1.70350465 -3.82299174  3.30010375]]

Cluster Visualization
plt.figure(figsize=(10,7))
a=plt.scatter(df0['pc1'],df0['pc2'],c='red')
b=plt.scatter(df1['pc1'],df1['pc2'],c='green')
c=plt.scatter(df2['pc1'],df2['pc2'],c='blue')
d=plt.scatter(df3['pc1'],df3['pc2'],c='black')
e=plt.scatter(df4['pc1'],df4['pc2'],c='cyan')
plt.scatter(km.cluster_centers_[:,0],km.cluster_centers_[:,1],s=200,c='purple',marker='*')
plt.title('pc1 vs pc2')
plt.xlabel('pc1(variance_explained:0.32)')
plt.ylabel('pc2(variance_explained:0.16)')
plt.show()
plt.savefig('cluster')

  • Using Kmean wee have grouped data into 5 classes(clusturs).
  • Next step is to predict class(clutures) using classification algorithms.

Predicting class using calssification model


Seperating independent and dependent features

x = Df.drop('Class',axis=1)
y = Df['Class']

Splitting data into train and test

from sklearn.model_selection import cross_val_score
from sklearn.model_selection import train_test_split
X_train,X_test,Y_train,Y_test = train_test_split(x,y,test_size=0.3,random_state=0)

1.logistic regression

from  sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
lr.fit(X_train,Y_train)
Y_p= lr.predict(X_test)
print("Logistic_Reg_train_score:",lr.score(X_train,Y_train))
print("Logistic_Reg_test_score:",lr.score(X_test,Y_test))
Logistic_Reg_train_score: 1.0
Logistic_Reg_test_score: 0.967741935483871

1.Ke-fold cross validation for logistic regression
score_lr=cross_val_score(lr,X_train,Y_train,cv=10)
print(score_lr)
print("Avg :",np.average(score_lr))
[1.         1.         0.93333333 0.92857143 1.         1.
 1.         1.         1.         1.        ]
Avg : 0.9861904761904763


2.Support Vector Machine
from sklearn.svm import SVC
svm = SVC()
svm.fit(X_train,Y_train)
Y_pred_svm= svm.predict(X_test)
SVM_score = svm.score(X_test,Y_test)
print("SVM_train_score:",svm.score(X_train,Y_train))
print("SVM_test_score:",SVM_score)
SVM_train_score: 1.0
SVM_test_score: 0.9516129032258065

2.K-fold cross_validation for SVM
from sklearn.model_selection import cross_val_score
score_svm=cross_val_score(svm,X_train,Y_train,cv=10)
print(score_svm)
print("Avg :",np.average(score_svm))
SVM_train_score: 1.0
SVM_test_score: 0.9516129032258065

3.Decision Tree
from sklearn.tree import DecisionTreeClassifier
dtc = DecisionTreeClassifier()
dtc.fit(X_train,Y_train)
print("dtc_train_score:",dtc.score(X_train,Y_train))
print("dtc_test_score:",dtc.score(X_test,Y_test))
dtc_train_score: 1.0
dtc_test_score: 0.9032258064516129

3.K-fold cross_validation for decision tree
score_dtc=cross_val_score(dtc,X_train,Y_train,cv=10)
print(score_dtc)
print("Avg :",np.average(score_dtc))
[0.93333333 1.         1.         0.85714286 0.92857143 0.78571429
 0.92857143 1.         1.         0.64285714]
Avg : 0.9076190476190475


4.Random forest
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_estimators=50,random_state=7)
rf.fit(X_train,Y_train)
Y_pred_rf= rf.predict(X_test)
print("rf_train_score:",rf.score(X_train,Y_train))
print("rf_test_score:",rf.score(X_test,Y_test))
rf_train_score: 1.0
rf_test_score: 0.967741935483871

Gap between train and test score is more.

4.K-fold cross validation random forest
score_rf=cross_val_score(rf,X_train,Y_train,cv=10)
print(score_rf)
print("Avg :",np.average(score_rf))
[1.         1.         0.86666667 0.92857143 0.92857143 0.85714286
 1.         1.         1.         0.78571429]
Avg : 0.9366666666666668

5.KNN Classifier

from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train,Y_train)
print("Knn_train_score:",knn.score(X_train,Y_train))
print("Knn_test_score:",knn.score(X_test,Y_test))
Knn_train_score: 0.993006993006993
Knn_train_score: 0.9838709677419355

Gap between train and test accuarcy is very less as compare to other model

5.K-fold cross validation for Knn

from sklearn.model_selection import cross_val_score
score_knn=cross_val_score(knn,X_train,Y_train,cv=10)
print(score_knn)
print("Avg :",np.average(score_knn))
[1.         1.         0.86666667 1.         1.         1.
 1.         1.         1.         1.        ]
Avg : 0.9866666666666667

Accuracy comparision table
data = {'classifier':['Logistic_regression','SVM','Decision_tree','Random_forest','Knn'],
        'model_train_score':[1,1,1,1,0.99],
        'model_test_accuarcy ':[0.96,0.95,0.90,0.96,0.98],
        'k-fold_cross_score ':[0.98, 0.99,0.90,0.93,0.98]}


df2 = pd.DataFrame(data)
df2

  • from above table,
  • For Knn classifier, the gap between train and test score is very less as compare to all other model.so Knn is performing very well.
  • For logistic regression & random forest, gap between train and test is slightly more as compare to Knn.
Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.