XOR没有使用keras v2.0学习

时间:2017-05-03 02:57:29

标签: python numpy neural-network keras

我有一段时间使用工具keras得到了相当糟糕的结果,并且对这个工具的怀疑并不多......但我现在开始有点担心了。

我试图看看它是否可以处理一个简单的XOR问题,并且在30000个时代之后它还没有解决它......

代码:

from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.optimizers import SGD
import numpy as np

np.random.seed(100)

model = Sequential()
model.add(Dense(2, input_dim=2))
model.add(Activation('tanh'))
model.add(Dense(1, input_dim=2))
model.add(Activation('sigmoid'))
X = np.array([[0,0],[0,1],[1,0],[1,1]], "float32")
y = np.array([[0],[1],[1],[0]], "float32")
model.compile(loss='binary_crossentropy', optimizer='adam')
model.fit(X, y, nb_epoch=30000, batch_size=1,verbose=1)

print(model.predict_classes(X))

以下是我的结果的一部分:

4/4 [==============================] - 0s - loss: 0.3481     
Epoch 29998/30000
4/4 [==============================] - 0s - loss: 0.3481     
Epoch 29999/30000
4/4 [==============================] - 0s - loss: 0.3481     
Epoch 30000/30000
4/4 [==============================] - 0s - loss: 0.3481     
4/4 [==============================] - 0s
[[0]
 [1]
 [0]
 [0]]

该工具是否有问题 - 或者我做错了什么?

我正在使用的版本:

MacBook-Pro:~ usr$ python -c "import keras; print keras.__version__"
Using TensorFlow backend.
2.0.3
MacBook-Pro:~ usr$ python -c "import tensorflow as tf; print tf.__version__"
1.0.1
MacBook-Pro:~ usr$ python -c "import numpy as np; print np.__version__"
1.12.0

更新版本:

from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.optimizers import Adam, SGD
import numpy as np

#np.random.seed(100)

model = Sequential()
model.add(Dense(units = 2, input_dim=2, activation = 'relu'))
model.add(Dense(units = 1, activation = 'sigmoid'))
X = np.array([[0,0],[0,1],[1,0],[1,1]], "float32")
y = np.array([[0],[1],[1],[0]], "float32")
model.compile(loss='binary_crossentropy', optimizer='adam')
print model.summary()
model.fit(X, y, nb_epoch=5000, batch_size=4,verbose=1)

print(model.predict_classes(X))

4 个答案:

答案 0 :(得分:2)

我不能对Daniel的回复添加评论,因为我没有足够的声誉,但我相信他是在正确的轨道上。虽然我没有亲自尝试使用Keras运行XOR,但这篇文章可能很有趣 - 它分析了2-2-1网络的局部最小区域,显示更高的数值精度会导致更少的卡住实例在梯度下降算法上。

The Local Minima of the Error Surface of the 2-2-1 XOR Network (Ida G. Sprinkhuizen-Kuyper and Egbert J.W. Boers)

另一方面,我不会考虑使用2-4-1网络来解决问题。在0-1平面上进行4次线性切割(切割成2x2网格)而不是2次切割(沿对角线切割角落)只是以不同方式分离数据,但由于我们只有4个数据点并且没有噪声数据,使用4个线性切割的神经网络不描述“噪声”而不是XOR关系。

答案 1 :(得分:1)

尝试使用relu激活隐藏图层而不是tanh,而不仅仅是增加时代数。只对您提供的代码进行更改,我只能在2000个时期(Theano后端)之后获得以下结果:

import numpy as np
print(np.__version__) #1.11.3
import keras
print(theano.__version__) # 0.9.0
import theano
print(keras.__version__) # 2.0.2

from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.optimizers import Adam, SGD

np.random.seed(100)

model = Sequential()
model.add(Dense(units = 2, input_dim=2, activation = 'relu'))
model.add(Dense(units = 1, activation = 'sigmoid'))
X = np.array([[0,0],[0,1],[1,0],[1,1]], "float32")
y = np.array([[0],[1],[1],[0]], "float32")
model.compile(loss='binary_crossentropy', optimizer='adam'
model.fit(X, y, epochs=2000, batch_size=1,verbose=0)
print(model.evaluate(X,y))
print(model.predict_classes(X))
4/4 [==============================] - 0s
0.118175707757
4/4 [==============================] - 0s
[[0]
[1]
[1]
[0]]

很容易得出结论,这是由于vanishing gradient problem。但是,这个网络的简单性表明情况并非如此。实际上,如果我将优化器从'adam'更改为SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False)(默认值),我可以在隐藏层中激活tanh的5000个纪元后看到以下结果。

from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.optimizers import Adam, SGD

np.random.seed(100)

model = Sequential()
model.add(Dense(units = 2, input_dim=2, activation = 'tanh'))
model.add(Dense(units = 1, activation = 'sigmoid'))
X = np.array([[0,0],[0,1],[1,0],[1,1]], "float32")
y = np.array([[0],[1],[1],[0]], "float32")
model.compile(loss='binary_crossentropy', optimizer=SGD())
model.fit(X, y, epochs=5000, batch_size=1,verbose=0)

print(model.evaluate(X,y))
print(model.predict_classes(X))
4/4 [==============================] - 0s
0.0314897596836
4/4 [==============================] - 0s
[[0]
 [1]
 [1]
 [0]]

修改: 5/17/17 - 包含完整代码以启用复制

答案 2 :(得分:1)

我认为它在损失函数中是"本地最小值"

为什么?

我一遍又一遍地运行相同的代码几次,有时它是正确的,有时它会陷入错误的结果。请注意,此代码"重新创建"每次运行它时的模型。 (如果我坚持训练一个发现错误结果的模型,它将永远保存在那里)。

from keras.models import Sequential
from keras.layers import *
import numpy as np

m = Sequential()
m.add(Dense(2,input_dim=2, activation='tanh'))
#m.add(Activation('tanh'))

m.add(Dense(1,activation='sigmoid'))
#m.add(Activation('sigmoid'))

X = np.array([[0,0],[0,1],[1,0],[1,1]],'float32')
Y = np.array([[0],[1],[1],[0]],'float32')

m.compile(optimizer='adam',loss='binary_crossentropy')
m.fit(X,Y,batch_size=1,epochs=20000,verbose=0)
print(m.predict(X))

运行此代码,我发现了一些不同的输出:

  • 错误:[[0.00392423],[0.99576807],[0.50008368],[0.50008368]]
  • 右:[[0.08072935],[0.95266515],[0.95266813],[0.09427474]]

我们可以从中得出什么结论?

优化器未正确处理此本地最小值。如果它变得幸运(适当的重量初始化),它将落在最低限度,并带来正确的结果。

如果它运气不好(一个糟糕的权重初始化),它将落在局部最小值,而不是真的知道损失函数中有更好的位置,并且其learn_rate不足以逃脱这个最小值。小渐变在同一点上转动。

如果你花时间研究哪个渐变出现在错误的情况下,你可能会看到它一直指向同一个点,并且稍微提高学习率可能会让它逃脱漏洞。

直觉让我觉得这种非常小的模型具有更突出的局部最小值。

答案 3 :(得分:0)

学习XOR所需的最小神经元网络体系结构,它应该是(2,2,1)网络。实际上,如果数学表明(2,2,1)网络可以解决XOR问题,但数学并不表明(2,2,1)网络易于训练。有时可能需要花费很多时间(迭代次数)或无法收敛到全局最小值。就是说,使用(2,3,1)或(2,4,1)网络体系结构,我很容易获得良好的结果。

问题似乎与许多局部极小值的存在有关。请看1998年Richard Bland的论文《 Learning XOR: exploring the space of a classic problem》。此外,权重初始化(随机数在0.5到1.0之间)有助于收敛。

它与Keras或TensorFlow一起使用损失函数'mean_squared_error',S型激活和Adam优化器可以正常工作。即使有了非常好的超参数,我也观察到学习到的XOR模型被困在局部最小值中的时间约为15%。

from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from tensorflow.keras import initializers
import numpy as np 

X = np.array([[0,0],[0,1],[1,0],[1,1]])
y = np.array([[0],[1],[1],[0]])

def initialize_weights(shape, dtype=None):
    return np.random.normal(loc = 0.75, scale = 1e-2, size = shape)

model = Sequential()
model.add(Dense(2, 
                activation='sigmoid', 
                kernel_initializer=initialize_weights, 
                input_dim=2))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='mean_squared_error', 
              optimizer='adam', 
              metrics=['accuracy'])

print("*** Training... ***")

model.fit(X, y, batch_size=4, epochs=10000, verbose=0)

print("*** Training done! ***")

print("*** Model prediction on [[0,0],[0,1],[1,0],[1,1]] ***")

print(model.predict_proba(X))

***培训... ***

***培训完成! ***

*** [[0,0],[0,1],[1,0],[1,1]] ***上的模型预测

[[0.08662204] [0.9235283] [0.92356336] [0.06672956]]