Как сделать НС, например, с 4 входами и только одним выходом? Точнее, (4,4) входная матрица ---> (1,1) выходная матрица вместо (4,1) выходная матрица.
Прошло несколько недель, что меня заинтересовало NN и я разобрались в математике solid. У меня есть шаблон, который отлично работает, и я пытаюсь обобщить его, чтобы можно было добавить больше слоев. Работа еще продолжается, но я только что понял, что не могу производить меньше, чем вводимые ресурсы. Зачем ? Это кажется довольно обычным, например, при классификации изображений у вас есть тысячи входов и около 10 выходов.
Когда я занимаюсь математикой, кажется невозможным получить меньше строк вывода, чем строк ввода, потому что матричное исчисление несет введенный номер полностью. В любом случае вот мой код, адаптированный из другого: (Кстати, он отлично работает, обучение и все такое, он может, например, изучить вентиль AND)
import numpy as np
from matplotlib import pyplot as plt
# Activation function
def sigmoid(t):
return 1 / (1 + np.exp(-t))
# Derivative of sigmoid
def sigmoid_derivative(p):
return p * (1 - p)
# Class definition
class NeuralNetwork:
error_history = []
hidden_size = 4
layers = 1 # Number of hidden layers with fixed size
layers_list = [] # Layers list. Useful to add new layers
w_list = [] # Weights list
def __init__(self, x, y):
self.input = x
self.y = y
# Input special case.
self.w_list.append(np.random.rand(self.input.shape[1], self.hidden_size))
#More weights for more hidden layers
for i in range(self.layers-1): # adds nothing if only one layer
self.w_list.append(np.random.rand(self.hidden_size, self.hidden_size))
# Output special case
self.w_list.append(np.random.rand(self.hidden_size, y.shape[1])) #y.shape[1] used to be 1
self.output = np.zeros(y.shape) #NN output
# Init layers
self.layers_list.append(np.zeros((self.input.shape[0], self.hidden_size)))
# More layers
for i in range(self.layers - 1): # adds nothing if only one layer
self.layers_list.append(np.zeros((self.hidden_size, self.hidden_size)))
self.layers_list.append(np.zeros((4, 1))) # LAST LAYER to OUTPUT
# The "1" is very practical to give neat results, like the end on an logical equation.
# 0 1 0 -> 1. Otherwise we end up with double arrays
def feedforward(self):
self.layers_list[0] = sigmoid(np.dot(self.input, self.w_list[0]))
for i in range (self.layers):
self.layers_list[i+1] = sigmoid(np.dot(self.layers_list[i], self.w_list[i+1]))
self.output = self.layers_list[-1] #last layer.
def backprop(self):
delta = 2 * (self.y - self.output) * sigmoid_derivative(self.output)
d_weights2 = np.dot(self.layers_list[0].T, delta )
#special case : input weights
d_weights1 = np.dot(self.input.T, np.dot(delta,self.w_list[1].T) * sigmoid_derivative(self.layers_list[0]))
self.w_list[0] += d_weights1
self.w_list[1] += d_weights2
def train(self, epochs):
for i in range(epochs): # trains the NN a lot of times
self.feedforward()
self.backprop()
self.error_history.append(self.loss())
# This should ONLY be called after training the NN.
# apply this and just read last layer. careful of input dimensions
def predict(self, entry):
self.input = entry
self.feedforward()
print("test result: ")
print(self.output)
# Standard loss function of the NN
def loss(self):
return np.mean(np.square(self.y - self.layers_list[1]))
# Showing the error converging to a minimum ! Hopefully.
def graph(self):
plt.plot(self.error_history)
plt.show()
plt.xlabel("Error")
plt.ylabel("Epochs")
if __name__ == "__main__":
# Each row is a training example, each column is a feature [X1, X2, X3]
X = np.array(([0, 0, 1],
[0, 1, 1],
[1, 0, 1],
[1, 1, 1]), dtype=float)
y = np.array(([0],
[1],
[1],
[0]), dtype=float)
X2 = np.array(([0], [0],[1],[1]), dtype=float)
X3 = np.array(([0], [0], [1]), dtype=float)
X32 = np.array(([0, 0, 1],
[0, 1, 1],
[1, 1, 1]), dtype=float)
y3 = np.array(([0],[1], [1]), dtype=float)
# This example shows NN learning AND gate.
X_and = np.array(([0, 0],
[0, 1],
[1, 0],
[1, 1]), dtype=float)
y_and = np.array(([0],
[0],
[0],
[1]), dtype=float)
and_test = np.array(([1, 0],
[0, 1],
[1,1],
[0, 1]), dtype=float)
nn = NeuralNetwork(X_and, y_and)
nn.train(1500)
print("layer1")
print(nn.layers_list[0])
print("layer2")
print(nn.layers_list[1])
nn.predict(and_test)
nn.graph()