关于XOR和多层感知机(MLP)的问题困扰我有一段时间了;这可能是一个基础问题(如果是的话,提前道歉),但我想了解更多。
解决XOR问题的MLP方法有很多,但通常看起来像这样:
from sklearn.neural_network import MLPClassifierX = [[0, 0], [0, 1], [1, 0], [1, 1]]y = [0, 1, 1, 0]model = MLPClassifier( activation='relu', max_iter=1000, hidden_layer_sizes=(4,2))
现在来训练模型:
model.fit(X, y)
那么,你猜怎么着?
print('score:', model.score(X, y))
输出一个完美的
score: 1.0
但是到底预测和评分的是什么?在XOR的情况下,我们有一个数据集,按定义(!)有四行、两个特征和一个二进制标签。没有标准的X_train, y_train, X_test, y_test
可以使用。同样,按定义,没有未见过的数据供模型处理。
预测是以这种形式进行的
model.predict(X)
这与训练时使用的X
完全相同。
那么,模型不是仅仅吐回它训练过的y
吗?我们怎么知道模型“学”到了什么呢?
编辑:只是为了试图澄清我的困惑——特征只有2个且仅2个独特值;这2个独特值有4种且仅4种可能的组合。每种可能组合的正确标签已经存在于标签列中。那么,当调用fit()
时,模型还有什么可以“学习”的呢?这种“学习”是如何进行的?当模型可以访问每种可能输入组合的“正确”答案时,它怎么可能“错误”呢?
再次,为这可能是一个非常基础的问题道歉。
回答:
关键是XOR问题被提出是为了展示某些模型可以学习非线性问题,而某些模型则不能。
所以,当一个模型在你提到的数据集上获得1.0的准确率时,这是值得注意的,因为它学会了非线性问题。模型学会了训练数据,这足以让我们知道它可以[潜在地]学习非线性模型。注意,如果不是这样,你的模型会得到非常低的准确率,比如0.25,因为它用一条线将二维空间分成了两个子空间。
为了更好地理解这一点,让我们看一个模型在相同情况下无法学习数据的案例:
import tensorflow as tfimport numpy as npX = np.array(X)y = np.array(y)model = tf.keras.models.Sequential()model.add(tf.keras.layers.Dense(2, activation='relu'))model.compile(optimizer=tf.train.GradientDescentOptimizer(learning_rate=0.1), loss='categorical_crossentropy', metrics=['categorical_accuracy'])model.fit(X, y, epochs=100)_, acc = model.evaluate(X, y)print('acc = ' + str(acc))
这给出:
acc = 0.5
如你所见,这个模型无法对它已经见过的数据进行分类。原因是,这是一个非线性数据,而我们的模型只能分类线性数据。(这里有一个链接可以更好地理解XOR问题的非线性)。一旦我们给网络添加另一层,它就能够解决这个问题:
import tensorflow as tfimport numpy as npX = np.array(X)y = np.array(y)model = tf.keras.models.Sequential()model.add(tf.keras.layers.Dense(1, activation='relu'))model.add(tf.keras.layers.Dense(2, activation='relu'))tb_callback = tf.keras.callbacks.TensorBoard(log_dir='./test/', write_graph=True)model.compile(optimizer=tf.train.GradientDescentOptimizer(learning_rate=0.1), loss='categorical_crossentropy', metrics=['categorical_accuracy'])model.fit(X, y, epochs=5, callbacks=[tb_callback, ])acc = model.evaluate(X, y)print('acc = ' + str(acc))
这给出:
acc = 1.0
只通过添加一个神经元,我们的模型学会了在100个周期内用1层无法学习的东西(尽管它已经见过了数据)。
总而言之,虽然我们的数据集很小,网络可以轻松地记忆它,但XOR问题很重要,因为这意味着有些网络无论如何都无法记忆这些数据。
不过,话虽如此,也有各种具有适当训练和测试集的XOR问题。这里是一个(图表略有不同):
import numpy as npimport matplotlib.pyplot as pltx1 =np.concatenate([np.random.uniform(0, 100, 100), np.random.uniform(-100, 0, 100)])y1 =np.concatenate([np.random.uniform(-100, 0, 100), np.random.uniform(0, 100, 100)])x2 =np.concatenate([np.random.uniform(0, 100, 100), np.random.uniform(-100, 0, 100)])y2 =np.concatenate([np.random.uniform(0, 100, 100), np.random.uniform(-100, 0, 100)])plt.scatter(x1, y1, c='red')plt.scatter(x2, y2, c='blue')plt.show()
希望这对你有帮助;))