# your code goes here
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
# Данные для XNOR
X = np.array([[0, 0],
[0, 1],
[1, 0],
[1, 1]])
y = np.array([[1],
[0],
[0],
[1]])
# Создание и обучение сети
print("Создание нейронной сети для XNOR...")
nn = SimpleNeuralNetwork(input_size=2, hidden_size=4, output_size=1)
print("\nОбучение сети...")
nn.train(X, y, epochs=300, learning_rate=1.57)
# Проверка результатов
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}%")
IyB5b3VyIGNvZGUgZ29lcyBoZXJlCmltcG9ydCBudW1weSBhcyBucAoKZGVmIHNpZ21vaWQoeCk6CiAgICAiIiLQodC40LPQvNC+0LjQtNC90LDRjyDRhNGD0L3QutGG0LjRjyDQsNC60YLQuNCy0LDRhtC40LgiIiIKICAgIHJldHVybiAxIC8gKDEgKyBucC5leHAoLXgpKQoKZGVmIHNpZ21vaWRfZGVyaXZhdGl2ZSh4KToKICAgICIiItCf0YDQvtC40LfQstC+0LTQvdCw0Y8g0YHQuNCz0LzQvtC40LTQvdC+0Lkg0YTRg9C90LrRhtC40LgiIiIKICAgIHJldHVybiB4ICogKDEgLSB4KQoKY2xhc3MgU2ltcGxlTmV1cmFsTmV0d29yazoKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBpbnB1dF9zaXplPTIsIGhpZGRlbl9zaXplPTQsIG91dHB1dF9zaXplPTEpOgogICAgICAgICIiItCY0L3QuNGG0LjQsNC70LjQt9Cw0YbQuNGPINC90LXQudGA0L7QvdC90L7QuSDRgdC10YLQuCIiIgogICAgICAgICMg0JLQtdGB0LAg0LzQtdC20LTRgyDQstGF0L7QtNC90YvQvCDQuCDRgdC60YDRi9GC0YvQvCDRgdC70L7Rj9C80LgKICAgICAgICBzZWxmLndlaWdodHMxID0gbnAucmFuZG9tLnVuaWZvcm0oLTEsIDEsIChpbnB1dF9zaXplLCBoaWRkZW5fc2l6ZSkpCiAgICAgICAgIyDQktC10YHQsCDQvNC10LbQtNGDINGB0LrRgNGL0YLRi9C8INC4INCy0YvRhdC+0LTQvdGL0Lwg0YHQu9C+0Y/QvNC4CiAgICAgICAgc2VsZi53ZWlnaHRzMiA9IG5wLnJhbmRvbS51bmlmb3JtKC0xLCAxLCAoaGlkZGVuX3NpemUsIG91dHB1dF9zaXplKSkKICAgICAgICAjINCh0LzQtdGJ0LXQvdC40Y8gKGJpYXMpCiAgICAgICAgc2VsZi5iaWFzMSA9IG5wLnplcm9zKCgxLCBoaWRkZW5fc2l6ZSkpCiAgICAgICAgc2VsZi5iaWFzMiA9IG5wLnplcm9zKCgxLCBvdXRwdXRfc2l6ZSkpCiAgICAgICAKICAgIGRlZiBmb3J3YXJkKHNlbGYsIFgpOgogICAgICAgICIiItCf0YDRj9C80L7QtSDRgNCw0YHQv9GA0L7RgdGC0YDQsNC90LXQvdC40LUiIiIKICAgICAgICAjINCS0YXQvtC00L3QvtC5IC0+INGB0LrRgNGL0YLRi9C5INGB0LvQvtC5CiAgICAgICAgc2VsZi5oaWRkZW5faW5wdXQgPSBucC5kb3QoWCwgc2VsZi53ZWlnaHRzMSkgKyBzZWxmLmJpYXMxCiAgICAgICAgc2VsZi5oaWRkZW5fb3V0cHV0ID0gc2lnbW9pZChzZWxmLmhpZGRlbl9pbnB1dCkKICAgICAgIAogICAgICAgICMg0KHQutGA0YvRgtGL0LkgLT4g0LLRi9GF0L7QtNC90L7QuSDRgdC70L7QuQogICAgICAgIHNlbGYuZmluYWxfaW5wdXQgPSBucC5kb3Qoc2VsZi5oaWRkZW5fb3V0cHV0LCBzZWxmLndlaWdodHMyKSArIHNlbGYuYmlhczIKICAgICAgICBzZWxmLmZpbmFsX291dHB1dCA9IHNpZ21vaWQoc2VsZi5maW5hbF9pbnB1dCkKICAgICAgIAogICAgICAgIHJldHVybiBzZWxmLmZpbmFsX291dHB1dAogICAKICAgIGRlZiBiYWNrd2FyZChzZWxmLCBYLCB5LCBvdXRwdXQsIGxlYXJuaW5nX3JhdGU9MC4xKToKICAgICAgICAiIiLQntCx0YDQsNGC0L3QvtC1INGA0LDRgdC/0YDQvtGB0YLRgNCw0L3QtdC90LjQtSDQvtGI0LjQsdC60LgiIiIKICAgICAgICAjINCe0YjQuNCx0LrQsCDQvdCwINCy0YvRhdC+0LTQvdC+0Lwg0YHQu9C+0LUKICAgICAgICBvdXRwdXRfZXJyb3IgPSB5IC0gb3V0cHV0CiAgICAgICAgb3V0cHV0X2RlbHRhID0gb3V0cHV0X2Vycm9yICogc2lnbW9pZF9kZXJpdmF0aXZlKG91dHB1dCkKICAgICAgIAogICAgICAgICMg0J7RiNC40LHQutCwINC90LAg0YHQutGA0YvRgtC+0Lwg0YHQu9C+0LUKICAgICAgICBoaWRkZW5fZXJyb3IgPSBucC5kb3Qob3V0cHV0X2RlbHRhLCBzZWxmLndlaWdodHMyLlQpCiAgICAgICAgaGlkZGVuX2RlbHRhID0gaGlkZGVuX2Vycm9yICogc2lnbW9pZF9kZXJpdmF0aXZlKHNlbGYuaGlkZGVuX291dHB1dCkKICAgICAgIAogICAgICAgICMg0J7QsdC90L7QstC70LXQvdC40LUg0LLQtdGB0L7QsiDQuCDRgdC80LXRidC10L3QuNC5CiAgICAgICAgc2VsZi53ZWlnaHRzMiArPSBsZWFybmluZ19yYXRlICogbnAuZG90KHNlbGYuaGlkZGVuX291dHB1dC5ULCBvdXRwdXRfZGVsdGEpCiAgICAgICAgc2VsZi5iaWFzMiArPSBsZWFybmluZ19yYXRlICogbnAuc3VtKG91dHB1dF9kZWx0YSwgYXhpcz0wLCBrZWVwZGltcz1UcnVlKQogICAgICAgCiAgICAgICAgc2VsZi53ZWlnaHRzMSArPSBsZWFybmluZ19yYXRlICogbnAuZG90KFguVCwgaGlkZGVuX2RlbHRhKQogICAgICAgIHNlbGYuYmlhczEgKz0gbGVhcm5pbmdfcmF0ZSAqIG5wLnN1bShoaWRkZW5fZGVsdGEsIGF4aXM9MCwga2VlcGRpbXM9VHJ1ZSkKICAgCiAgICBkZWYgdHJhaW4oc2VsZiwgWCwgeSwgZXBvY2hzPTEwMDAwLCBsZWFybmluZ19yYXRlPTAuMSwgdmVyYm9zZT1UcnVlKToKICAgICAgICAiIiLQntCx0YPRh9C10L3QuNC1INC90LXQudGA0L7QvdC90L7QuSDRgdC10YLQuCIiIgogICAgICAgIGZvciBlcG9jaCBpbiByYW5nZShlcG9jaHMpOgogICAgICAgICAgICAjINCf0YDRj9C80L7QtSDRgNCw0YHQv9GA0L7RgdGC0YDQsNC90LXQvdC40LUKICAgICAgICAgICAgb3V0cHV0ID0gc2VsZi5mb3J3YXJkKFgpCiAgICAgICAgICAgCiAgICAgICAgICAgICMg0J7QsdGA0LDRgtC90L7QtSDRgNCw0YHQv9GA0L7RgdGC0YDQsNC90LXQvdC40LUKICAgICAgICAgICAgc2VsZi5iYWNrd2FyZChYLCB5LCBvdXRwdXQsIGxlYXJuaW5nX3JhdGUpCiAgICAgICAgICAgCiAgICAgICAgICAgICMg0JLRi9Cy0L7QtCDQv9GA0L7Qs9GA0LXRgdGB0LAKICAgICAgICAgICAgaWYgdmVyYm9zZSBhbmQgZXBvY2ggJSAxMDAwID09IDA6CiAgICAgICAgICAgICAgICBsb3NzID0gbnAubWVhbihucC5zcXVhcmUoeSAtIG91dHB1dCkpCiAgICAgICAgICAgICAgICBwcmludChmItCt0L/QvtGF0LAge2Vwb2NofSwgTG9zczoge2xvc3M6LjZmfSIpCiAgIAogICAgZGVmIHByZWRpY3Qoc2VsZiwgWCk6CiAgICAgICAgIiIi0J/RgNC10LTRgdC60LDQt9Cw0L3QuNC1INC00LvRjyDQvdC+0LLRi9GFINC00LDQvdC90YvRhSIiIgogICAgICAgIG91dHB1dCA9IHNlbGYuZm9yd2FyZChYKQogICAgICAgIHJldHVybiAob3V0cHV0ID4gMC41KS5hc3R5cGUoaW50KSwgb3V0cHV0CgojINCU0LDQvdC90YvQtSDQtNC70Y8gWE5PUgpYID0gbnAuYXJyYXkoW1swLCAwXSwKICAgICAgICAgICAgICBbMCwgMV0sCiAgICAgICAgICAgICAgWzEsIDBdLAogICAgICAgICAgICAgIFsxLCAxXV0pCgp5ID0gbnAuYXJyYXkoW1sxXSwKICAgICAgICAgICAgICBbMF0sCiAgICAgICAgICAgICAgWzBdLAogICAgICAgICAgICAgIFsxXV0pCgojINCh0L7Qt9C00LDQvdC40LUg0Lgg0L7QsdGD0YfQtdC90LjQtSDRgdC10YLQuApwcmludCgi0KHQvtC30LTQsNC90LjQtSDQvdC10LnRgNC+0L3QvdC+0Lkg0YHQtdGC0Lgg0LTQu9GPIFhOT1IuLi4iKQpubiA9IFNpbXBsZU5ldXJhbE5ldHdvcmsoaW5wdXRfc2l6ZT0yLCBoaWRkZW5fc2l6ZT00LCBvdXRwdXRfc2l6ZT0xKQoKcHJpbnQoIlxu0J7QsdGD0YfQtdC90LjQtSDRgdC10YLQuC4uLiIpCm5uLnRyYWluKFgsIHksIGVwb2Nocz0zMDAsIGxlYXJuaW5nX3JhdGU9MS41NykKCiMg0J/RgNC+0LLQtdGA0LrQsCDRgNC10LfRg9C70YzRgtCw0YLQvtCyCnByaW50KCJcbtCg0LXQt9GD0LvRjNGC0LDRgtGLOiIpCnByZWRpY3Rpb25zLCBwcm9iYWJpbGl0aWVzID0gbm4ucHJlZGljdChYKQpmb3IgaSwgKHgsIHByZWQsIHByb2IpIGluIGVudW1lcmF0ZSh6aXAoWCwgcHJlZGljdGlvbnMsIHByb2JhYmlsaXRpZXMpKToKICAgIHByaW50KGYi0JLRhdC+0LQ6IHt4fSAtPiDQn9GA0LXQtNGB0LrQsNC30LDQvdC40LU6IHtwcmVkWzBdfSAo0LLQtdGA0L7Rj9GC0L3QvtGB0YLRjDoge3Byb2JbMF06LjRmfSkiKQoKIyDQlNC+0L/QvtC70L3QuNGC0LXQu9GM0L3QsNGPINC/0YDQvtCy0LXRgNC60LAg0YLQvtGH0L3QvtGB0YLQuAphY2N1cmFjeSA9IG5wLm1lYW4ocHJlZGljdGlvbnMgPT0geSkgKiAxMDAKcHJpbnQoZiJcbtCi0L7Rh9C90L7RgdGC0Yw6IHthY2N1cmFjeTouMmZ9JSIp