Skip to content

03-SVM-Project-Exercise-Solutions

Updated
17 Sept 2026
3 min read
6 sections
Page 79 of 117
Python & Machine Learning

Support Vector Machines

Exercise - Solutions

Fraud in Wine

Wine fraud relates to the commercial aspects of wine. The most prevalent type of fraud is one where wines are adulterated, usually with the addition of cheaper products (e.g. juices) and sometimes with harmful chemicals and sweeteners (compensating for color or flavor).

Counterfeiting and the relabelling of inferior and cheaper wines to more expensive brands is another common type of wine fraud.

Project Goals

A distribution company that was recently a victim of fraud has completed an audit of various samples of wine through the use of chemical analysis on samples. The distribution company specializes in exporting extremely high quality, expensive wines, but was defrauded by a supplier who was attempting to pass off cheap, low quality wine as higher grade wine. The distribution company has hired you to attempt to create a machine learning model that can help detect low quality (a.k.a "fraud") wine samples. They want to know if it is even possible to detect such a difference.

Data Source: P. Cortez, A. Cerdeira, F. Almeida, T. Matos and J. Reis. Modeling wine preferences by data mining from physicochemical properties. In Decision Support Systems, Elsevier, 47(4):547-553, 2009.



TASK: Your overall goal is to use the wine dataset shown below to develop a machine learning model that attempts to predict if a wine is "Legit" or "Fraud" based on various chemical features. Complete the tasks below to follow along with the project.



Complete the Tasks in bold

TASK: Run the cells below to import the libraries and load the dataset.

python
df = pd.read_csv("../DATA/wine_fraud.csv")
python
df.head()
Out · table
fixed acidity
volatile acidity
citric acid
residual sugar
chlorides
78 more lines
free sulfur dioxide
total sulfur dioxide
density
pH
sulphates
alcohol
quality
type
0
7.4
0.70
0.00
1.9
0.076
11.0
34.0
0.9978
3.51
0.56
9.4
Legit
red
1
7.8
0.88
0.00
2.6
0.098
25.0
67.0
0.9968
3.20
0.68
9.8
Legit
red
2
7.8
0.76
0.04
2.3
0.092
15.0
54.0
0.9970
3.26
0.65
9.8
Legit
red
3
11.2
0.28
0.56
1.9
0.075
17.0
60.0
0.9980
3.16
0.58
9.8
Legit
red
4
7.4
0.70
0.00
1.9
0.076
11.0
34.0
0.9978
3.51
0.56
9.4
Legit
red

TASK: What are the unique variables in the target column we are trying to predict (quality)?

python
df['quality'].unique()
Out · result
array(['Legit', 'Fraud'], dtype=object)

TASK: Create a countplot that displays the count per category of Legit vs Fraud. Is the label/target balanced or unbalanced?

python
sns.countplot(x='quality',data=df)
Out · result
<AxesSubplot:xlabel='quality', ylabel='count'>
Out · plot
Output 1

*TASK: Let's find out if there is a difference between red and white wine when it comes to fraud. Create a countplot that has the wine type on the x axis with the hue separating columns by Fraud vs Legit.*

python
sns.countplot(x='type',hue='quality',data=df)
Out · result
<AxesSubplot:xlabel='type', ylabel='count'>
Out · plot
Output 2

TASK: What percentage of red wines are Fraud? What percentage of white wines are fraud?

python
reds = df[df["type"]=='red']
python
whites = df[df["type"]=='white']
python
print("Percentage of fraud in Red Wines:")
print(100* (len(reds[reds['quality']=='Fraud'])/len(reds)))
Out · stdout
Percentage of fraud in Red Wines:
3.9399624765478425
python
print("Percentage of fraud in White Wines:")
print(100* (len(whites[whites['quality']=='Fraud'])/len(whites)))
Out · stdout
Percentage of fraud in White Wines:
3.7362188648427925

TASK: Calculate the correlation between the various features and the "quality" column. To do this you may need to map the column to 0 and 1 instead of a string.

python
df['Fraud']= df['quality'].map({'Legit':0,'Fraud':1})
python
df.corr()['Fraud']
Out · result
fixed acidity           0.021794
volatile acidity        0.151228
citric acid            -0.061789
residual sugar         -0.048756
chlorides               0.034499
8 more lines
free sulfur dioxide    -0.085204
total sulfur dioxide   -0.035252
density                 0.016351
pH                      0.020107
sulphates              -0.034046
alcohol                -0.051141
Fraud                   1.000000
Name: Fraud, dtype: float64

TASK: Create a bar plot of the correlation values to Fraudlent wine.

python
# CODE HERE
python
df.corr()['Fraud'][:-1].sort_values().plot(kind='bar')
Out · result
<AxesSubplot:>
Out · plot
Output 3

TASK: Create a clustermap with seaborn to explore the relationships between variables.

python
sns.clustermap(df.corr(),cmap='viridis')
Out · result
<seaborn.matrix.ClusterGrid at 0x231b34be088>
Out · plot
Output 4

Machine Learning Model

TASK: Convert the categorical column "type" from a string or "red" or "white" to dummy variables:

python
# CODE HERE
python
df['type'] = pd.get_dummies(df['type'],drop_first=True)
python
df = df.drop('Fraud',axis=1)

TASK: Separate out the data into X features and y target label ("quality" column)

python
X = df.drop('quality',axis=1)
y = df['quality']

TASK: Perform a Train|Test split on the data, with a 10% test size. Note: The solution uses a random state of 101

python
from sklearn.model_selection import train_test_split
python
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=101)

TASK: Scale the X train and X test data.

python
from sklearn.preprocessing import StandardScaler
python
scaler = StandardScaler()
python
scaled_X_train = scaler.fit_transform(X_train)
scaled_X_test = scaler.transform(X_test)

TASK: Create an instance of a Support Vector Machine classifier. Previously we have left this model "blank", (e.g. with no parameters). However, we already know that the classes are unbalanced, in an attempt to help alleviate this issue, we can automatically adjust weights inversely proportional to class frequencies in the input data with a argument call in the SVC() call. Check out the [documentation for SVC] online and look up what the argument\parameter is.

python
# CODE HERE
python
from sklearn.svm import SVC
python
svc = SVC(class_weight='balanced')

TASK: Use a GridSearchCV to run a grid search for the best C and gamma parameters.

python
# CODE HERE
python
from sklearn.model_selection import GridSearchCV
python
param_grid = {'C':[0.001,0.01,0.1,0.5,1],'gamma':['scale','auto']}
grid = GridSearchCV(svc,param_grid)
python
grid.fit(scaled_X_train,y_train)
Out · result
GridSearchCV(estimator=SVC(class_weight='balanced'),
             param_grid={'C': [0.001, 0.01, 0.1, 0.5, 1],
                         'gamma': ['scale', 'auto']})
python
grid.best_params_
Out · result
{'C': 1, 'gamma': 'auto'}

TASK: Display the confusion matrix and classification report for your model.

python
from sklearn.metrics import confusion_matrix,classification_report
python
grid_pred = grid.predict(scaled_X_test)
python
confusion_matrix(y_test,grid_pred)
Out · result
array([[ 17,  10],
       [ 92, 531]], dtype=int64)
python
print(classification_report(y_test,grid_pred))
Out · stdout
              precision    recall  f1-score   support

       Fraud       0.16      0.63      0.25        27
       Legit       0.98      0.85      0.91       623
3 more lines
    accuracy                           0.84       650
   macro avg       0.57      0.74      0.58       650
weighted avg       0.95      0.84      0.88       650

TASK: Finally, think about how well this model performed, would you suggest using it? Realistically will this work?

python
# View video for full discussion on this.