Python 训练神经网络来计算';异或';在scikit中学习

Python 训练神经网络来计算';异或';在scikit中学习,python,numpy,machine-learning,scikit-learn,Python,Numpy,Machine Learning,Scikit Learn,我正在尝试学习如何使用scikit learn的MLPC分类器。对于一个非常简单的例子,我想我应该试着让它学习如何计算XOR函数,因为我以前做过一个手工练习 然而,在我尝试拟合模型后,它只会吐出零 xs = np.array([ 0, 0, 0, 1, 1, 0, 1, 1 ]).reshape(4, 2) ys = np.array([0, 1, 1, 0]).reshape(4,) model = sklearn.neural_network.MLPCla

我正在尝试学习如何使用scikit learn的MLPC分类器。对于一个非常简单的例子,我想我应该试着让它学习如何计算XOR函数,因为我以前做过一个手工练习

然而,在我尝试拟合模型后,它只会吐出零

xs = np.array([
    0, 0,
    0, 1,
    1, 0,
    1, 1
]).reshape(4, 2)

ys = np.array([0, 1, 1, 0]).reshape(4,)

model = sklearn.neural_network.MLPClassifier(
    activation='logistic', max_iter=10000, hidden_layer_sizes=(4,2))
model.fit(xs, ys)

print('score:', model.score(xs, ys)) # outputs 0.5
print('predictions:', model.predict(xs)) # outputs [0, 0, 0, 0]
print('expected:', np.array([0, 1, 1, 0]))
我把我的代码也放在github上的jupyter笔记本中


当我可以明确地证明存在一个解决方案时,为什么scikit learn不能找到一个解决方案?成本函数是否陷入局部最小值?参数上是否发生了某种正则化,迫使它们保持接近0?我使用的参数相当大(即-30到30)。

看来逻辑激活是根本原因

将激活更改为
tanh
relu
(我的最爱)。演示:

此模型的输出:

score: 1.0
predictions: [0 1 1 0]
expected: [0 1 1 0]

在选择最好的网络配置或完全放弃之前,尝试不同的网络配置总是一个好主意。

实际上,这里的重点是关于“解算器”,它默认为“adam”,适用于大型数据集。更大的“alpha”也应该改善:

MLPClassifier(activation='logistic', max_iter=100, hidden_layer_sizes=(3,), alpha=0.001, solver='lbfgs', verbose = True)

顺便说一句,在一个隐藏层中只有3个元素可以用

解决这个问题。下面是一个简单的例子,通过sklearn.neural\u网络进行XOR分类

import numpy as np
import sklearn.neural_network

inputs = np.array([[0,0],[0,1],[1,0],[1,1]])
expected_output = np.array([0,1,1,0])

model = sklearn.neural_network.MLPClassifier(
                activation='logistic',
                max_iter=100,
                hidden_layer_sizes=(2,),
                solver='lbfgs')
model.fit(inputs, expected_output)
print('predictions:', model.predict(inputs))

是否有一系列神奇的参数可以让模型从以前没有见过的数据中正确推断?上面提到的所有解决方案似乎都不起作用

from sklearn.ensemble import RandomForestClassifier
from sklearn.neural_network import MLPClassifier

# clf = RandomForestClassifier(random_state=0)
# clf = MLPClassifier(activation='logistic', max_iter=100, hidden_layer_sizes=(2,), alpha=0.001, solver='lbfgs', verbose = True)
clf = MLPClassifier(
                activation='logistic',
                max_iter=100,
                hidden_layer_sizes=(2,),
                solver='lbfgs')
X = [[ 0,  0],  # 2 samples, 3 features
     [0, 1],
#      [1, 0],
    [1, 1]]
y = [1, 
     0,
#      1,
     1]  # classes of each sample
clf.fit(X, y)

assert clf.predict([[0, 1]]) == [0]
assert clf.predict([[1, 0]]) == [0]

很好,就这样。然而,在我的手动设置中,我使用1/(1+e^(-z))作为激活功能。这就是后勤功能,对吗?是的,这确实是乙状结肠。根本原因可能是什么?嗯,下溢是一种可能的解释。@zrbecker溢出也是可能的,如果你设置了大参数。
from sklearn.ensemble import RandomForestClassifier
from sklearn.neural_network import MLPClassifier

# clf = RandomForestClassifier(random_state=0)
# clf = MLPClassifier(activation='logistic', max_iter=100, hidden_layer_sizes=(2,), alpha=0.001, solver='lbfgs', verbose = True)
clf = MLPClassifier(
                activation='logistic',
                max_iter=100,
                hidden_layer_sizes=(2,),
                solver='lbfgs')
X = [[ 0,  0],  # 2 samples, 3 features
     [0, 1],
#      [1, 0],
    [1, 1]]
y = [1, 
     0,
#      1,
     1]  # classes of each sample
clf.fit(X, y)

assert clf.predict([[0, 1]]) == [0]
assert clf.predict([[1, 0]]) == [0]