fork download
  1. # your code goes here
  2. import numpy as np
  3.  
  4. class XNORNeuralNetwork:
  5. def __init__(self, hidden_size=4, lr=0.5):
  6. np.random.seed(42)
  7. self.W1 = np.random.randn(2, hidden_size) * 0.5
  8. self.b1 = np.zeros((1, hidden_size))
  9. self.W2 = np.random.randn(hidden_size, 1) * 0.5
  10. self.b2 = np.zeros((1, 1))
  11. self.lr = lr
  12.  
  13. def sigmoid(self, x):
  14. x = np.clip(x, -500, 500)
  15. return 1 / (1 + np.exp(-x))
  16.  
  17. def sigmoid_derivative(self, x):
  18. return x * (1 - x)
  19.  
  20. def forward(self, X):
  21. self.z1 = np.dot(X, self.W1) + self.b1
  22. self.a1 = self.sigmoid(self.z1)
  23. self.z2 = np.dot(self.a1, self.W2) + self.b2
  24. self.a2 = self.sigmoid(self.z2)
  25. return self.a2
  26.  
  27. def backward(self, X, y, output):
  28. m = X.shape[0]
  29. delta2 = (output - y) * self.sigmoid_derivative(output)
  30. dW2 = np.dot(self.a1.T, delta2) / m
  31. db2 = np.sum(delta2, axis=0, keepdims=True) / m
  32.  
  33. delta1 = np.dot(delta2, self.W2.T) * self.sigmoid_derivative(self.a1)
  34. dW1 = np.dot(X.T, delta1) / m
  35. db1 = np.sum(delta1, axis=0, keepdims=True) / m
  36.  
  37. self.W2 -= self.lr * dW2
  38. self.b2 -= self.lr * db2
  39. self.W1 -= self.lr * dW1
  40. self.b1 -= self.lr * db1
  41.  
  42. def train(self, X, y, epochs=10000, verbose=False):
  43. losses = []
  44. for epoch in range(epochs):
  45. output = self.forward(X)
  46.  
  47. # Стандартная ошибка
  48. standard_loss = np.mean((output - y) ** 2)
  49.  
  50. # Дополнительная ошибка инверсии:
  51. # f(NOT x) + f(x) должно быть ≈ 1
  52. X_inverted = 1 - X # Инвертируем входные значения
  53. output_inverted = self.forward(X_inverted)
  54.  
  55. # y_inverted = 1 - y (инвертированная целевая переменная)
  56. y_inverted = 1 - y
  57.  
  58. # Комбинированная функция потерь
  59. consistency_loss = np.mean((output + output_inverted - 1) ** 2)
  60. inverted_loss = np.mean((output_inverted - y_inverted) ** 2)
  61.  
  62. # Общая ошибка
  63. total_loss = standard_loss + 0.3 * consistency_loss + 0.5 * inverted_loss
  64.  
  65. losses.append(total_loss)
  66.  
  67. # Обратное распространение с учётом всех компонент
  68. self.backward(X, y, output)
  69.  
  70. if verbose and epoch % 2000 == 0:
  71. print(f"Epoch {epoch}, Loss: {total_loss:.6f}, "
  72. f"Std: {standard_loss:.6f}, "
  73. f"Inv: {inverted_loss:.6f}, "
  74. f"Cons: {consistency_loss:.6f}")
  75. return losses
  76.  
  77.  
  78. # ===== ДАННЫЕ =====
  79. X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=np.float64)
  80. y = np.array([[1], [0], [0], [1]], dtype=np.float64)
  81.  
  82. # Инвертированные данные
  83. X_inv = 1 - X
  84. y_inv = 1 - y
  85.  
  86. print("=" * 70)
  87. print("XNOR С ИСПОЛЬЗОВАНИЕМ СВОЙСТВА ИНВЕРСИИ")
  88. print("f(x) + f(NOT x) ≈ 1")
  89. print("=" * 70)
  90.  
  91. # Обучение
  92. model = XNORNeuralNetwork(hidden_size=4, lr=0.5)
  93. losses = model.train(X, y, epochs=12000, verbose=True)
  94.  
  95. # ===== ТЕСТИРОВАНИЕ =====
  96. print("\n" + "=" * 70)
  97. print("РЕЗУЛЬТАТЫ")
  98. print("=" * 70)
  99.  
  100. print(f"\n{'Вход':<12} {'f(x)':<15} {'Предск.':<10} "
  101. f"{'f(~x)':<15} {'Сумма':<15} {'Статус'}")
  102. print("-" * 75)
  103.  
  104. correct_direct = 0
  105. correct_ensemble = 0
  106.  
  107. for i in range(len(X)):
  108. # Прямой проход
  109. f_x = model.forward(X[i:i+1])[0][0]
  110. pred_direct = 1 if f_x > 0.5 else 0
  111.  
  112. # Инвертированный проход
  113. X_inv_i = 1 - X[i]
  114. f_not_x = model.forward(X_inv_i.reshape(1, -1))[0][0]
  115.  
  116. # Проверка свойства
  117. sum_outputs = f_x + f_not_x
  118.  
  119. # Ансамблевое предсказание с учётом инверсии
  120. # f(x) = 1 - f(NOT x), поэтому:
  121. # ensemble_prediction = (f(x) + (1 - f(NOT x))) / 2
  122. ensemble_score = (f_x + (1 - f_not_x)) / 2
  123. pred_ensemble = 1 if ensemble_score > 0.5 else 0
  124.  
  125. # Проверка корректности
  126. if pred_direct == y[i][0]:
  127. correct_direct += 1
  128.  
  129. if pred_ensemble == y[i][0]:
  130. correct_ensemble += 1
  131.  
  132. # Статус суммы (должна быть ≈ 1)
  133. if abs(sum_outputs - 1.0) < 0.1:
  134. consistency = "✓"
  135. elif abs(sum_outputs - 1.0) < 0.2:
  136. consistency = "~"
  137. else:
  138. consistency = "✗"
  139.  
  140. print(f"{str(X[i]):<12} {f_x:<15.6f} {pred_direct:<10} "
  141. f"{f_not_x:<15.6f} {sum_outputs:<15.6f} {consistency}")
  142.  
  143. print(f"\nТочность прямых предсказаний: {correct_direct}/4")
  144. print(f"Точность ансамблевых предсказаний: {correct_ensemble}/4")
  145.  
  146. # ===== ДЕМОНСТРАЦИЯ СВОЙСТВА =====
  147. print("\n" + "=" * 70)
  148. print("ДЕМОНСТРАЦИЯ СВОЙСТВА ИНВЕРСИИ")
  149. print("=" * 70)
  150.  
  151. print("\nf(0,0) + f(1,1) = ", end="")
  152. f00 = model.forward(np.array([[0, 0]]))[0][0]
  153. f11 = model.forward(np.array([[1, 1]]))[0][0]
  154. print(f"{f00:.4f} + {f11:.4f} = {f00 + f11:.4f} ≈ 1")
  155.  
  156. print("f(0,1) + f(1,0) = ", end="")
  157. f01 = model.forward(np.array([[0, 1]]))[0][0]
  158. f10 = model.forward(np.array([[1, 0]]))[0][0]
  159. print(f"{f01:.4f} + {f10:.4f} = {f01 + f10:.4f} ≈ 1")
Success #stdin #stdout 4.52s 42232KB
stdin
Standard input is empty
stdout
======================================================================
XNOR С ИСПОЛЬЗОВАНИЕМ СВОЙСТВА ИНВЕРСИИ
f(x) + f(NOT x) ≈ 1
======================================================================
Epoch 0, Loss: 0.388517, Std: 0.254656, Inv: 0.255675, Cons: 0.020077
Epoch 2000, Loss: 0.375214, Std: 0.250223, Inv: 0.249982, Cons: 0.000000
Epoch 4000, Loss: 0.374912, Std: 0.249819, Inv: 0.250186, Cons: 0.000000
Epoch 6000, Loss: 0.374918, Std: 0.249815, Inv: 0.250207, Cons: 0.000000
Epoch 8000, Loss: 0.375018, Std: 0.250005, Inv: 0.250026, Cons: 0.000000
Epoch 10000, Loss: 0.375053, Std: 0.250073, Inv: 0.249961, Cons: 0.000000

======================================================================
РЕЗУЛЬТАТЫ
======================================================================

Вход         f(x)            Предск.    f(~x)           Сумма           Статус
---------------------------------------------------------------------------
[0. 0.]      0.494075        0          0.505471        0.999547        ✓
[0. 1.]      0.500690        1          0.500119        1.000808        ✓
[1. 0.]      0.500119        1          0.500690        1.000808        ✓
[1. 1.]      0.505471        1          0.494075        0.999547        ✓

Точность прямых предсказаний: 1/4
Точность ансамблевых предсказаний: 2/4

======================================================================
ДЕМОНСТРАЦИЯ СВОЙСТВА ИНВЕРСИИ
======================================================================

f(0,0) + f(1,1) = 0.4941 + 0.5055 = 0.9995 ≈ 1
f(0,1) + f(1,0) = 0.5007 + 0.5001 = 1.0008 ≈ 1