什么?神经网络还能创造新知识?
神经网络(NNs)可以在不知道用显式算法执行工作的情况下被设计和训练于特定的任务,很多人都对此表示惊叹。例如,著名的手写体数字识别教程很容易执行,但其背后的逻辑还是隐藏在神经网络下,仅能通过层次化结构、权值和激活函数略知一二。
图片来源:Unsplash
本文通过神经网络透明原则来揭示其“黑盒知识”,为此来检验一个布尔异或函数的神经网络。首先,利用已知异或属性过程构造了一个自底向上的神经网络,即清晰包含已知的代数关系。在第二步中使用TensorFlow Keras从简易图形化编程工具到异或逻辑运算训练神经网络。
最后比较两种方法。将Keras神经网络分解为布尔组件,发现逻辑设置与第一步中构造的神经网络不同。被训练的神经网络发现了使用不同布尔函数的另一种异或运算表示方法。
这另一种异或公式在数学领域不是未知的,但至少很新奇。这或许表明神经网络可以创造新的知识。但要提取它,必须能够将神经网络的设置和参数转化为显式规则。
自底向上构造异或运算神经网络(XOR NN)
异或运算是由映射定义的布尔函数,
XOR (0,0) = XOR (1,1) = 0 XOR (1,0) = XOR (0,1) = 1
为异或运算构造一个已知的神经网络或谷歌标识列
XOR (x,y) = AND ( NAND (x,y) , OR (x,y) )
这很有帮助,因为操作符AND、NAND(而非AND)和OR是众所周知的,并且都可以用简单的神经网络来表示,其中有2个输入和1个输出结点、偏移量和sigmoid激活函数。
布尔函数操作符的神经网络
在此基础上可通过连接NAND、AND和OR的NNs来构造异或运算神经网络。所以异或变成了一个三层神经网络。
异或运算的神经网络
输送可能的输入配置并检查输出(本文使用Excel工作表)。分别得到有效的(0,0)、(1,1)的0.0072以及(0,1)、(1,0)的0.9924。
可以用以下异或运算的表示来建构其他的神经网络:
XOR (x,y) = OR ( AND ( NOT(x) , y ) , AND ( x , NOT(y) ) ) XOR (x,y) = NAND ( NAND ( x , NAND ( x,y) ) , NAND ( y , NAND ( x,y) ) )
然而这些标识列导致了更复杂的网络。
此外,由于异或运算不能通过线性可分(且激活函数严格单调),因此,不可能建立两层的神经网络。
但也许还有其他方法可以构建异或运算的神经网络呢?下一节将通过训练神经网络来寻找另一种解决方案。
使用TensorFlow Keras构建异或神经网络
Keras是一个功能强大且易于使用的神经网络库。上一节中建立了一个三层的2-2-1模型,并与之前建构的神经网络进行了比较。
使用梯度下降优化器与学习率1和均方误差损失函数的误差反向传播,这是建构神经网络的标准方法。
以下是Python的代码片段:
# Generate NN for XOR operation # input layer: <NODES> nodes, one for each bit (0 = false and +1 = true) # output layer: 1 node for result (0 = false and +1 = true) # Use sigmoid activation function, gradient descent optimizer and mean squared error loss function # Last update: 28.05.2019 import tensorflow as tf import numpy as np import matplotlib.pyplot as plt # Define model nodes = 2 model = tf.keras.Sequential() model.add(tf.keras.layers.Dense(nodes, input_dim=2, activation=tf.nn.sigmoid)) model.add(tf.keras.layers.Dense(1, activation=tf.nn.sigmoid)) model.compile(optimizer=tf.train.GradientDescentOptimizer(1), loss=tf.keras.losses.mean_squared_error, metrics=['binary_accuracy']) model.summary() # Generate train & test data epochs = 10000 data_in = np.array([[0,0],[0,1],[1,0],[1,1]]) data_out = np.array([0,1,1,0]) # Train model history = model.fit(data_in, data_out, epochsepochs=epochs, verbose=0) # Analysis of training history for key in history.history.keys(): plt.scatter(range(epochs), history.history[key], s=1) plt.ylabel(key) plt.xlabel('epochs') plt.show() # Predict with model result = model.predict(data_in) # Print results def printarray(arr): return np.array2string(arr).replace('\n','') print() print('input', printarray(data_in)) print('output (calculation)', printarray(data_out)) print('output (prediction) ', printarray(result)) print('output (pred. norm.)', printarray(np.round(result))) # Get weights of model print() print(model.get_weights())
异或运算的好处是可以训练整个参数空间,因为只有四种可能的配置可以教。然而,需要一些在神经网络中传递数据集的过程来驱动模型达到零损耗和100%精准,即输出趋向于一个分别是(0,1)、(1,0)和(0,0)、(1,1)的零。
异或运算神经网络的Loss和epochs对比
异或运算神经网络的Accuracy 和epochs对比
然而,训练期也可能陷入停滞,无法衔接。接着精准度停止在75%甚至50%,即一个或两个二元元组的映射是不正确的。在这种情况下就要重新构建神经网络,直到得到合适的解决方案。
分析和结论
现在验证Keras神经网络是否与建构的具有相似结构。通过返回权值(参见代码片段的末尾),得到了权值和偏差值。
Python的脚本输出
使用这些参数来重建神经网络(再次使用Excel)。由三个操作符组成。
基于Keras训练的异或运算神经网络
通过输入所有可能的配置,可以识别与H1、H2和O操作符关联的布尔函数。
Keras在异或运算神经网络中的布尔函数
有趣的是,本以为Keras 神经网络与所建构的逻辑是一样的,但它却创建了另一种解决方案。使用OR,AND和(相对没人知道的)INH,而非操作符NAND, OR 和AND,即神经网络找到的公式。
XOR (x,y) = INH ( OR (x,y), AND (x,y) )