我刚刚开始学习神经网络,我决定研究一个简单的 3 输入感知器来开始学习。我也只使用二进制输入来全面了解感知器的工作原理。我很难理解为什么某些培训输出有效而其他培训输出无效。我猜这与输入数据的线性可分性有关,但我不清楚如何轻松确定这一点。我知道绘图线测试,但我不清楚如何绘制输入数据以完全了解什么可行,什么不可行。
后面有很多信息。但这一切都非常简单。我将所有这些信息包括在内,以便清楚地了解我在做什么以及试图理解和学习。
这是我正在建模的简单 3 输入感知器的示意图。
因为它只有 3 个输入并且它们是二进制(0 或 1),所以只有 8 种可能的输入组合。但是,这也允许 8 个可能的输出。这允许训练 256 个可能的输出。换句话说,感知器可以被训练来识别一种以上的输入配置。
让我们称输入 0 到 7(3 输入二进制系统的所有可能配置)。但是我们可以训练感知器识别不止一个输入。换句话说,我们可以训练感知器触发从 0 到 3 的任何输入,而不是针对输入 4 到 7。所有这些可能的组合加起来有 256 种可能的训练输入状态。
其中一些训练输入状态有效,而另一些则无效。我正在尝试学习如何确定哪些训练集有效,哪些无效。
我用 Python 编写了以下程序,通过所有 256 种可能的训练状态来模拟这个感知器。
这是此仿真的代码:
import numpy as np
np.set_printoptions(formatter={'float': '{: 0.1f}'.format})
# Perceptron math fucntions.
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def sigmoid_derivative(x):
return x * (1 - x)
# END Perceptron math functions.
# The first column of 1's is used as the bias.
# The other 3 cols are the actual inputs, x3, x2, and x1 respectively
training_inputs = np.array([[1, 0, 0, 0],
[1, 0, 0, 1],
[1, 0, 1, 0],
[1, 0, 1, 1],
[1, 1, 0, 0],
[1, 1, 0, 1],
[1, 1, 1, 0],
[1, 1, 1, 1]])
# Setting up the training outputs data set array
num_array = np.array
num_array = np.arange(8).reshape([1,8])
num_array.fill(0)
for num in range(25):
bnum = bin(num).replace('0b',"").rjust(8,"0")
for i in range(8):
num_array[0,i] = int(bnum[i])
training_outputs = num_array.T
# training_outputs will have the array form: [[n,n,n,n,n,n,n,n]]
# END of setting up training outputs data set array
# ------- BEGIN Perceptron functions ----------
np.random.seed(1)
synaptic_weights = 2 * np.random.random((4,1)) - 1
for iteration in range(20000):
input_layer = training_inputs
outputs = sigmoid(np.dot(input_layer, synaptic_weights))
error = training_outputs - outputs
adjustments = error * sigmoid_derivative(outputs)
synaptic_weights += np.dot(input_layer.T, adjustments)
# ------- END Perceptron functions ----------
# Convert to clean output 0, 0.5, or 1 instead of the messy calcuated values.
# This is to make the printout easier to read.
# This also helps with testing analysis below.
for i in range(8):
if outputs[i] <= 0.25:
outputs[i] = 0
if (outputs[i] > 0.25 and outputs[i] < 0.75):
outputs[i] = 0.5
if outputs[i] > 0.75:
outputs[i] = 1
# End convert to clean output values.
# Begin Testing Analysis
# This is to check to see if we got the correct outputs after training.
evaluate = "Good"
test_array = training_outputs
for i in range(8):
# Evaluate for a 0.5 error.
if outputs[i] == 0.5:
evaluate = "The 0.5 Error"
break
# Evaluate for incorrect output
if outputs[i] != test_array[i]:
evaluate = "Wrong Answer"
# End Testing Analysis
# Printout routine starts here:
print_array = test_array.T
print("Test#: {0}, Training Data is: {1}".format(num, print_array[0]))
print("{0}, {1}".format(outputs.T, evaluate))
print("")
当我运行这段代码时,我得到了前 25 个训练测试的以下输出。
Test#: 0, Training Data is: [0 0 0 0 0 0 0 0]
[[ 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0]], Good
Test#: 1, Training Data is: [0 0 0 0 0 0 0 1]
[[ 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0]], Good
Test#: 2, Training Data is: [0 0 0 0 0 0 1 0]
[[ 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0]], Good
Test#: 3, Training Data is: [0 0 0 0 0 0 1 1]
[[ 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0]], Good
Test#: 4, Training Data is: [0 0 0 0 0 1 0 0]
[[ 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0]], Good
Test#: 5, Training Data is: [0 0 0 0 0 1 0 1]
[[ 0.0 0.0 0.0 0.0 0.0 1.0 0.0 1.0]], Good
Test#: 6, Training Data is: [0 0 0 0 0 1 1 0]
[[ 0.0 0.0 0.0 0.0 0.5 0.5 0.5 0.5]], The 0.5 Error
Test#: 7, Training Data is: [0 0 0 0 0 1 1 1]
[[ 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0]], Good
Test#: 8, Training Data is: [0 0 0 0 1 0 0 0]
[[ 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0]], Good
Test#: 9, Training Data is: [0 0 0 0 1 0 0 1]
[[ 0.0 0.0 0.0 0.0 0.5 0.5 0.5 0.5]], The 0.5 Error
Test#: 10, Training Data is: [0 0 0 0 1 0 1 0]
[[ 0.0 0.0 0.0 0.0 1.0 0.0 1.0 0.0]], Good
Test#: 11, Training Data is: [0 0 0 0 1 0 1 1]
[[ 0.0 0.0 0.0 0.0 1.0 0.0 1.0 1.0]], Good
Test#: 12, Training Data is: [0 0 0 0 1 1 0 0]
[[ 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0]], Good
Test#: 13, Training Data is: [0 0 0 0 1 1 0 1]
[[ 0.0 0.0 0.0 0.0 1.0 1.0 0.0 1.0]], Good
Test#: 14, Training Data is: [0 0 0 0 1 1 1 0]
[[ 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0]], Good
Test#: 15, Training Data is: [0 0 0 0 1 1 1 1]
[[ 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0]], Good
Test#: 16, Training Data is: [0 0 0 1 0 0 0 0]
[[ 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0]], Good
Test#: 17, Training Data is: [0 0 0 1 0 0 0 1]
[[ 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0]], Good
Test#: 18, Training Data is: [0 0 0 1 0 0 1 0]
[[ 0.0 0.0 0.5 0.5 0.0 0.0 0.5 0.5]], The 0.5 Error
Test#: 19, Training Data is: [0 0 0 1 0 0 1 1]
[[ 0.0 0.0 0.0 1.0 0.0 0.0 1.0 1.0]], Good
Test#: 20, Training Data is: [0 0 0 1 0 1 0 0]
[[ 0.0 0.5 0.0 0.5 0.0 0.5 0.0 0.5]], The 0.5 Error
Test#: 21, Training Data is: [0 0 0 1 0 1 0 1]
[[ 0.0 0.0 0.0 1.0 0.0 1.0 0.0 1.0]], Good
Test#: 22, Training Data is: [0 0 0 1 0 1 1 0]
[[ 0.0 0.0 0.0 1.0 0.0 1.0 1.0 1.0]], Wrong Answer
Test#: 23, Training Data is: [0 0 0 1 0 1 1 1]
[[ 0.0 0.0 0.0 1.0 0.0 1.0 1.0 1.0]], Good
Test#: 24, Training Data is: [0 0 0 1 1 0 0 0]
[[ 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0]], Wrong Answer
在大多数情况下,它似乎正在工作。但是在某些情况下它显然不起作用。
我有两种不同的标签。
第一种错误是很容易看到的“0.5 错误”。在这种情况下,它永远不应该返回 0.5 的任何输出。一切都应该是二进制的。第二种错误是当它报告正确的二进制输出但它们与训练识别的内容不匹配时。
我想了解这些错误的原因。我对尝试纠正错误不感兴趣,因为我相信这些是有效的错误。换句话说,这些是感知器根本无法训练的情况。没关系。
我想了解的是为什么这些案例是无效的。我怀疑它们与在这些情况下无法线性分离的输入数据有关。但如果是这样的话,那么我该如何确定哪些情况不是线性可分的呢?如果我能理解如何做到这一点,我会非常高兴。
另外,它在特定情况下不起作用的原因是否相同?换句话说,这两种类型的错误都是由输入数据的线性不可分性引起的吗?或者是否有不止一种情况会导致感知器在某些训练情况下失败。
任何帮助,将不胜感激。