Производительность больше вам не помешает
This commit is contained in:
@@ -133,6 +133,9 @@ def backward(loss: Node):
|
|||||||
for node in reversed(topo):
|
for node in reversed(topo):
|
||||||
node._backward()
|
node._backward()
|
||||||
|
|
||||||
|
def update_weights(weight: Node, lr: float):
|
||||||
|
return Node(float(weight) - lr * weight.grad)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
x = Node(2, label="x")
|
x = Node(2, label="x")
|
||||||
|
|||||||
101
classes.py
101
classes.py
@@ -1,4 +1,6 @@
|
|||||||
|
import copy
|
||||||
import random
|
import random
|
||||||
|
from auto_diff import auto_diff
|
||||||
|
|
||||||
class DataSet:
|
class DataSet:
|
||||||
def __init__(self, func, N=1000) -> None:
|
def __init__(self, func, N=1000) -> None:
|
||||||
@@ -7,12 +9,97 @@ class DataSet:
|
|||||||
self.test = []
|
self.test = []
|
||||||
self.test_answs = []
|
self.test_answs = []
|
||||||
|
|
||||||
for i in range(N//5*4):
|
def gen_data():
|
||||||
x = random.uniform(1, 9)
|
x1 = random.uniform(-1, 1)
|
||||||
self.train.append(x)
|
x2 = random.uniform(-1, 1)
|
||||||
self.train_answs.append(func(x))
|
y = func(x1, x2)
|
||||||
|
return (x1, x2), y
|
||||||
|
|
||||||
|
for i in range(N):
|
||||||
|
(x1, x2), y = gen_data()
|
||||||
|
self.train.append((x1, x2))
|
||||||
|
self.train_answs.append(y)
|
||||||
|
|
||||||
for i in range(N//5):
|
for i in range(N//5):
|
||||||
x = random.uniform(1, 9)
|
(x1, x2), y = gen_data()
|
||||||
self.test.append(x)
|
self.test.append((x1, x2))
|
||||||
self.test_answs.append(func(x))
|
self.test_answs.append(y)
|
||||||
|
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"test: {self.test}\nansws: {self.test_answs}"
|
||||||
|
|
||||||
|
|
||||||
|
class Neuron:
|
||||||
|
def __init__(self, weights_num: int) -> None:
|
||||||
|
self.weights = [auto_diff.Node(random.uniform(-1, 1)) for _ in range(weights_num)]
|
||||||
|
self.b = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
|
||||||
|
def __repr__(self, debug: bool = False) -> str:
|
||||||
|
if not debug:
|
||||||
|
return f"<weights = {len(self.weights)} b = {float(self.b)}>"
|
||||||
|
else:
|
||||||
|
return f"<weights = {self.weights} b = {float(self.b)}>"
|
||||||
|
|
||||||
|
def update_weights(self, lr):
|
||||||
|
for i in range(len(self.weights)):
|
||||||
|
self.weights[i] = auto_diff.update_weights(self.weights[i], lr)
|
||||||
|
|
||||||
|
self.b = auto_diff.update_weights(self.b, lr)
|
||||||
|
|
||||||
|
def my_sum(array: list) -> int:
|
||||||
|
result = 0
|
||||||
|
for i in array:
|
||||||
|
result += i
|
||||||
|
return result
|
||||||
|
|
||||||
|
class NeuronNetwork:
|
||||||
|
def __init__(self, neurons_num: int, layers_num: int, inputs_num: int, outputs_num: int = 1) -> None:
|
||||||
|
'''
|
||||||
|
neurons_num: количество нейронов на каждом слое\n
|
||||||
|
layers_num: количество слоёв\n
|
||||||
|
inputs_num: количество входных нейронов\n
|
||||||
|
outputs_num: количество выходных нейронов (по умолчанию 1)\n
|
||||||
|
'''
|
||||||
|
neurons = []
|
||||||
|
for layer in range(layers_num+1):
|
||||||
|
neurons.append([])
|
||||||
|
|
||||||
|
if layer == layers_num:
|
||||||
|
for neuron in range(outputs_num):
|
||||||
|
neurons[layer].append(Neuron(neurons_num))
|
||||||
|
continue
|
||||||
|
|
||||||
|
for neuron in range(neurons_num):
|
||||||
|
if layer == 0:
|
||||||
|
neurons[layer].append(Neuron(inputs_num))
|
||||||
|
else:
|
||||||
|
neurons[layer].append(Neuron(neurons_num))
|
||||||
|
|
||||||
|
self.neurons = neurons
|
||||||
|
|
||||||
|
def forward(self, func, *args, func_out=None):
|
||||||
|
if func_out is None:
|
||||||
|
func_out = func
|
||||||
|
|
||||||
|
|
||||||
|
prev_out = [*args]
|
||||||
|
out = []
|
||||||
|
for layer in self.neurons[:-1]:
|
||||||
|
for neuron in layer:
|
||||||
|
out.append(func(my_sum([prev_out[i]*neuron.weights[i] for i in range(len(prev_out))]) + neuron.b))
|
||||||
|
prev_out = copy.deepcopy(out)
|
||||||
|
out = []
|
||||||
|
|
||||||
|
for neuron in self.neurons[-1]:
|
||||||
|
out.append(func_out(my_sum([prev_out[i]*neuron.weights[i] for i in range(len(prev_out))]) + neuron.b))
|
||||||
|
|
||||||
|
return out[0]
|
||||||
|
|
||||||
|
def update_weights(self, lr=0.1):
|
||||||
|
for i in range(len(self.neurons)):
|
||||||
|
for j in range(len(self.neurons[i])):
|
||||||
|
self.neurons[i][j].update_weights(lr)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(NeuronNetwork(4, 4, 2).neurons)
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import classes
|
import classes
|
||||||
|
|
||||||
def generate_dataset(N=1000):
|
def generate_dataset(N=100):
|
||||||
return classes.DataSet(lambda x: 1*x-12, N)
|
return classes.DataSet(lambda x, y: float(((x**2 + y**2)**0.5)>=0.5), N)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print([[i.train, i.train_answs] for i in [generate_dataset(10)]])
|
print(generate_dataset(10))
|
||||||
10
main.py
10
main.py
@@ -9,12 +9,16 @@ dataset = generate.generate_dataset(100)
|
|||||||
|
|
||||||
# Создаём и обучаем сеть
|
# Создаём и обучаем сеть
|
||||||
nn = neuro_defs.SimpleNN()
|
nn = neuro_defs.SimpleNN()
|
||||||
nn.train(dataset.train, dataset.train_answs, epochs=100)
|
epoch = 100
|
||||||
|
for i in range(epoch):
|
||||||
|
nn.train(dataset.train, dataset.train_answs, epochs=1)
|
||||||
|
|
||||||
|
if epoch % 10 == 0:
|
||||||
|
print("*"*(i//10) + "-"*((epoch-i)//10))
|
||||||
|
|
||||||
# Проверяем на новой точке
|
# Проверяем на новой точке
|
||||||
for dot in range(len(dataset.test)):
|
for dot in range(len(dataset.test)):
|
||||||
print(nn.forward(dataset.test[dot]).val, dataset.test_answs[dot])
|
print(nn.forward(*dataset.test[dot]).val, dataset.test_answs[dot])
|
||||||
print()
|
print()
|
||||||
print(nn.w_out.val, nn.b_out.val)
|
|
||||||
# visual.plot_dataset(dataset)
|
# visual.plot_dataset(dataset)
|
||||||
# visual.plt_show()
|
# visual.plt_show()
|
||||||
@@ -1,32 +1,86 @@
|
|||||||
import math
|
|
||||||
import random
|
|
||||||
from auto_diff import auto_diff
|
|
||||||
|
|
||||||
def func_active(x):
|
from auto_diff import auto_diff
|
||||||
return
|
import classes
|
||||||
|
|
||||||
|
def sigmoid(x: auto_diff.Node):
|
||||||
|
return 1 / (1 + (-x).exp())
|
||||||
|
|
||||||
|
def tanh(x: auto_diff.Node):
|
||||||
|
return (x.exp() - (-x).exp()) / (x.exp() + (-x).exp())
|
||||||
|
|
||||||
class SimpleNN:
|
class SimpleNN:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.w_out = auto_diff.Node(random.uniform(-1, 1), label="w_out")
|
#111 - 1 слой, 1 нейрон, 1 вес
|
||||||
self.b_out = auto_diff.Node(random.uniform(-1, 1), label="b_out")
|
# self.w111 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
self.lr = 0.02 # скорость обучения
|
# self.w112 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.b11 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
|
||||||
def forward(self, x):
|
# self.w121 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.w122 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.b12 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
|
||||||
|
# self.w131 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.w132 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.b13 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
|
||||||
|
# self.w141 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.w142 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.b14 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# self.w211 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.w212 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.w213 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.w214 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.b21 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
|
||||||
|
# self.w221 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.w222 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.w223 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.w224 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.b22 = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# self.w1_out = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.w2_out = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
# self.b_out = auto_diff.Node(random.uniform(-1, 1))
|
||||||
|
|
||||||
|
self.network = classes.NeuronNetwork(4, 2, 2)
|
||||||
|
|
||||||
|
self.lr = 0.1 # скорость обучения
|
||||||
|
|
||||||
|
def forward(self, x1, x2):
|
||||||
# прямой проход
|
# прямой проход
|
||||||
self.z1 = self.w_out * x + self.b_out
|
|
||||||
return self.z1
|
|
||||||
|
|
||||||
def backward(self, x, y):
|
# #скрытые слои
|
||||||
|
# self.h11 = tanh(self.w111*x1 + self.w112*x2 + self.b11)
|
||||||
|
# self.h12 = tanh(self.w121*x1 + self.w122*x2 + self.b12)
|
||||||
|
# self.h13 = tanh(self.w131*x1 + self.w132*x2 + self.b13)
|
||||||
|
# self.h14 = tanh(self.w141*x1 + self.w142*x2 + self.b14)
|
||||||
|
|
||||||
|
# self.h21 = tanh(self.w211*self.h11 + self.w212*self.h12 + self.w213*self.h13 + self.w214*self.h14 + self.b21)
|
||||||
|
# self.h22 = tanh(self.w221*self.h11 + self.w222*self.h12 + self.w223*self.h13 + self.w224*self.h14 + self.b22)
|
||||||
|
|
||||||
|
# #выходной слой
|
||||||
|
# self.a1 = sigmoid(self.w1_out*self.h21 + self.w2_out*self.h22 + self.b_out)
|
||||||
|
|
||||||
|
self.a1 = self.network.forward(sigmoid, x1, x2)
|
||||||
|
|
||||||
|
return self.a1
|
||||||
|
|
||||||
|
def backward(self, y):
|
||||||
# вычисляем ошибку
|
# вычисляем ошибку
|
||||||
error = (self.z1 - y)**2 # dL/da2
|
error = (self.a1 - y)**2 # dL/da2
|
||||||
|
|
||||||
auto_diff.backward(error)
|
auto_diff.backward(error)
|
||||||
self.w_out = auto_diff.Node(float(self.w_out) - self.lr * self.w_out.grad, label="w_out")
|
|
||||||
self.b_out = auto_diff.Node(float(self.b_out) - self.lr * self.b_out.grad, label="b_out")
|
self.network.update_weights(self.lr)
|
||||||
|
|
||||||
def train(self, dataset, answs, epochs=1000):
|
def train(self, dataset, answs, epochs=1000):
|
||||||
for _ in range(epochs):
|
for _ in range(epochs):
|
||||||
for i in range(len(dataset)):
|
for i in range(len(dataset)):
|
||||||
self.forward(dataset[i])
|
self.forward(*dataset[i])
|
||||||
self.backward(dataset[i], answs[i])
|
self.backward(answs[i])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user