```
import numpy as np
def sigmoid(x):
# Sigmoid activation function: f(x) = 1 / (1 + e^(-x))
return 1 / (1 + np.exp(-x))
def deriv_sigmoid(x):
# Derivative of sigmoid: f'(x) = f(x) * (1 - f(x))
fx = sigmoid(x)
return fx * (1 - fx)
def mse_loss(y_true, y_pred):
# y_true and y_pred are numpy arrays of the same length.
return ((y_true - y_pred) ** 2).mean()
class Neuron:
def __init__(self, weights, bias):
self.weights = weights
self.bias = bias
def feedforward(self, inputs):
# Weight inputs, add bias, then use the activation function
total = np.dot(self.weights, inputs) + self.bias
return sigmoid(total)
class OurNeuralNetwork:
'''
A neural network with:
- 2 inputs
- a hidden layer with 2 neurons (h1, h2)
- an output layer with 1 neuron (o1)
*** DISCLAIMER ***:
The code below is intended to be simple and educational, NOT optimal.
Real neural net code looks nothing like this. DO NOT use this code.
Instead, read/run it to understand how this specific network works.
'''
def __init__(self):
# Weights
self.w1 = np.random.normal()
self.w2 = np.random.normal()
self.w12_3 = np.random.normal()
self.w12_4 = np.random.normal()
self.w3 = np.random.normal()
self.w4 = np.random.normal()
self.w34_3=np.random.normal()
self.w34_4=np.random.normal()
self.w3_1 = np.random.normal()
self.w3_2 = np.random.normal()
self.w3_3 = np.random.normal()
self.w3_4 = np.random.normal()
self.w4_1 = np.random.normal()
self.w4_2 = np.random.normal()
self.w4_3 =np.random.normal()
self.w4_4 =np.random.normal()
self.w5 = np.random.normal()
self.w6 = np.random.normal()
self.w56_3=np.random.normal()
self.w56_4=np.random.normal()
self.w7 =np.random.normal()
self.w8 =np.random.normal()
self.w9 =np.random.normal()
self.w10 =np.random.normal()
self.w11 =np.random.normal()
self.w12 =np.random.normal()
# Biases
self.b1 = np.random.normal()
self.b2 = np.random.normal()
self.b12_3=np.random.normal()
self.b12_4=np.random.normal()
#self.b3 = np.random.normal()
self.b5 = np.random.normal()
def feedforward(self, x):
#o1 = sigmoid(self.w5 * h1 + self.w6 * h2 + self.b5) #3)'''
h1 = sigmoid(self.w1 *x[0] +self.w2*x[1] + self.w12_3*x[2] + self.w12_4*x[3] + self.b1 )
h2= sigmoid(self.w3*x[0]+ self.w4*x[1]+self.w34_3*x[2] + self.w34_4*x[3] + self.b2)
h3= sigmoid(self.w3_1*x[0] + self.w3_2*x[1]+ self.w3_3*x[2]+self.w3_4*x[3] +self.b12_3 )
h4= sigmoid(self.w4_1*x[0] + self.w4_2*x[1] + self.w4_3*x[2] + self.w4_4*x[3] +self.b12_4)
o1= sigmoid(self.w5*h1 +self.w6*h2 + self.w56_3*h3+ self.w56_4*h4 + self.b5)
return o1
def train(self, data, all_y_trues):
'''
- data is a (n x 2) numpy array, n = # of samples in the dataset.
- all_y_trues is a numpy array with n elements.
Elements in all_y_trues correspond to those in data.
'''
learn_rate = 0.1 #0.1
epochs = 4000 #1000 # number of times to loop through the entire dataset
for epoch in range(epochs):
for x, y_true in zip(data, all_y_trues):
# --- Do a feedforward (we'll need these values later)
sum_h1 = self.w1 * x[0] + self.w2 * x[1] + self.w12_3 * x[2] + self.w12_4 * x[3] +self.b1
h1 = sigmoid(sum_h1)
sum_h2 = self.w3 * x[0] + self.w4 * x[1] + self.w34_3 * x[2] + self.w34_4 * x[3] + self.b2
h2 = sigmoid(sum_h2)
sum_h3 = self.w3_1 * x[0] + self.w3_2 * x[1] + self.w3_3 * x[2] + self.w3_4 * x[3] +self.b12_3
h3 = sigmoid(sum_h3)
sum_h4 = self.w4_1 * x[0] + self.w4_2 * x[1] + self.w4_3 * x[2] + self.w4_4 * x[3] + self.b12_4
h4 = sigmoid(sum_h4)
#sum_o1 = self.w5 * h1 + self.w6 * h2 + self.b3
sum_o1 = self.w5 * h1 + self.w6 * h2 + self.w56_3 * h3 + self.w56_4*h4 +self.b5 #+ self.b3
o1 = sigmoid(sum_o1)
y_pred = o1
# --- Calculate partial derivatives.
# --- Naming: d_L_d_w1 represents "partial L / partial w1"
#d_L_d_ypred = -2 * (y_true - y_pred)
d_L_d_ypred = -4 * (y_true - y_pred)
# Neuron o1 原 Neuron o1
d_ypred_d_w5 = h1 * deriv_sigmoid(sum_o1)
d_ypred_d_w6 = h2 * deriv_sigmoid(sum_o1)
d_ypred_d_w56_3=h3* deriv_sigmoid(sum_o1)
d_ypred_d_w56_4=h4* deriv_sigmoid(sum_o1)
#d_ypred_d_b3 = deriv_sigmoid(sum_o1)
d_ypred_d_b5 = deriv_sigmoid(sum_o1)
d_ypred_d_h1 = self.w5 * deriv_sigmoid(sum_o1)
d_ypred_d_h2 = self.w6 * deriv_sigmoid(sum_o1)
d_ypred_d_h3 = self.w56_3 * deriv_sigmoid(sum_o1)
d_ypred_d_h4 = self.w56_4 * deriv_sigmoid(sum_o1)
# Neuron h1
d_h1_d_w1 = x[0] * deriv_sigmoid(sum_h1)
d_h1_d_w2 = x[1] * deriv_sigmoid(sum_h1)
d_h1_d_w12_3=x[2] * deriv_sigmoid(sum_h1)
d_h1_d_w12_4=x[3] * deriv_sigmoid(sum_h1)
d_h1_d_b1 = deriv_sigmoid(sum_h1)
# Neuron h2
d_h2_d_w3 = x[0] * deriv_sigmoid(sum_h2)
d_h2_d_w4 = x[1] * deriv_sigmoid(sum_h2)
d_h2_d_w34_3=x[2] * deriv_sigmoid(sum_h2)
d_h2_d_w34_4=x[3] * deriv_sigmoid(sum_h2)
d_h2_d_b2 = deriv_sigmoid(sum_h2)
# Neuron h3
d_h3_d_w3_1 = x[0] * deriv_sigmoid(sum_h3)
d_h3_d_w3_2 = x[1] * deriv_sigmoid(sum_h3)
d_h3_d_w3_3 = x[2] * deriv_sigmoid(sum_h3)
d_h3_d_w3_4 = x[3] * deriv_sigmoid(sum_h3)
d_h3_d_b3 = deriv_sigmoid(sum_h3)
# Neuron h4
d_h4_d_w4_1 = x[0] * deriv_sigmoid(sum_h4)
d_h4_d_w4_2 = x[1] * deriv_sigmoid(sum_h4)
d_h4_d_w4_3 = x[2] * deriv_sigmoid(sum_h4)
d_h4_d_w4_4 = x[3] * deriv_sigmoid(sum_h4)
d_h4_d_b4 = deriv_sigmoid(sum_h4)
#====================================================================
# --- Update weights and biases
# Neuron h1
self.w1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w1
self.w2 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w2
self.w12_3 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w12_3
self.w12_4 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w12_4
self.b1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_b1
# Neuron h2
self.w3 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w3
self.w4 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w4
self.w34_3 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w34_3
self.w34_4 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w34_4
self.b2 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_b2
#Neuron h3
self.w3_1 -= learn_rate * d_L_d_ypred * d_ypred_d_h3 * d_h3_d_w3_1
self.w3_2 -= learn_rate * d_L_d_ypred * d_ypred_d_h3 * d_h3_d_w3_2
self.w3_3 -= learn_rate * d_L_d_ypred * d_ypred_d_h3 * d_h3_d_w3_3
self.w3_4 -= learn_rate * d_L_d_ypred * d_ypred_d_h3 * d_h3_d_w3_4
self.b12_3 -= learn_rate * d_L_d_ypred * d_ypred_d_h3 * d_h3_d_b3
# Neuron h4
self.w4_1 -= learn_rate * d_L_d_ypred * d_ypred_d_h4 * d_h4_d_w4_1
self.w4_2 -= learn_rate * d_L_d_ypred * d_ypred_d_h4 * d_h4_d_w4_2
self.w4_3 -= learn_rate * d_L_d_ypred * d_ypred_d_h4 * d_h4_d_w4_3
self.w4_4 -= learn_rate * d_L_d_ypred * d_ypred_d_h4 * d_h4_d_w4_4
self.b12_4 -= learn_rate * d_L_d_ypred * d_ypred_d_h4 * d_h4_d_b4
#===================================================================
# Neuron o1
self.w5 -= learn_rate * d_L_d_ypred * d_ypred_d_w5
self.w6 -= learn_rate * d_L_d_ypred * d_ypred_d_w6
self.w56_3 -= learn_rate * d_L_d_ypred * d_ypred_d_w56_3
self.w56_4 -= learn_rate * d_L_d_ypred * d_ypred_d_w56_4
self.b5 -= learn_rate * d_L_d_ypred * d_ypred_d_b5
# --- Calculate total loss at the end of each epoch
if 0 == epoch % 100: # == 0:
y_preds = np.apply_along_axis(self.feedforward, 1, data)
loss = mse_loss(all_y_trues, y_preds)
print("Epoch %d loss: %.5f" % (epoch, loss))
# Define dataset
data = np.array([
[9,0,
9,0], #1yes -2, -1], # Alice
[9,9,
0,0], #0_no 25, 6], # Bob
[0,0,8,9], #0_no 17, 4], # Charlie
[0,8,0,8], #1yes-15, -6], # Diana
[9,0,8,0], #1yes
[0,0,99,99], #0_no
[99,0,98,0], #1yes
[0,0,0,0], #0_no
[99,99,99,99], #0_no
])
all_y_trues = np.array([
1, # Alice
0, # Bob
0, # Charlie
1, # Diana
1,
0,
1,
0,
0,
])
# Train our neural network!
network = OurNeuralNetwork()
network.train(data, all_y_trues)
# Make some predictions
No01= np.array([9,9, 0,0] ) #-7, -3]) # 128 pounds, 63 inches
Ye01 = np.array([0,9, 0,9] ) #20, 2]) # 155 pounds, 68 inches
No02=np.array([0,7, 8,7])
No03=np.array([0,0,0,0])
Ye3=np.array([99,0,98,0])
No4=np.array([99,98,97,96])
print("No01: %.3f" % network.feedforward(No01) ) # 0.951 - F
print("Ye01: %.3f" % network.feedforward(Ye01 )) # 0.039 - M
print("No02: %.4f" % network.feedforward(No02) ) #
print("No03: %.4f" % network.feedforward(No03) )
print("Ye3: %.5f" % network.feedforward(Ye3) )
print("No4: %.6f" %network.feedforward(No4) )
```