import numpy as np
def sigmoid(x):
"""Сигмоидная функция активации"""
return 1 / (1 + np.exp(-x))
def sigmoid_derivative(x):
"""Производная сигмоидной функции"""
return x * (1 - x)
class SimpleNeuralNetwork:
def __init__(self, input_size=2, hidden_size=4, output_size=1):
"""Инициализация нейронной сети"""
# Веса между входным и скрытым слоями
self.weights1 = np.random.uniform(-1, 1, (input_size, hidden_size))
# Веса между скрытым и выходным слоями
self.weights2 = np.random.uniform(-1, 1, (hidden_size, output_size))
# Смещения (bias)
self.bias1 = np.zeros((1, hidden_size))
self.bias2 = np.zeros((1, output_size))
def forward(self, X):
"""Прямое распространение"""
# Входной -> скрытый слой
self.hidden_input = np.dot(X, self.weights1) + self.bias1
self.hidden_output = sigmoid(self.hidden_input)
# Скрытый -> выходной слой
self.final_input = np.dot(self.hidden_output, self.weights2) + self.bias2
self.final_output = sigmoid(self.final_input)
return self.final_output
def backward(self, X, y, output, learning_rate=0.1):
"""Обратное распространение ошибки"""
# Ошибка на выходном слое
output_error = y - output
output_delta = output_error * sigmoid_derivative(output)
# Ошибка на скрытом слое
hidden_error = np.dot(output_delta, self.weights2.T)
hidden_delta = hidden_error * sigmoid_derivative(self.hidden_output)
# Обновление весов и смещений
self.weights2 += learning_rate * np.dot(self.hidden_output.T, output_delta)
self.bias2 += learning_rate * np.sum(output_delta, axis=0, keepdims=True)
self.weights1 += learning_rate * np.dot(X.T, hidden_delta)
self.bias1 += learning_rate * np.sum(hidden_delta, axis=0, keepdims=True)
def train(self, X, y, epochs=10000, learning_rate=0.1, verbose=True):
"""Обучение нейронной сети"""
for epoch in range(epochs):
# Прямое распространение
output = self.forward(X)
# Обратное распространение
self.backward(X, y, output, learning_rate)
# Вывод прогресса
if verbose and epoch % 1000 == 0:
loss = np.mean(np.square(y - output))
print(f"Эпоха {epoch}, Loss: {loss:.6f}")
def predict(self, X):
"""Предсказание для новых данных"""
output = self.forward(X)
return (output > 0.5).astype(int), output
# Данные для XOR
X = np.array([[0, 0],
[0, 1],
[1, 0],
[1, 1]])
y = np.array([[0],
[1],
[1],
[0]])
# Создание и обучение сети
print("Создание нейронной сети для XOR...")
nn = SimpleNeuralNetwork(input_size=2, hidden_size=4, output_size=1)
print("\nОбучение сети...")
nn.train(X, y, epochs=10000, learning_rate=0.5)
# Проверка результатов
print("\nРезультаты:")
predictions, probabilities = nn.predict(X)
for i, (x, pred, prob) in enumerate(zip(X, predictions, probabilities)):
print(f"Вход: {x} -> Предсказание: {pred[0]} (вероятность: {prob[0]:.4f})")
# Дополнительная проверка точности
accuracy = np.mean(predictions == y) * 100
print(f"\nТочность: {accuracy:.2f}%")
aW1wb3J0IG51bXB5IGFzIG5wCgpkZWYgc2lnbW9pZCh4KToKICAgICIiItCh0LjQs9C80L7QuNC00L3QsNGPINGE0YPQvdC60YbQuNGPINCw0LrRgtC40LLQsNGG0LjQuCIiIgogICAgcmV0dXJuIDEgLyAoMSArIG5wLmV4cCgteCkpCgpkZWYgc2lnbW9pZF9kZXJpdmF0aXZlKHgpOgogICAgIiIi0J/RgNC+0LjQt9Cy0L7QtNC90LDRjyDRgdC40LPQvNC+0LjQtNC90L7QuSDRhNGD0L3QutGG0LjQuCIiIgogICAgcmV0dXJuIHggKiAoMSAtIHgpCgpjbGFzcyBTaW1wbGVOZXVyYWxOZXR3b3JrOgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGlucHV0X3NpemU9MiwgaGlkZGVuX3NpemU9NCwgb3V0cHV0X3NpemU9MSk6CiAgICAgICAgIiIi0JjQvdC40YbQuNCw0LvQuNC30LDRhtC40Y8g0L3QtdC50YDQvtC90L3QvtC5INGB0LXRgtC4IiIiCiAgICAgICAgIyDQktC10YHQsCDQvNC10LbQtNGDINCy0YXQvtC00L3Ri9C8INC4INGB0LrRgNGL0YLRi9C8INGB0LvQvtGP0LzQuAogICAgICAgIHNlbGYud2VpZ2h0czEgPSBucC5yYW5kb20udW5pZm9ybSgtMSwgMSwgKGlucHV0X3NpemUsIGhpZGRlbl9zaXplKSkKICAgICAgICAjINCS0LXRgdCwINC80LXQttC00YMg0YHQutGA0YvRgtGL0Lwg0Lgg0LLRi9GF0L7QtNC90YvQvCDRgdC70L7Rj9C80LgKICAgICAgICBzZWxmLndlaWdodHMyID0gbnAucmFuZG9tLnVuaWZvcm0oLTEsIDEsIChoaWRkZW5fc2l6ZSwgb3V0cHV0X3NpemUpKQogICAgICAgICMg0KHQvNC10YnQtdC90LjRjyAoYmlhcykKICAgICAgICBzZWxmLmJpYXMxID0gbnAuemVyb3MoKDEsIGhpZGRlbl9zaXplKSkKICAgICAgICBzZWxmLmJpYXMyID0gbnAuemVyb3MoKDEsIG91dHB1dF9zaXplKSkKICAgICAgICAKICAgIGRlZiBmb3J3YXJkKHNlbGYsIFgpOgogICAgICAgICIiItCf0YDRj9C80L7QtSDRgNCw0YHQv9GA0L7RgdGC0YDQsNC90LXQvdC40LUiIiIKICAgICAgICAjINCS0YXQvtC00L3QvtC5IC0+INGB0LrRgNGL0YLRi9C5INGB0LvQvtC5CiAgICAgICAgc2VsZi5oaWRkZW5faW5wdXQgPSBucC5kb3QoWCwgc2VsZi53ZWlnaHRzMSkgKyBzZWxmLmJpYXMxCiAgICAgICAgc2VsZi5oaWRkZW5fb3V0cHV0ID0gc2lnbW9pZChzZWxmLmhpZGRlbl9pbnB1dCkKICAgICAgICAKICAgICAgICAjINCh0LrRgNGL0YLRi9C5IC0+INCy0YvRhdC+0LTQvdC+0Lkg0YHQu9C+0LkKICAgICAgICBzZWxmLmZpbmFsX2lucHV0ID0gbnAuZG90KHNlbGYuaGlkZGVuX291dHB1dCwgc2VsZi53ZWlnaHRzMikgKyBzZWxmLmJpYXMyCiAgICAgICAgc2VsZi5maW5hbF9vdXRwdXQgPSBzaWdtb2lkKHNlbGYuZmluYWxfaW5wdXQpCiAgICAgICAgCiAgICAgICAgcmV0dXJuIHNlbGYuZmluYWxfb3V0cHV0CiAgICAKICAgIGRlZiBiYWNrd2FyZChzZWxmLCBYLCB5LCBvdXRwdXQsIGxlYXJuaW5nX3JhdGU9MC4xKToKICAgICAgICAiIiLQntCx0YDQsNGC0L3QvtC1INGA0LDRgdC/0YDQvtGB0YLRgNCw0L3QtdC90LjQtSDQvtGI0LjQsdC60LgiIiIKICAgICAgICAjINCe0YjQuNCx0LrQsCDQvdCwINCy0YvRhdC+0LTQvdC+0Lwg0YHQu9C+0LUKICAgICAgICBvdXRwdXRfZXJyb3IgPSB5IC0gb3V0cHV0CiAgICAgICAgb3V0cHV0X2RlbHRhID0gb3V0cHV0X2Vycm9yICogc2lnbW9pZF9kZXJpdmF0aXZlKG91dHB1dCkKICAgICAgICAKICAgICAgICAjINCe0YjQuNCx0LrQsCDQvdCwINGB0LrRgNGL0YLQvtC8INGB0LvQvtC1CiAgICAgICAgaGlkZGVuX2Vycm9yID0gbnAuZG90KG91dHB1dF9kZWx0YSwgc2VsZi53ZWlnaHRzMi5UKQogICAgICAgIGhpZGRlbl9kZWx0YSA9IGhpZGRlbl9lcnJvciAqIHNpZ21vaWRfZGVyaXZhdGl2ZShzZWxmLmhpZGRlbl9vdXRwdXQpCiAgICAgICAgCiAgICAgICAgIyDQntCx0L3QvtCy0LvQtdC90LjQtSDQstC10YHQvtCyINC4INGB0LzQtdGJ0LXQvdC40LkKICAgICAgICBzZWxmLndlaWdodHMyICs9IGxlYXJuaW5nX3JhdGUgKiBucC5kb3Qoc2VsZi5oaWRkZW5fb3V0cHV0LlQsIG91dHB1dF9kZWx0YSkKICAgICAgICBzZWxmLmJpYXMyICs9IGxlYXJuaW5nX3JhdGUgKiBucC5zdW0ob3V0cHV0X2RlbHRhLCBheGlzPTAsIGtlZXBkaW1zPVRydWUpCiAgICAgICAgCiAgICAgICAgc2VsZi53ZWlnaHRzMSArPSBsZWFybmluZ19yYXRlICogbnAuZG90KFguVCwgaGlkZGVuX2RlbHRhKQogICAgICAgIHNlbGYuYmlhczEgKz0gbGVhcm5pbmdfcmF0ZSAqIG5wLnN1bShoaWRkZW5fZGVsdGEsIGF4aXM9MCwga2VlcGRpbXM9VHJ1ZSkKICAgIAogICAgZGVmIHRyYWluKHNlbGYsIFgsIHksIGVwb2Nocz0xMDAwMCwgbGVhcm5pbmdfcmF0ZT0wLjEsIHZlcmJvc2U9VHJ1ZSk6CiAgICAgICAgIiIi0J7QsdGD0YfQtdC90LjQtSDQvdC10LnRgNC+0L3QvdC+0Lkg0YHQtdGC0LgiIiIKICAgICAgICBmb3IgZXBvY2ggaW4gcmFuZ2UoZXBvY2hzKToKICAgICAgICAgICAgIyDQn9GA0Y/QvNC+0LUg0YDQsNGB0L/RgNC+0YHRgtGA0LDQvdC10L3QuNC1CiAgICAgICAgICAgIG91dHB1dCA9IHNlbGYuZm9yd2FyZChYKQogICAgICAgICAgICAKICAgICAgICAgICAgIyDQntCx0YDQsNGC0L3QvtC1INGA0LDRgdC/0YDQvtGB0YLRgNCw0L3QtdC90LjQtQogICAgICAgICAgICBzZWxmLmJhY2t3YXJkKFgsIHksIG91dHB1dCwgbGVhcm5pbmdfcmF0ZSkKICAgICAgICAgICAgCiAgICAgICAgICAgICMg0JLRi9Cy0L7QtCDQv9GA0L7Qs9GA0LXRgdGB0LAKICAgICAgICAgICAgaWYgdmVyYm9zZSBhbmQgZXBvY2ggJSAxMDAwID09IDA6CiAgICAgICAgICAgICAgICBsb3NzID0gbnAubWVhbihucC5zcXVhcmUoeSAtIG91dHB1dCkpCiAgICAgICAgICAgICAgICBwcmludChmItCt0L/QvtGF0LAge2Vwb2NofSwgTG9zczoge2xvc3M6LjZmfSIpCiAgICAKICAgIGRlZiBwcmVkaWN0KHNlbGYsIFgpOgogICAgICAgICIiItCf0YDQtdC00YHQutCw0LfQsNC90LjQtSDQtNC70Y8g0L3QvtCy0YvRhSDQtNCw0L3QvdGL0YUiIiIKICAgICAgICBvdXRwdXQgPSBzZWxmLmZvcndhcmQoWCkKICAgICAgICByZXR1cm4gKG91dHB1dCA+IDAuNSkuYXN0eXBlKGludCksIG91dHB1dAoKIyDQlNCw0L3QvdGL0LUg0LTQu9GPIFhPUgpYID0gbnAuYXJyYXkoW1swLCAwXSwKICAgICAgICAgICAgICBbMCwgMV0sCiAgICAgICAgICAgICAgWzEsIDBdLAogICAgICAgICAgICAgIFsxLCAxXV0pCgp5ID0gbnAuYXJyYXkoW1swXSwKICAgICAgICAgICAgICBbMV0sCiAgICAgICAgICAgICAgWzFdLAogICAgICAgICAgICAgIFswXV0pCgojINCh0L7Qt9C00LDQvdC40LUg0Lgg0L7QsdGD0YfQtdC90LjQtSDRgdC10YLQuApwcmludCgi0KHQvtC30LTQsNC90LjQtSDQvdC10LnRgNC+0L3QvdC+0Lkg0YHQtdGC0Lgg0LTQu9GPIFhPUi4uLiIpCm5uID0gU2ltcGxlTmV1cmFsTmV0d29yayhpbnB1dF9zaXplPTIsIGhpZGRlbl9zaXplPTQsIG91dHB1dF9zaXplPTEpCgpwcmludCgiXG7QntCx0YPRh9C10L3QuNC1INGB0LXRgtC4Li4uIikKbm4udHJhaW4oWCwgeSwgZXBvY2hzPTEwMDAwLCBsZWFybmluZ19yYXRlPTAuNSkKCiMg0J/RgNC+0LLQtdGA0LrQsCDRgNC10LfRg9C70YzRgtCw0YLQvtCyCnByaW50KCJcbtCg0LXQt9GD0LvRjNGC0LDRgtGLOiIpCnByZWRpY3Rpb25zLCBwcm9iYWJpbGl0aWVzID0gbm4ucHJlZGljdChYKQpmb3IgaSwgKHgsIHByZWQsIHByb2IpIGluIGVudW1lcmF0ZSh6aXAoWCwgcHJlZGljdGlvbnMsIHByb2JhYmlsaXRpZXMpKToKICAgIHByaW50KGYi0JLRhdC+0LQ6IHt4fSAtPiDQn9GA0LXQtNGB0LrQsNC30LDQvdC40LU6IHtwcmVkWzBdfSAo0LLQtdGA0L7Rj9GC0L3QvtGB0YLRjDoge3Byb2JbMF06LjRmfSkiKQoKIyDQlNC+0L/QvtC70L3QuNGC0LXQu9GM0L3QsNGPINC/0YDQvtCy0LXRgNC60LAg0YLQvtGH0L3QvtGB0YLQuAphY2N1cmFjeSA9IG5wLm1lYW4ocHJlZGljdGlvbnMgPT0geSkgKiAxMDAKcHJpbnQoZiJcbtCi0L7Rh9C90L7RgdGC0Yw6IHthY2N1cmFjeTouMmZ9JSIp