平方(x ^ 2)逼近的神经网络

Ame*_*eel 7 python machine-learning neural-network keras tensorflow

我是TensorFlow和数据科学的新手。我做了一个简单的模块,应该弄清楚输入和输出数字之间的关系。在这种情况下,x和x平方。Python中的代码:

import numpy as np
import tensorflow as tf

# TensorFlow only log error messages.
tf.logging.set_verbosity(tf.logging.ERROR)

features = np.array([-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,
                    9, 10], dtype = float)
labels = np.array([100, 81, 64, 49, 36, 25, 16, 9, 4, 1, 0, 1, 4, 9, 16, 25, 36, 49, 64,
                    81, 100], dtype = float)

model = tf.keras.Sequential([
    tf.keras.layers.Dense(units = 1, input_shape = [1])
])

model.compile(loss = "mean_squared_error", optimizer = tf.keras.optimizers.Adam(0.0001))
model.fit(features, labels, epochs = 50000, verbose = False)
print(model.predict([4, 11, 20]))
Run Code Online (Sandbox Code Playgroud)

我尝试了不同数量的单元,添加了更多的图层,甚至使用了relu激活功能,但是结果总是错误的。它可以与其他关系(例如x和2x)一起使用。这里有什么问题?

des*_*aut 13

你犯了两个非常基本的错误:

  • 您的超简单模型(具有单个单元的单层网络)根本不符合神经网络的条件,更不用说“深度学习”模型了(因为您的问题已被标记)
  • 同样,你的数据集(只有 20 个样本)也超小

当然可以理解,如果神经网络要解决“简单”的问题,则需要具有一定的复杂性x*x;它们真正闪耀的地方是在接受大型训练数据集时。

尝试解决此类函数近似的方法不仅仅是列出(少数可能的)输入,然后将其连同所需的输出一起输入模型;请记住,神经网络通过示例而不是通过符号推理来学习。而且例子越多越好。在类似情况下,我们通常会生成大量示例,然后将其提供给模型进行训练。

话虽如此,这里是一个相当简单的演示,在 Keras 中x*x使用 10,000 个在 中生成的随机数作为输入来逼近函数 的 3 层神经网络[-50, 50]

import numpy as np
import keras
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam
from keras import regularizers
import matplotlib.pyplot as plt

model = Sequential()
model.add(Dense(8, activation='relu', kernel_regularizer=regularizers.l2(0.001), input_shape = (1,)))
model.add(Dense(8, activation='relu', kernel_regularizer=regularizers.l2(0.001)))
model.add(Dense(1))

model.compile(optimizer=Adam(),loss='mse')

# generate 10,000 random numbers in [-50, 50], along with their squares
x = np.random.random((10000,1))*100-50
y = x**2

# fit the model, keeping 2,000 samples as validation set
hist = model.fit(x,y,validation_split=0.2,
             epochs= 15000,
             batch_size=256)

# check some predictions:
print(model.predict([4, -4, 11, 20, 8, -5]))
# result:
[[ 16.633354]
 [ 15.031291]
 [121.26833 ]
 [397.78638 ]
 [ 65.70035 ]
 [ 27.040245]]
Run Code Online (Sandbox Code Playgroud)

嗯,没那么糟糕!请记住,NN 是函数逼近器:我们不应该期望它们准确地重现函数关系,也不应该“知道”结果4-4应该是相同的。

让我们生成一些新的随机数据[-50,50](请记住,出于所有实际目的,这些是模型中看不见的数据)并将它们与原始数据一起绘制,以获得更一般的图片:

plt.figure(figsize=(14,5))
plt.subplot(1,2,1)
p = np.random.random((1000,1))*100-50 # new random data in [-50, 50]
plt.plot(p,model.predict(p), '.')
plt.xlabel('x')
plt.ylabel('prediction')
plt.title('Predictions on NEW data in [-50,50]')

plt.subplot(1,2,2)
plt.xlabel('x')
plt.ylabel('y')
plt.plot(x,y,'.')
plt.title('Original data')
Run Code Online (Sandbox Code Playgroud)

结果:

在此处输入图片说明

好吧,可以说它确实看起来确实是一个很好的近似值......

您还可以查看此线程以获取正弦近似值。

最后要记住的是,尽管即使使用我们相对简单的模型,我们也确实得到了一个不错的近似值,但我们应该期望的是外推,即良好的外部性能[-50, 50];有关详细信息,请参阅我在深度学习在训练范围之外拟合简单非线性函数方面的答案吗?


ded*_*bed 7

问题是那x*x是与完全不同的野兽a*x

请注意,通常的“神经网络”的作用是:它会堆叠y = f(W*x + b)几次,而不会x与其自身相乘。因此,您将永远无法完美地重建x*x。除非您设置f(x) = x*x或类似。

您可以得到的是训练过程中显示的值范围的近似值(也许只是一点点外推)。无论如何,我建议您使用较小的值范围,这将更容易优化问题。

从哲学上讲:在机器学习中,我认为思考好/不好而不是正确/错误是有用的。尤其是对于回归,除非您拥有精确的模型,否则您将无法获得“正确”的结果。在这种情况下,没有什么可学的。


其实有一些NN架构乘f(x)g(x),最值得注意的是LSTMs公路网络。但即使是这些具有一个或两个f(x)g(s)(由物流乙状结肠或正切)为界,因而不能模拟x*x充分。


由于在评论中表达了一些误解,所以让我强调以下几点:

  1. 可以估算数据。
  2. 为了在任何意义上都做好,您确实需要一个隐藏层
  3. 但是不需要更多数据,尽管如果您覆盖该空间,则该模型将更紧密地拟合,请参见desernaut的答案

例如,这是一个模型的结果,该模型具有10个具有tanh激活的单层隐藏层,该模型由SGD以学习速率1e-3进行了15k次迭代训练,以最小化数据的MSE。五次最佳:

基于OP数据训练的简单NN的性能

这是重现结果的完整代码。不幸的是,我无法在当前环境中安装Keras / TF,但希望PyTorch代码可访问:-)

#!/usr/bin/env python
import torch
import torch.nn as nn
import matplotlib.pyplot as plt

X = torch.tensor([range(-10,11)]).float().view(-1, 1)
Y = X*X

model = nn.Sequential(
    nn.Linear(1, 10),
    nn.Tanh(),
    nn.Linear(10, 1)
)

optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)
loss_func = nn.MSELoss()
for _ in range(15000):
    optimizer.zero_grad()
    pred = model(X)
    loss = loss_func(pred, Y)
    loss.backward()
    optimizer.step()

x = torch.linspace(-12, 12, steps=200).view(-1, 1)
y = model(x)
f = x*x

plt.plot(x.detach().view(-1).numpy(), y.detach().view(-1).numpy(), 'r.', linestyle='None')
plt.plot(x.detach().view(-1).numpy(), f.detach().view(-1).numpy(), 'b')
plt.show()
Run Code Online (Sandbox Code Playgroud)

  • 嗯……这不是首先用 ML 解决的问题;-) 如果学习,请尝试拟合具有不同噪声量的数据。绘制预测图并观察不同模型如何适应不同范围的数据。总体而言:尽管最近大肆宣传,所谓的神经网络只是输入的参数化函数。所以无论如何你都要给他们一些结构。如果输入之间没有乘法,则输入永远不会相乘。如果您知道/怀疑您的任务需要它们成倍增加,请告诉网络这样做。 (2认同)