机器学习奇数/偶数预测不起作用(50% 成功)

Mil*_*ano 6 python machine-learning keras tensorflow

我对机器学习很陌生。我试图创建一个模型来预测数字是否为偶数。

我使用了这个代码https://machinelearningmastery.com/tutorial-first-neural-network-python-keras/ 我根据我的需要改变了它。

问题是大约有 50% 的成功率等于随机。

你知道怎么做才能让它发挥作用吗?

from keras.models import Sequential
from keras.layers import Dense
import numpy
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)

X = list(range(1000))
Y = [1,0]*500
# create model
model = Sequential()
model.add(Dense(12, input_dim=1, init='uniform', activation='relu'))
model.add(Dense(8, init='uniform', activation='relu'))
model.add(Dense(1, init='uniform', activation='sigmoid'))
# Compile model
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy'])
# Fit the model
model.fit(X, Y, epochs=150, batch_size=10,  verbose=2)
# calculate predictions
predictions = model.predict(X)
# round predictions
rounded = [round(x[0])for x in predictions]
print(rounded)


>>> [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
Run Code Online (Sandbox Code Playgroud)

Dun*_*nes 6

神经网络不擅长判断数字是否为偶数。至少如果输入表示只是一个整数则不会。神经网络擅长找出并组合线性决策边界。对于所有自然数,有无限多个决策边界来检查数字是否为偶数。但是,如果您只想让神经网络处理所有数字的子集,那么您就可以让它工作。但是,您希望能够在输入层中测试的每个数字本质上都需要一个神经元。因此,0 <= n < 1000您的输入层中需要一千个神经元。这并不是神经网络的一个很好的例子。

如果您要将输入的表示形式更改为数字的二进制表示形式,那么神经网络将更容易检测数字是否为偶数。例如。

X = [
  [0, 0, 0], # 0
  [0, 0, 1], # 1
  [0, 1, 0], # 2
  [0, 1, 1], # 3
  [1, 0, 0], # 4
  [1, 0, 1], # 5
  [1, 1, 0], # 6
  [1, 1, 1]  # 7
]

Y = [1, 0, 1, 0, 1, 0, 1, 0]
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,现在这是一个要解决的相当简单的问题:基本上是最后一个二进制数字的倒数。这是一个对输入进行预处理以创建神经网络更容易解决的问题的示例。


Hoj*_*atK 5

我认为阅读感知器异或问题以了解单个感知器的工作原理及其局限性是一个好主意。

预测一个数字是否为偶数是一个二元分类问题,具有一维输入;在分类问题中,训练神经网络通过边界来分离类别。思考这个问题的一种方法是通过将输入数字添加到添加的维度(例如将 7 映射到 [7, 7])来将其一维输入映射为二维输入,并查看偶数和奇数向量在散点图中的样子。

如果您在 Jupyter Notebook 中运行以下代码

%matplotlib inline
import matplotlib.pyplot as plt

X = list(range(-20, 20))
evens = [x for x in X if x % 2 == 0]
odds = [x for x in X if x % 2 != 0]
data = (evens, odds)
colors = ("green", "blue")
groups = ("Even", "Odd") 

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
for data, color, group in zip(data, colors, groups):
    x = data
    ax.scatter(x, x, alpha=0.8, c=color, edgecolors='none', s=30, label=group)
plt.title('Even/Odd numbers')
plt.legend(loc=2)
plt.show()

data = (evens, odds)
fig2 = plt.figure()
ax = fig2.add_subplot(1, 1, 1)
for data, color, group in zip(data, colors, groups):
    x = data
    y = [abs(i) if i%2==0 else -abs(i) for i in data]
    ax.scatter(x, y, alpha=0.8, c=color, edgecolors='none', s=30, label=group)
plt.title('Even/Odd numbers (Separatable)')
plt.legend(loc=2)
plt.show()
Run Code Online (Sandbox Code Playgroud)

您将看到类似下图的内容:

偶数和奇数

您可以在第一张图中看到,实际上不可能在偶数和奇数向量之间得出边界,但是如果将第二维数映射到其等效的负数,则在两个类(偶数和奇数向量)之间绘制边界简单。因此,如果您将输入数据转换为二维,并根据偶数或奇数对第二维值取反,那么神经网络可以学习如何分离偶数和奇数向量类。

您可以尝试类似下面的代码,您将看到网络将学习并收敛到几乎 100% 的准确度。

import numpy
from keras.models import Sequential
from keras.layers import Dense

# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)

X = numpy.array([[x, x if x%2 == 0 else -x] for x in range(1000)])
Y = [1,0]*500

# create model
model = Sequential()
model.add(Dense(12, input_dim=2, init='uniform', activation='relu'))
model.add(Dense(8, init='uniform', activation='relu'))
model.add(Dense(1, init='uniform', activation='sigmoid'))
# Compile model
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy'])
# Fit the model
model.fit(X, Y, epochs=50, batch_size=10,  verbose=2)
# Calculate predictions
predictions = model.predict(X)
Run Code Online (Sandbox Code Playgroud)

请注意,根据偶数或奇数将数字转换为负空间也适用于一维,但使用二维向量的散点图更容易演示。


pro*_*sti 5

以下是我在 Keras 中创建模型以在 Python 3 中对奇数/偶数进行分类的方法。

它仅在第一个隐藏层中使用 1 个神经元,并具有 32 个输入。输出层只有 2 个神经元,用于 one-hot 编码 0 和 1。

from keras.models import Sequential
from keras.layers import Dense
from keras.utils import to_categorical


# Helper function to convert a number 
# to its fixed width binary representation
def conv(x):
  a = format(x, '032b')
  l = list(str(a))
  l = np.array(list(map(int, l)))
  return l

# input data
data = [conv(i) for i in range(100000)]
X = np.array(data)


Y= list() # empty list of results
for v in range(100000):
  Y.append( to_categorical(v%2, 2) )

Y = np.array(Y) # we need np.array


# Sequential is a fully connected network
model = Sequential()

# 32 inputs and 1 neuron in the first layer (hidden layer)
model.add(Dense(1, input_dim=32, activation='relu'))

# 2 output layer 
model.add(Dense(2, activation='sigmoid'))


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

# epochs is the number of times to retrain over the same data set
# batch_size is how may elements to process in parallel at one go
model.fit(X, Y, epochs=5, batch_size=100, verbose=1)
weights, biases = model.layers[0].get_weights()
print("weights",weights.size, weights, "biases", biases)
model.summary()
Run Code Online (Sandbox Code Playgroud)
Epoch 1/5
100000/100000 [==============================] - 3s 26us/step - loss: 0.6111 - acc: 0.6668
Epoch 2/5
100000/100000 [==============================] - 1s 13us/step - loss: 0.2276 - acc: 1.0000
Epoch 3/5
100000/100000 [==============================] - 1s 13us/step - loss: 0.0882 - acc: 1.0000
Epoch 4/5
100000/100000 [==============================] - 1s 13us/step - loss: 0.0437 - acc: 1.0000
Epoch 5/5
100000/100000 [==============================] - 1s 13us/step - loss: 0.0246 - acc: 1.0000
weights 32 [[-4.07479703e-01]
 [ 2.29798079e-01]
 [ 4.12091196e-01]
 [-1.86401993e-01]
 [ 3.70162904e-01]
 [ 1.34553611e-02]
 [ 2.01252878e-01]
 [-1.00370705e-01]
 [-1.41752958e-01]
 [ 7.27931559e-02]
 [ 2.55639553e-01]
 [ 1.90407157e-01]
 [-2.42316410e-01]
 [ 2.43226111e-01]
 [ 2.22285628e-01]
 [-7.04377817e-05]
 [ 2.20522008e-04]
 [-1.48785894e-05]
 [-1.15533156e-04]
 [ 1.16850446e-04]
 [ 6.37861085e-05]
 [-9.74628711e-06]
 [ 3.84256418e-05]
 [-6.19597813e-06]
 [-7.05791535e-05]
 [-4.78575275e-05]
 [-3.07796836e-05]
 [ 3.26417139e-05]
 [-1.51580054e-04]
 [ 1.27965177e-05]
 [ 1.48101550e-04]
 [ 3.18456793e+00]] biases [-0.00016785]
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_49 (Dense)             (None, 1)                 33        
_________________________________________________________________
dense_50 (Dense)             (None, 2)                 4         
=================================================================
Total params: 37
Trainable params: 37
Non-trainable params: 0
Run Code Online (Sandbox Code Playgroud)

以下是预测:

print(X[0:1])
scores = model.predict(X[0:1])
print(scores)
print(np.argmax(scores))

print(X[1:2])
scores = model.predict(X[1:2])
print(scores)
print(np.argmax(scores))

[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]
[[0.9687797  0.03584918]]
0
[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]]
[[0.00130448 0.9949934 ]]
1
Run Code Online (Sandbox Code Playgroud)


Kor*_*ral 1

我对它不起作用并不感到惊讶——神经网络根本不是那样工作的。

你必须更好地感受你传递给神经网络的输入是什么。

当您传递数字时,它必须具有某种意义。这意味着:如果一个数字大于另一个数字,就会导致某些情况。就像年龄->金钱,应该有任何依赖性。

但当寻找奇数时,这个含义就更加抽象了。老实说,您应该将您的输入视为独立的字符串值。

也许:请尝试将其作为输入:

X = [[math.floor(item/2), item/2 - math.floor(item/2)] for item in range(1000)]
Run Code Online (Sandbox Code Playgroud)

并检查网络是否会理解“如果第二个值大于零,则数字为奇数”。

继续阅读以获得更好的感觉:)

编辑:

@MIlano 完整代码如下

from keras.models import Sequential
from keras.layers import Dense
import numpy
import math
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)

X = numpy.array([[math.floor(item/2), item/2 - math.floor(item/2)] for item in range(1000)])

Y = [1, 0]*500
# create model
model = Sequential()
model.add(Dense(12, input_shape=(2,), init='uniform', activation='relu'))
model.add(Dense(8, init='uniform', activation='relu'))
model.add(Dense(1, init='uniform', activation='sigmoid'))
# Compile model
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy'])
# Fit the model
model.fit(X, Y, epochs=150, batch_size=10,  verbose=2)
# calculate predictions
predictions = model.predict(X)
# round predictions
rounded = [round(x[0])for x in predictions]
print(rounded)
Run Code Online (Sandbox Code Playgroud)