【问题标题】:Neural Network to predict nth square神经网络预测第 n 个正方形
【发布时间】:2017-08-25 17:17:02
【问题描述】:

我正在尝试使用多层神经网络来预测第 n 个正方形。

我有以下包含前 99 个方格的训练数据

1    1
2    4
3    9
4    16
5    25
...
98   9604
99   9801

这是代码:

import numpy as np
import neurolab as nl

# Load input data
text = np.loadtxt('data_sq.txt')

# Separate it into datapoints and labels
data = text[:, :1]
labels = text[:, 1:]

# Define a multilayer neural network with 2 hidden layers;
# First hidden layer consists of 10 neurons
# Second hidden layer consists of 6 neurons
# Output layer consists of 1 neuron
nn = nl.net.newff([[0, 99]], [10, 6, 1]) 

# Train the neural network
error_progress = nn.train(data, labels, epochs=2000, show=10, goal=0.01) 

# Run the classifier on test datapoints
print('\nTest results:')
data_test = [[100], [101]]
for item in data_test:
    print(item, '-->', nn.sim([item])[0])

第 100 和第 101 方格都打印 1:

Test results:
[100] --> [ 1.]
[101] --> [ 1.]

这样做的正确方法是什么?

【问题讨论】:

  • 文本变量中数据的格式是什么?
  • 你确定神经网络应该能够做到这一点吗?根据我的经验,神经网络并不擅长数学推理。
  • @Seanny123 我不知道。我也试图找到这一点——如果这对于神经网络或人工智能来说是一个很好的问题。如果不是NN,线性分类器会不会很合适?

标签: python-3.x machine-learning tensorflow neural-network artificial-intelligence


【解决方案1】:

检查了 neurolab 的文档 - 默认情况下,newff 在所有神经元中创建具有sigmoid 传递函数的 NN。 Sigmoid 值总是在(-1; 1) 范围内,所以你的输出永远不会离开这个范围。

第二个正方形 (4) 已超出此范围,因此您的代码与您的问题完全不符。

尝试使用其他功能(我建议SoftPlus or ReLU)。它们在前馈网络中工作得很好,允许反向传播训练(因为它们可以在整个域中导出)并且值在(0, ∞) 范围内,正如你所需要的那样。

另外:newff 的第一个参数定义了输入数据的范围 - 您正在使用 [0, 99] 匹配所有训练数据,但不匹配您在测试时尝试过的值(因为 100 和 101 是大于 99)。将此值更改为更大的值,因此您测试的值不是“特殊”(意思是“在范围的末端”) - 我建议像[-300, 300]

此外,正如 Seanny123 在评论中所说,我认为它根本不会起作用,但以目前的设置,我可以确定这一点。祝你好运。如果您成功了,请告诉我(例如在 cmets 中)。

最后但并非最不重要的一点 - 您要做的是外推(根据该范围内的值找出某个范围外的值)。 NN 更适合插值(根据该范围内的样本找出该范围内的值),因为它们应该概括训练中使用的数据。试着教它,例如,每 3 个正方形的平方(所以 1、16、49,...),然后通过询问其余的平方来测试(例如,询问 2 或 8 的平方)。

【讨论】:

  • 按照你和 Seanny123 的建议,我实施了网络。你可以在我的回答中看到结果。
  • 不错。我想知道如果你教它偶数并测试相同范围内的奇数会发生什么。我猜你会得到近乎完美的匹配,但很高兴看到这一点。
  • 我也检查并更新了我对这个案例的回答。比赛确实很不错。
【解决方案2】:

按照 Filip Malczak 和 Seanny123 的建议和 cmets,我在 tensorflow 中实现了一个神经网络,以检查当我们尝试教它预测(和插值)第二平方时会发生什么。

连续间隔训练

我在区间 [-7,7] 上训练网络(在此区间内取 300 个点,使其连续),然后在区间 [-30,30] 上对其进行测试。激活函数是 ReLu,网络有 3 个隐藏层,每个隐藏层大小为 50。epochs=500。结果如下图所示。

所以基本上,在区间 [-7,7] 内部(也接近),拟合非常完美,然后在外部或多或少线性地继续。很高兴看到,至少在最初,网络输出的斜率试图“匹配”x^2 的斜率。如果我们增加测试间隔,两张图的差异很大,如下图所示:

偶数训练

最后,如果我在区间 [-100,100] 内的所有偶数集合上训练网络,并将其应用于此区间内的所有整数(偶数和奇数)集合,我得到:

在训练网络以生成上述图像时,我将 epoch 增加到 2500 以获得更好的准确度。其余参数保持不变。因此,在训练间隔“内部”进行插值似乎效果很好(也许除了 0 附近的区域,拟合度稍差一些)。

这是我用于第一个图的代码:

import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
from tensorflow.python.framework.ops import reset_default_graph

#preparing training data
train_x=np.linspace(-7,7,300).reshape(-1,1)
train_y=train_x**2

#setting network features
dimensions=[50,50,50,1]
epochs=500
batch_size=5

reset_default_graph()
X=tf.placeholder(tf.float32, shape=[None,1])
Y=tf.placeholder(tf.float32, shape=[None,1])

weights=[]
biases=[]
n_inputs=1

#initializing variables
for i,n_outputs in enumerate(dimensions):
    with tf.variable_scope("layer_{}".format(i)):
        w=tf.get_variable(name="W",shape=[n_inputs,n_outputs],initializer=tf.random_normal_initializer(mean=0.0,stddev=0.02,seed=42))
        b=tf.get_variable(name="b",initializer=tf.zeros_initializer(shape=[n_outputs]))
        weights.append(w)
        biases.append(b)
        n_inputs=n_outputs

def forward_pass(X,weights,biases):
    h=X
    for i in range(len(weights)):
        h=tf.add(tf.matmul(h,weights[i]),biases[i])
        h=tf.nn.relu(h)
    return h

output_layer=forward_pass(X,weights,biases)
cost=tf.reduce_mean(tf.squared_difference(output_layer,Y),1)
cost=tf.reduce_sum(cost)
optimizer=tf.train.AdamOptimizer(learning_rate=0.01).minimize(cost)


with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    #train the network
    for i in range(epochs):
        idx=np.arange(len(train_x))
        np.random.shuffle(idx)
        for j in range(len(train_x)//batch_size):
            cur_idx=idx[batch_size*j:batch_size*(j+1)]
            sess.run(optimizer,feed_dict={X:train_x[cur_idx],Y:train_y[cur_idx]})
        #current_cost=sess.run(cost,feed_dict={X:train_x,Y:train_y})
        #print(current_cost)
    #apply the network on the test data
    test_x=np.linspace(-30,30,300)
    network_output=sess.run(output_layer,feed_dict={X:test_x.reshape(-1,1)})    



plt.plot(test_x,test_x**2,color='r',label='y=x^2')
plt.plot(test_x,network_output,color='b',label='network output')
plt.legend(loc='center')
plt.show()

【讨论】:

  • 非常感谢。对于像我这样的业余爱好者来说,这很有帮助。您能帮助我以最简单的方式保存和加载此模型以进行预测吗?
猜你喜欢
  • 2017-02-04
  • 1970-01-01
  • 2017-12-02
  • 1970-01-01
  • 2016-07-28
  • 2012-05-06
  • 2017-12-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多