Skip to content

Commit 47f7d10

Browse files
authored
Merge pull request #1 from commitBlob/feature/custom_nn
Add custom neural network
2 parents 594903e + c81d8e6 commit 47f7d10

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
2+
#%% packages
3+
import numpy as np
4+
import pandas as pd
5+
import seaborn as sns
6+
from sklearn.preprocessing import StandardScaler
7+
from sklearn.model_selection import train_test_split
8+
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
9+
10+
#%% data prep
11+
# source: https://www.kaggle.com/datasets/rashikrahmanpritom/heart-attack-analysis-prediction-dataset
12+
df = pd.read_csv('heart.csv')
13+
df.head()
14+
15+
#%% separate independent / dependent features
16+
X = np.array(df.loc[ :, df.columns != 'output'])
17+
y = np.array(df['output'])
18+
19+
print(f"X: {X.shape}, y: {y.shape}")
20+
21+
#%% Train / Test Split
22+
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=12)
23+
24+
#%% scale the data
25+
scaler = StandardScaler()
26+
X_train_scale = scaler.fit_transform(X_train)
27+
X_test_scale = scaler.transform(X_test)
28+
29+
#%% network class
30+
class CustomNeuralNetwork:
31+
def __init__(self, learning_rate, X_train, y_train, X_test, y_test):
32+
self.weights = np.random.randn(X_train.shape[1])
33+
self.biases = np.random.randn()
34+
self.learning_rate = learning_rate
35+
self.X_train = X_train
36+
self.y_train = y_train
37+
self.X_test = X_test
38+
self.y_test = y_test
39+
self.learning_losses_train = []
40+
self.learning_losses_test = []
41+
42+
def activationFunction(self, x):
43+
# sigmoid
44+
return 1 / (1 + np.exp(-x))
45+
46+
def activationDerivative(self, x):
47+
# sigmoid derivative
48+
return self.activationFunction(x) * (1 - self.activationFunction(x))
49+
50+
def forwardPass(self, derivative_x):
51+
hidden_layer_1 = np.dot(derivative_x, self.weights) + self.biases
52+
activate_layer = self.activationFunction(hidden_layer_1)
53+
54+
return activate_layer
55+
56+
def backwardPass(self, independent_features, y_true_values):
57+
# calculcate gradients1
58+
hidden_layer_1 = np.dot(independent_features, self.weights) + self.biases
59+
y_predictions = self.forwardPass(independent_features)
60+
61+
derivative_of_losses_to_predictions = 2 * (y_predictions - y_true_values)
62+
derivative_of_predictions_to_hidden_layer = self.activationDerivative(hidden_layer_1)
63+
derivative_of_hidden_layer_biases = 1
64+
derivative_of_hidden_layer_weights = independent_features
65+
66+
derivatives_biases = derivative_of_losses_to_predictions * derivative_of_predictions_to_hidden_layer * derivative_of_hidden_layer_biases
67+
derivatives_weights = derivative_of_losses_to_predictions * derivative_of_predictions_to_hidden_layer * derivative_of_hidden_layer_weights
68+
69+
return derivatives_biases, derivatives_weights
70+
71+
def optimiser(self, derivatives_biases, derivatives_weights):
72+
# update weights
73+
self.biases = self.biases - derivatives_biases * self.learning_rate
74+
self.weights = self.weights - derivatives_weights * self.learning_rate
75+
76+
def train(self, iterations):
77+
for iteration in range(iterations):
78+
# get random position
79+
random_position = np.random.randint(len(self.X_train))
80+
81+
# forward pass
82+
y_train_true = self.y_train[random_position]
83+
y_train_predictictions = self.forwardPass(self.X_train[random_position])
84+
85+
# calculate training losses
86+
losses = np.sum(np.square(y_train_predictictions - y_train_true))
87+
self.learning_losses_train.append(losses)
88+
89+
# calculate gradients
90+
derivatives_biases, derivatives_weights = self.backwardPass(self.X_train[random_position], self.y_train[random_position])
91+
92+
# update rates
93+
self.optimiser(derivatives_biases, derivatives_weights)
94+
95+
# calculate errors for test data
96+
losses_sum = 0
97+
for i in range(len(self.X_test)):
98+
y_true_value = self.y_test[i]
99+
y_predictions = self.forwardPass(self.X_test[i])
100+
101+
losses_sum += np.square(y_predictions - y_true_value)
102+
self.learning_losses_test.append(losses_sum)
103+
return 'training done'
104+
105+
#%% Hyper parameters
106+
learning_rate = 0.2
107+
iterations = 1000
108+
109+
#%% model instance and training
110+
neural_network = CustomNeuralNetwork(learning_rate, X_train_scale, y_train, X_test_scale, y_test)
111+
112+
neural_network.train(iterations)
113+
114+
# %% check losses
115+
sns.lineplot(x=list(range(len(neural_network.learning_losses_test))), y=neural_network.learning_losses_test)
116+
117+
# %% iterate over test data
118+
total_observations = X_test_scale.shape[0]
119+
correct_predictions = 0
120+
y_preditctions = []
121+
for i in range(total_observations):
122+
y_true = y_test[i]
123+
y_preditction = np.round(neural_network.forwardPass(X_test_scale[i]))
124+
y_preditctions.append(y_preditction)
125+
correct_predictions += 1 if y_true == y_preditction else 0
126+
127+
# %% Calculate Accuracy
128+
correct_predictions / total_observations
129+
130+
# %% Baseline Classifier
131+
from collections import Counter
132+
Counter(y_test)
133+
134+
# %% Confusion Matrix
135+
cm = confusion_matrix(y_true=y_test, y_pred=y_preditctions)
136+
137+
138+
# %%
139+
import matplotlib.pyplot as plt
140+
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=['true', 'false'])
141+
142+
disp.plot()
143+
plt.show()
144+
145+
# %%

0 commit comments

Comments
 (0)