diff --git a/digit_prediction.png b/digit_prediction.png new file mode 100644 index 0000000..f086839 Binary files /dev/null and b/digit_prediction.png differ diff --git a/guess_test.py b/guess_test.py new file mode 100644 index 0000000..3829565 --- /dev/null +++ b/guess_test.py @@ -0,0 +1,35 @@ +import mnist_loader +import network +import numpy as np +import matplotlib.pyplot as plt + +# Load data +training_data, validation_data, test_data = mnist_loader.load_data_wrapper() +# Ensure test_data is a list of (x, y) pairs +test_data = list(test_data) + +# Pick one sample +x, y = test_data[0] + +# Create and train a network +net = network.Network([784, 30, 10]) +training_data = list(training_data) +net.SGD(training_data, 1, 10, 3.0) + +# Call the guess function defined in network.py (it expects self, x) +pred_by_guess = network.guess(net, x) + +# Reshape x from (784, 1) to (28, 28) and display as image +x_image = x.reshape(28, 28) +plt.figure(figsize=(6, 6)) +plt.imshow(x_image, cmap='gray') +plt.title(f"Actual: {y}, Predicted: {int(pred_by_guess)}") +plt.axis('off') +plt.tight_layout() +plt.savefig('digit_prediction.png') +plt.show() +print(f"Image saved as digit_prediction.png") + + +print("Actual label:", y) +print("network.guess predicted:", int(pred_by_guess)) diff --git a/network.py b/network.py index 78629cf..73a4232 100644 --- a/network.py +++ b/network.py @@ -84,7 +84,7 @@ def update_mini_batch(self, mini_batch, eta): for x, y in mini_batch: delta_nabla_b, delta_nabla_w = self.backprop(x, y) nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)] - nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)] + nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)] self.weights = [w-(eta/len(mini_batch))*nw for w, nw in zip(self.weights, nabla_w)] self.biases = [b-(eta/len(mini_batch))*nb @@ -95,6 +95,7 @@ def backprop(self, x, y): gradient for the cost function C_x. ``nabla_b`` and ``nabla_w`` are layer-by-layer lists of numpy arrays, similar to ``self.biases`` and ``self.weights``.""" + # print("weights first row: {}".format(self.weights[0])) nabla_b = [np.zeros(b.shape) for b in self.biases] nabla_w = [np.zeros(w.shape) for w in self.weights] # feedforward @@ -139,6 +140,14 @@ def cost_derivative(self, output_activations, y): \partial a for the output activations.""" return (output_activations-y) +def guess(self, x): + """Return the index of the highest activation neuron.""" + activation = x + + for b, w in zip(self.biases, self.weights): + activation = sigmoid(np.dot(w, activation)+b) + + return np.argmax(activation) #### Miscellaneous functions def sigmoid(z): """The sigmoid function.""" diff --git a/practice.py b/practice.py new file mode 100644 index 0000000..e69de29 diff --git a/quadratic_cost_demo.py b/quadratic_cost_demo.py new file mode 100644 index 0000000..330d31d --- /dev/null +++ b/quadratic_cost_demo.py @@ -0,0 +1,102 @@ +"""quadratic_cost_demo.py +~~~~~~~~~~~~~~~~~~~~~~~~ + +Demonstration of quadratic cost function during gradient descent training. + +""" + +import numpy as np +import matplotlib.pyplot as plt + + +def sigmoid(z): + """The sigmoid function.""" + return 1.0/(1.0+np.exp(-z)) + + +def sigmoid_prime(z): + """Derivative of the sigmoid function.""" + return sigmoid(z)*(1-sigmoid(z)) + + +def quadraticCostDemo(epochs): + """Demonstrate quadratic cost function over epochs.""" + w = 0.6 + b = 0.9 + x = 1 + y = 0 # desired output + cost_history = {} # dictionary to store cost values + + # Enable interactive mode for real-time plotting + plt.ion() + fig, ax = plt.subplots(figsize=(10, 6)) + + for i in range(1, epochs): + z = w * x + b + a = sigmoid(z) + cost = 0.5 * (a - y) ** 2 + cost_history[i] = cost + + # Calculate gradients + nabla_cW = (a - y) * sigmoid_prime(z) * x + nabla_cB = (a - y) * sigmoid_prime(z) + + # Update weights and bias + w = w - nabla_cW + b = b - nabla_cB + + # Update plot in real-time + if i % 5 == 0 or i == 1: # Update every 5 epochs for better visualization + ax.clear() + epoch_list = sorted(cost_history.keys()) + cost_list = [cost_history[e] for e in epoch_list] + + ax.plot(epoch_list, cost_list, 'b-', linewidth=2) + ax.set_xlabel('Epoch', fontsize=12) + ax.set_ylabel('Quadratic Cost', fontsize=12) + ax.set_title('Quadratic Cost Function Over Training Epochs', fontsize=14) + ax.grid(True, alpha=0.3) + plt.tight_layout() + plt.pause(0.01) # Small pause to see the update + + # Turn off interactive mode + plt.ioff() + + return cost_history + + +def plot_cost_history(cost_history): + """Plot the cost function over epochs.""" + epochs = sorted(cost_history.keys()) + costs = [cost_history[epoch] for epoch in epochs] + + plt.figure(figsize=(10, 6)) + plt.plot(epochs, costs, 'b-', linewidth=2) + plt.xlabel('Epoch', fontsize=12) + plt.ylabel('Quadratic Cost', fontsize=12) + plt.title('Quadratic Cost Function Over Training Epochs', fontsize=14) + plt.grid(True, alpha=0.3) + plt.tight_layout() + plt.savefig('quadratic_cost_plot.png', dpi=150, bbox_inches='tight') + print("Plot saved to quadratic_cost_plot.png") + plt.show() + + +if __name__ == "__main__": + # Run the demo with 100 epochs + epochs = 300 + cost_history = quadraticCostDemo(epochs) + + # Save final plot + plt.figure(figsize=(10, 6)) + epoch_list = sorted(cost_history.keys()) + cost_list = [cost_history[e] for e in epoch_list] + plt.plot(epoch_list, cost_list, 'b-', linewidth=2) + plt.xlabel('Epoch', fontsize=12) + plt.ylabel('Quadratic Cost', fontsize=12) + plt.title('Quadratic Cost Function Over Training Epochs', fontsize=14) + plt.grid(True, alpha=0.3) + plt.tight_layout() + plt.savefig('quadratic_cost_plot.png', dpi=150, bbox_inches='tight') + print("Plot saved to quadratic_cost_plot.png") + plt.show() diff --git a/quadratic_cost_plot.png b/quadratic_cost_plot.png new file mode 100644 index 0000000..9ac8298 Binary files /dev/null and b/quadratic_cost_plot.png differ diff --git a/test.py b/test.py index d1f4996..f6b84df 100644 --- a/test.py +++ b/test.py @@ -17,19 +17,18 @@ # ---------------------- # - read the input data: -''' + import mnist_loader training_data, validation_data, test_data = mnist_loader.load_data_wrapper() training_data = list(training_data) -''' # --------------------- # - network.py example: -#import network +import network + -''' net = network.Network([784, 30, 10]) -net.SGD(training_data, 30, 10, 3.0, test_data=test_data) -''' +net.SGD(training_data, 1, 10, 3.0, test_data=test_data) + # ---------------------- # - network2.py example: @@ -124,6 +123,7 @@ """ +''' def testTheano(): from theano import function, config, shared, sandbox import theano.tensor as T @@ -149,17 +149,18 @@ def testTheano(): print('Used the gpu') # Perform check: #testTheano() +''' # ---------------------- # - network3.py example: -import network3 -from network3 import Network, ConvPoolLayer, FullyConnectedLayer, SoftmaxLayer # softmax plus log-likelihood cost is more common in modern image classification networks. +# import network3 +# from network3 import Network, ConvPoolLayer, FullyConnectedLayer, SoftmaxLayer # softmax plus log-likelihood cost is more common in modern image classification networks. # read data: -training_data, validation_data, test_data = network3.load_data_shared() -# mini-batch size: -mini_batch_size = 10 +# training_data, validation_data, test_data = network3.load_data_shared() +# # mini-batch size: +# mini_batch_size = 10 # chapter 6 - shallow architecture using just a single hidden layer, containing 100 hidden neurons. ''' @@ -195,6 +196,7 @@ def testTheano(): ''' # chapter 6 - rectified linear units and some l2 regularization (lmbda=0.1) => even better accuracy +''' from network3 import ReLU net = Network([ ConvPoolLayer(image_shape=(mini_batch_size, 1, 28, 28), @@ -208,3 +210,4 @@ def testTheano(): FullyConnectedLayer(n_in=40*4*4, n_out=100, activation_fn=ReLU), SoftmaxLayer(n_in=100, n_out=10)], mini_batch_size) net.SGD(training_data, 60, mini_batch_size, 0.03, validation_data, test_data, lmbda=0.1) +''' \ No newline at end of file