In [1]:
import pandas as df
import numpy as np
from sklearn import tree
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
data = df.read_csv(r'C:\Users\GelsthN\OneDrive - DVLA\Desktop\Machine Learning Assignment\data.csv')
# This is where I have cleansed the data for play time as I didn't need to see it to as many decimal places as I have.
data['PlayTimeHours'] = data['PlayTimeHours'].round(1)
print(data)
PlayerID Age Gender Location GameGenre PlayTimeHours \
0 9000 43 Male Other Strategy 16.3
1 9001 29 Female USA Strategy 5.5
2 9002 22 Female USA Sports 8.2
3 9003 35 Male USA Action 5.3
4 9004 33 Male Europe Action 15.5
... ... ... ... ... ... ...
40029 49029 32 Male USA Strategy 20.6
40030 49030 44 Female Other Simulation 13.5
40031 49031 15 Female USA RPG 0.2
40032 49032 34 Male USA Sports 14.0
40033 49033 19 Male USA Sports 10.1
InGamePurchases GameDifficulty SessionsPerWeek \
0 0 Medium 6
1 0 Medium 5
2 0 Easy 16
3 1 Easy 9
4 0 Medium 2
... ... ... ...
40029 0 Easy 4
40030 0 Hard 19
40031 1 Easy 10
40032 1 Medium 3
40033 0 Easy 13
AvgSessionDurationMinutes PlayerLevel AchievementsUnlocked \
0 108 79 25
1 144 11 10
2 142 35 41
3 85 57 47
4 131 95 37
... ... ... ...
40029 75 85 14
40030 114 71 27
40031 176 29 1
40032 128 70 10
40033 84 72 39
EngagementLevel
0 Medium
1 Medium
2 High
3 Medium
4 Medium
... ...
40029 Medium
40030 High
40031 High
40032 Medium
40033 Medium
[40034 rows x 13 columns]
In [2]:
import pandas as df
import numpy as np
from sklearn.model_selection import train_test_split, GridSearchCV, cross_val_score
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
import matplotlib.pyplot as plt
import joblib # to save the trained model
data = df.read_csv(r'C:\Users\GelsthN\OneDrive - DVLA\Desktop\Machine Learning Assignment\data.csv')
# This is where I have cleansed the data for play time as I didn't need to see it to as many decimal places as I have.
data['PlayTimeHours'] = data['PlayTimeHours'].round(1)
TARGET = 'EngagementLevel'
#Here I am mapping the non-numerical columns into numeric values so that they can be used by the machine learning model
gender_map = {'Male': 0, 'Female': 1}
location_map = {'Asia': 0, 'Europe': 1, 'USA': 2, 'Other': 3}
genre_map = {
'Action': 0,
'RPG': 1,
'Simulation': 2,
'Sports': 3,
'Strategy': 4
}
difficulty_map = {'Easy': 0, 'Medium': 1, 'Hard': 2}
data['Gender'] = data['Gender'].map(gender_map)
data['Location'] = data['Location'].map(location_map)
data['GameGenre'] = data['GameGenre'].map(genre_map)
data['GameDifficulty'] = data['GameDifficulty'].map(difficulty_map)
engagement_map = {'Low': 0, 'Medium': 1, 'High': 2}
data[TARGET] = data[TARGET].map(engagement_map)
# Here I am choosing the data within the Target column which is the classifier for engagement level which is always either High, Medium or Low as the y axis as that is the column that was are targeting to see what influences it
y = data[TARGET]
# Here I am saying that the X axis is made up of all of the other columns within the dataset with the exception of the engagement Level column as it wouldn’t make sense to have that in both the Y and X for comparison
X = data.drop(columns=[TARGET])
print("Columns:", data.columns.tolist())
print("Rows:", len(data))
print(data.head())
#Here I am training the model splitting the X and Y columns randomly but using the number 42 as a way to be able to have someone else use the code and be able to see the same results. The model is using an 80% train and 20% testing ratio.
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
#Here I am training the Decision Tree model
model = DecisionTreeClassifier(
random_state=42,
max_depth=12, # prevents overfitting
min_samples_leaf=100 # requires meaningful leaf sizes
)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
Columns: ['PlayerID', 'Age', 'Gender', 'Location', 'GameGenre', 'PlayTimeHours', 'InGamePurchases', 'GameDifficulty', 'SessionsPerWeek', 'AvgSessionDurationMinutes', 'PlayerLevel', 'AchievementsUnlocked', 'EngagementLevel'] Rows: 40034 PlayerID Age Gender Location GameGenre PlayTimeHours InGamePurchases \ 0 9000 43 0 3 4 16.3 0 1 9001 29 1 2 4 5.5 0 2 9002 22 1 2 3 8.2 0 3 9003 35 0 2 0 5.3 1 4 9004 33 0 1 0 15.5 0 GameDifficulty SessionsPerWeek AvgSessionDurationMinutes PlayerLevel \ 0 1 6 108 79 1 1 5 144 11 2 0 16 142 35 3 0 9 85 57 4 1 2 131 95 AchievementsUnlocked EngagementLevel 0 25 1 1 10 1 2 41 2 3 47 1 4 37 1
In [3]:
#Here I have evaluated the accuracy of this model
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)
Accuracy: 0.8877232421631073
In [4]:
#Here I have evaluated the Precision, Recall and F1-Score
from sklearn.metrics import classification_report
print("Classification Report:\n")
print(classification_report(y_test, y_pred, target_names=['Low', 'Medium', 'High']))
Classification Report:
precision recall f1-score support
Low 0.89 0.83 0.86 2065
Medium 0.87 0.93 0.90 3875
High 0.92 0.87 0.89 2067
accuracy 0.89 8007
macro avg 0.89 0.88 0.88 8007
weighted avg 0.89 0.89 0.89 8007
In [5]:
#Here I have produced a confusion Matrix
from sklearn.metrics import confusion_matrix
import seaborn as sns
cm = confusion_matrix(y_test, y_pred)
print("Confusion Matrix:\n", cm)
#Here I have included a visual representation to make it easier to see the results
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['Low','Medium','High'], yticklabels=['Low','Medium','High'])
plt.xlabel("Predicted")
plt.ylabel("Actual")
plt.show()
Confusion Matrix: [[1709 306 50] [ 159 3605 111] [ 61 212 1794]]
In [6]:
#Here I have calculated the AUC-ROC
from sklearn.metrics import roc_auc_score
from sklearn.preprocessing import label_binarize
y_test_bin = label_binarize(y_test, classes=[0,1,2]) # 0=Low,1=Medium,2=High
y_pred_prob = model.predict_proba(X_test) # predicted probabilities for each class
auc_roc = roc_auc_score(y_test_bin, y_pred_prob, average='macro')
print("AUC-ROC (macro-average):", auc_roc)
AUC-ROC (macro-average): 0.9376145906916525
In [7]:
#Here I have produced a list of the column titles with an evaluation of each and which is the most important in affecting the overall enagementlevel of the user
importances = df.DataFrame({
'Feature': X.columns,
'Importance': model.feature_importances_
}).sort_values(by='Importance', ascending=False)
print(importances)
Feature Importance 8 SessionsPerWeek 0.627061 9 AvgSessionDurationMinutes 0.338717 11 AchievementsUnlocked 0.017211 10 PlayerLevel 0.014477 5 PlayTimeHours 0.000949 0 PlayerID 0.000717 1 Age 0.000385 3 Location 0.000192 7 GameDifficulty 0.000139 2 Gender 0.000078 4 GameGenre 0.000073 6 InGamePurchases 0.000000
In [19]:
#Now I am going to start on developing the SVM Model
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
svm_model = SVC(
kernel='sigmoid',
probability=True,
random_state=42
)
svm_model.fit(X_train_scaled, y_train)
y_pred_svm = svm_model.predict(X_test_scaled)
accuracy_svm = accuracy_score(y_test, y_pred_svm)
report = classification_report(y_test, y_pred_svm, target_names=['Low', 'Medium', 'High'])
print(report)
precision recall f1-score support
Low 0.59 0.59 0.59 2065
Medium 0.69 0.72 0.71 3875
High 0.77 0.71 0.74 2067
accuracy 0.68 8007
macro avg 0.68 0.67 0.68 8007
weighted avg 0.69 0.68 0.69 8007
In [20]:
print("SVM Accuracy:", accuracy_svm)
SVM Accuracy: 0.6849007118771075
In [21]:
from sklearn.metrics import confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt
cm_svm = confusion_matrix(y_test, y_pred_svm)
print("SVM Confusion Matrix:\n", cm_svm)
# Visualize it
sns.heatmap(cm_svm, annot=True, fmt='d', cmap='Greens',
xticklabels=['Low','Medium','High'],
yticklabels=['Low','Medium','High'])
plt.xlabel("Predicted")
plt.ylabel("Actual")
plt.title("SVM Confusion Matrix")
plt.show()
SVM Confusion Matrix: [[1218 776 71] [ 704 2801 370] [ 131 471 1465]]
In [36]:
#Here is where I have started to apply Kmeans (clustering) machine learning to this dataset
# I have removed the target column as this is not needed for the clustering
X_clustering = data.drop(columns=['EngagementLevel'])
print("Shape of data used for clustering:", X_clustering.shape)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
#Scaling has been applied here so that columns are normalised and so ones with large numbers like playtime don't dominate over columns I have manually assigned numbers from 0 to 3 and so the end result is not impacted
X_scaled = scaler.fit_transform(X_clustering)
#importing the machine learning model Kmeans which uses clustering
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=4, random_state=42)
cluster_labels = kmeans.fit_predict(X_scaled)
data['Cluster'] = cluster_labels
print("Cluster counts:")
print(data['Cluster'].value_counts())
cluster_summary = data.groupby('Cluster').mean()
print("Cluster Summary (averages of features):\n", cluster_summary)
Shape of data used for clustering: (40034, 13)
Cluster counts:
Cluster
1 11789
0 10163
2 9637
3 8445
Name: count, dtype: int64
Cluster Summary (averages of features):
PlayerID Age Gender Location GameGenre \
Cluster
0 29056.389058 31.787563 0.633474 0.412673 1.986028
1 29097.671813 32.156502 0.000000 1.403172 1.966240
2 29071.286189 32.108229 1.000000 1.976964 2.021999
3 28792.663233 31.878271 0.000000 1.897099 2.043813
PlayTimeHours InGamePurchases GameDifficulty SessionsPerWeek \
Cluster
0 12.125367 0.209092 0.441799 9.526124
1 11.993935 0.208330 0.671898 9.460344
2 11.960133 0.193110 0.871952 9.537408
3 12.017928 0.189343 0.854115 9.347425
AvgSessionDurationMinutes PlayerLevel AchievementsUnlocked \
Cluster
0 107.316737 48.836269 24.714258
1 53.447197 50.108406 24.801171
2 93.869254 49.880357 24.342223
3 138.489757 49.752872 24.127294
EngagementLevel
Cluster
0 1.103710
1 0.707948
2 0.999585
3 1.284784
In [35]:
from sklearn.metrics import silhouette_score
score = silhouette_score(X_scaled, cluster_labels)
print("Silhouette Score:", score)
Silhouette Score: 0.08898699285863793
In [ ]: