0. Problema
OR exclusivo (OR exclusivo, XOR, EOR, EX-OR). En 1969, Marvin Minsky publicó el libro "Perceptron", que señaló dos defectos clave de las redes neuronales: uno es que el perceptrón no puede manejar el problema del circuito "O exclusivo"; el otro es que la computadora en ese momento no puede soportar el procesamiento de redes neuronales a gran escala Calcular la capacidad. Estas afirmaciones han hecho que la gente cuestione la red neuronal representada por el perceptrón y condujo a la "edad de hielo" de más de diez años de investigación de redes neuronales. Se puede considerar que el perceptrón es una capa de red neuronal feedforward (sin capa de entrada). Intente utilizar una red neuronal de alimentación directa de dos capas (sin la capa de entrada) para resolver el problema XOR, que requiere una precisión del 100% en el conjunto de prueba. Específicamente, el conjunto de entrenamiento y el conjunto de prueba de la red neuronal son iguales, ambos son S = {(1, 0, 1), (1, 1, 0), (0, 0, 0), (0, 1, 1)}, la tercera dimensión de cada dato es etiqueta.
1. Análisis de problemas
El título señalaba que el perceptrón (una capa de red neuronal feedforward) no puede darse cuenta del problema XOR. Esto se debe principalmente a que una capa de red neuronal feedforward solo puede representar el espacio lineal, y el problema XOR es un problema en el espacio no lineal.
Según el conocimiento del circuito digital, la puerta OR exclusiva se puede configurar a través de la puerta Y, la puerta NAND o la puerta, como se muestra en la figura.
Según el conocimiento del perceptrón (una capa de red neuronal de alimentación directa), se puede saber que la puerta AND, la puerta NAND y la puerta OR se pueden realizar mediante una capa de red neuronal. Por lo tanto, se puede inferir que la puerta XOR se puede realizar mediante una red neuronal de alimentación directa de dos capas.
2. Pasos de implementación
Primero enumere la tabla de verdad de la puerta AND, la puerta NAND, la puerta OR, la puerta XOR, como se muestra en la figura.
Debido a la lógica simple de la tabla de verdad, no es necesario entrenar la red neuronal y establecer directamente los pesos y sesgos para construir una red neuronal de dos capas.
La red neuronal feedforward de dos capas construida de acuerdo con la tabla de verdad se muestra en la figura.
La función de activación de esta red neuronal es una función escalonada, y el peso y el sesgo de cada capa de la red neuronal se pueden ver en la siguiente fórmula.
En base a esto, primero puede usar Python para construir una función de paso, inicializar una red neuronal y construir una función de retroalimentación.
import numpy as np
def step_function(x):
y = x > 0
return y.astype(np.int)
def init_network():
network = {
}
network['W1'] = np.array([[-0.5, 0.5], [-0.5, 0.5]])
network['b1'] = np.array([0.7, -0.2])
network['W2'] = np.array([0.5, 0.5])
network['b2'] = np.array([-0.7])
return network
def forward(network, x):
W1, W2 = network['W1'], network['W2']
b1, b2 = network['b1'], network['b2']
NAND_OR = step_function(np.dot(x, W1) + b1)
XOR = step_function(np.dot(NAND_OR, W2) + b2)
return XOR
Finalmente, el conjunto de prueba S = ((1, 0, 1), (1, 1, 0), (0, 0, 0), (0, 1, 1)) se puede ingresar al feedforward de dos capas construido En la red neuronal, el resultado de salida se compara con la etiqueta en el conjunto de prueba y finalmente se obtiene la precisión.
network = init_network()
s_test = np.array([[1, 0, 1], [1, 1, 0], [0, 0, 0], [0, 1, 1]])
y = []
accuracy_cnt = 0
for i in range(0, 4):
y.append(forward(network, s_test[i, 0:2]))
if y[i] == s_test[i, 2]:
accuracy_cnt += 1
print('accuracy:', str(accuracy_cnt / len(s_test)))
3. Resultados y análisis experimentales
La salida después de ejecutar el código se muestra en la figura.
Como se muestra en la figura, la red neuronal feedforward de dos capas construida resuelve el problema XOR, y la precisión en el conjunto de prueba es del 100%.
4. Código fuente
XOR.py
# -*- coding: utf-8 -*-
"""
Created on Wed Dec 23 20:30:24 2020
@author: jiawei
"""
import numpy as np
def step_function(x):
y = x > 0
return y.astype(np.int)
def init_network():
network = {
}
network['W1'] = np.array([[-0.5, 0.5], [-0.5, 0.5]])
network['b1'] = np.array([0.7, -0.2])
network['W2'] = np.array([0.5, 0.5])
network['b2'] = np.array([-0.7])
return network
def forward(network, x):
W1, W2 = network['W1'], network['W2']
b1, b2 = network['b1'], network['b2']
NAND_OR = step_function(np.dot(x, W1) + b1)
XOR = step_function(np.dot(NAND_OR, W2) + b2)
return XOR
network = init_network()
s_test = np.array([[1, 0, 1], [1, 1, 0], [0, 0, 0], [0, 1, 1]])
y = []
accuracy_cnt = 0
for i in range(0, 4):
y.append(forward(network, s_test[i, 0:2]))
if y[i] == s_test[i, 2]:
accuracy_cnt += 1
print('accuracy:', str(accuracy_cnt / len(s_test)))