-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathneural6.py
192 lines (155 loc) · 9.05 KB
/
neural6.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
import numpy as np
from PIL import Image
import streamlit as st
import joblib
import os
# Sigmoid activation function
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# Derivative of the sigmoid function
def sigmoid_derivative(x):
return x * (1 - x)
# Define the neural network architecture
class NeuralNetwork:
def __init__(self, input_nodes, hidden_nodes, output_nodes, hidden_layers=2):
self.input_nodes = input_nodes
self.hidden_nodes = hidden_nodes
self.output_nodes = output_nodes
self.hidden_layers = hidden_layers
# Initialize weights and biases with smaller values (Xavier/Glorot Initialization)
self.weights = [np.random.randn(input_nodes, hidden_nodes) / np.sqrt(input_nodes)] + \
[np.random.randn(hidden_nodes, hidden_nodes) / np.sqrt(hidden_nodes) for _ in range(hidden_layers - 1)] + \
[np.random.randn(hidden_nodes, output_nodes) / np.sqrt(hidden_nodes)]
self.biases = [np.random.randn(hidden_nodes) / np.sqrt(hidden_nodes) for _ in range(hidden_layers)] + \
[np.random.randn(output_nodes) / np.sqrt(output_nodes)]
# Forward pass - Added safe_sigmoid function to keep values under a threshold and avoid OverflowError
def feedforward(self, inputs):
def safe_sigmoid(x):
return sigmoid(np.clip(x, -100, 100))
self.layers = [inputs]
for i in range(len(self.weights)):
self.layers.append(safe_sigmoid(np.dot(self.layers[-1], self.weights[i]) + self.biases[i]))
return self.layers[-1]
# Backward pass
def backpropagation(self, inputs, target_outputs, learning_rate=0.5):
deltas = [None] * (self.hidden_layers + 1)
# Calculate output error
output_error = target_outputs - self.layers[-1]
deltas[-1] = output_error * sigmoid_derivative(self.layers[-1])
# Calculate hidden error
for i in range(len(deltas) - 2, -1, -1):
hidden_error = np.dot(deltas[i+1], self.weights[i+1].T)
deltas[i] = hidden_error * sigmoid_derivative(self.layers[i+1])
# Update weights and biases
for i in range(len(self.weights)):
self.weights[i] += learning_rate * np.dot(self.layers[i].T, deltas[i])
self.biases[i] += learning_rate * np.sum(deltas[i], axis=0)
# Train the neural network
def train(self, inputs, target_outputs, epochs, learning_rate):
for epoch in range(epochs):
predicted_outputs = self.feedforward(inputs)
self.backpropagation(inputs, target_outputs, learning_rate)
# Evaluate the neural network performance
def evaluate(self, test_inputs, test_outputs):
test_predictions = self.feedforward(test_inputs)
predicted_classes = np.argmax(test_predictions, axis=1)
true_classes = np.argmax(test_outputs, axis=1)
accuracy = np.sum(predicted_classes == true_classes) / len(true_classes)
return accuracy
# Create a function to convert images to input data accepted by the network
def process_image(img_path, flatten=True):
try:
img = Image.open(img_path)
except FileNotFoundError:
print(f"The image file '{img_path}' was not found. Please check the file path and try again.")
return None
img = img.resize((32, 32))
img_array = np.array(img, dtype=np.float32) / 255
if flatten:
img_array = img_array.flatten()
return img_array
if __name__ == "__main__":
# Check if a pre-trained model exists
model_path = "neural_network_model.joblib"
if os.path.exists(model_path):
# Load the pre-trained model
neural_network = joblib.load(model_path)
else:
# Create a neural network with increased input nodes, hidden nodes, and a higher number of output nodes for handling more classes
neural_network = NeuralNetwork(3072, 150, 2, hidden_layers=3) # Updated output_nodes to 4
# Define training data and add more image samples
cat_paths = ['cat1.jpg', 'cat2.jpg', 'cat3.jpg', 'cat4.jpg', 'cat5.jpg', 'cat6.jpg', 'cat7.jpg', 'cat8.jpg', 'cat9.jpg', 'cat10.jpg']
dog_paths = ['dog1.jpg', 'dog2.jpg', 'dog3.jpg', 'dog4.jpg', 'dog5.jpg', 'dog6.jpg', 'dog7.jpg', 'dog8.jpg', 'dog9.jpg', 'dog10.jpg']
cat_inputs = [process_image(cat_path) for cat_path in cat_paths]
dog_inputs = [process_image(dog_path) for dog_path in dog_paths]
inputs = np.concatenate([cat_inputs, dog_inputs], axis=0)
if not inputs.any():
print("No valid images found for training")
else:
# Define target outputs with an additional class
cat_targets = np.array([[1, 0] for _ in cat_inputs])
dog_targets = np.array([[0, 1] for _ in dog_inputs])
target_outputs = np.concatenate([cat_targets, dog_targets], axis=0)
# Train the neural network
neural_network.train(inputs, target_outputs, epochs=2500, learning_rate=0.2)
# Save the trained model
joblib.dump(neural_network, model_path)
# Test the neural network with more images and evaluate its performance
test_image_paths = ['dog14.jpg']
test_inputs = [process_image(test_image_path) for test_image_path in test_image_paths]
test_inputs = np.array([test_input for test_input in test_inputs if test_input is not None])
if not test_inputs.any():
print("No valid test images found")
else:
test_outputs = np.array([[1, 0]])
test_predictions = neural_network.feedforward(test_inputs)
print("Test image predictions: ", test_predictions)
# Evaluate the neural network performance
accuracy = neural_network.evaluate(test_inputs, test_outputs)
print(f"Neural network accuracy: {accuracy:.2%}")
def classify_image(predictions):
# Create a list of labels
labels = ['cat', 'dog']
# Find the index of the highest prediction
max_index = predictions.argmax()
# Return the label with the corresponding index
return labels[max_index]
# Example usage
predictions = test_predictions
label = classify_image(predictions[0])
print(f'This image looks most like a {label}.')
def main():
st.title("Image Classification with Neural Network")
uploaded_file = st.file_uploader("Choose an image of a dog ore a cat...", type="jpg")
if uploaded_file is not None:
st.image(uploaded_file, caption="Uploaded Image.", use_column_width=True)
st.write("")
st.write("Classifying...")
# Process the uploaded image
img_array = process_image(uploaded_file, flatten=True)
if img_array is not None:
img_array = img_array.reshape(1, -1) # Reshape for the neural network input
prediction = neural_network.feedforward(img_array)
# Display prediction result
st.write(f"Prediction Result: {classify_image(prediction[0])}")
# Show test image predictions
st.write("Test Image Predictions:")
st.write(prediction)
st.markdown("This application is an image classification tool using a neural network. The nn was made with python "
"using the numpy and joblib librairies, while the streamlit librairy was used to host and create the "
"front end interface of the app. The user can upload an image of a cat or a dog, and the neural network "
"classifies the image as either a cat or a dog based on its training. The neural network has been "
"trained on a dataset of images of cats and dogs (10 each).To test the model, you can upload images of "
"cats or dogs using the Streamlit interface. A potential weak spot could be the small size of the "
"training dataset and the simplicity of the neural network architecture "
"( it only has 3 hidden layers, total layers=5). To further improve the nn, we must consider data "
"augmentation, hyperparameter tuning, Regularization, and diversifying the dataset. The speed of the "
"application itself could also be inproved. This could be done best by using a a diffrent cloud service"
" to host it, or make a local version (which has the downside of varying speeds depending on the user "
"hardware).The main issue with this nn is that it tends to overfit for test images not in it's dataset "
"(the model learns training data too well, thus capturing noise and random fluctuations as data which "
"causes it to focus less on underlying patterns), which decreses the accuracy of the model.The advantages"
" of this implementation include: a somewhat user-friendly UI, and a quick and easy way to deploy a "
"pre-trained nn for image classification.")
if __name__ == "__main__":
main()