将具有ReLU的神经网络拟合到多项式函数

时间:2019-12-06 10:16:00

标签: neural-network julia relu flux-machine-learning

出于好奇,我试图将具有校正线性单位的神经网络拟合到多项式函数。 例如,我想看看神经网络想出函数f(x) = x^2 + x的近似是多么容易(或困难)。以下代码应该可以做到,但是似乎什么也没学。当我跑步时

using Base.Iterators: repeated
ENV["JULIA_CUDA_SILENT"] = true
using Flux
using Flux: throttle
using Random

f(x) = x^2 + x
x_train = shuffle(1:1000)
y_train = f.(x_train)
x_train = hcat(x_train...)

m = Chain(
    Dense(1, 45, relu),
    Dense(45, 45, relu),
    Dense(45, 1),
    softmax
)

function loss(x, y) 
    Flux.mse(m(x), y)
end

evalcb = () -> @show(loss(x_train, y_train))
opt = ADAM()

@show loss(x_train, y_train)

dataset = repeated((x_train, y_train), 50)

Flux.train!(loss, params(m), dataset, opt, cb = throttle(evalcb, 10))

println("Training finished")

@show m([20])

它返回

loss(x_train, y_train) = 2.0100101f14
loss(x_train, y_train) = 2.0100101f14
loss(x_train, y_train) = 2.0100101f14
Training finished
m([20]) = Float32[1.0]

这里的所有人都知道如何使网络适合f(x) = x^2 + x

1 个答案:

答案 0 :(得分:2)

您的试用中似乎有几处错误,这主要与您使用优化器和处理输入的方式有关– Julia或Flux没有错。提供的解决方案确实可以学习,但绝非最佳选择。

  • 在回归问题上激活softmax输出是没有意义的。 Softmax用于分类问题,其中模型的输出表示概率,因此应在区间(0,1)上。很明显,您的多项式的值超出此间隔。通常在此类回归问题中具有线性输出激活。这意味着在Flux中,不应在输出层上定义任何输出激活。
  • 数据的形状很重要。 train!loss(d...)计算梯度,其中d是您的data中的一批。在您的情况下,一个小批量包含1000个样品,并且同一批次重复50次。神经网络通常以较小的批次大小但较大的样本集进行训练。在我提供的代码中,所有批次均包含不同的数据。
  • 通常,对于训练神经网络,建议对输入进行标准化。您输入的值从1到1000。我的示例应用了简单的线性变换,以使输入数据处于正确的范围内。
  • 规范化也可以应用于输出。如果输出很大,这会导致(太大)的梯度和权重更新。另一种方法是大大降低学习率。
using Flux
using Flux: @epochs
using Random

normalize(x) = x/1000
function generate_data(n)
    f(x) = x^2 + x
    xs = reduce(hcat, rand(n)*1000)
    ys = f.(xs)
    (normalize(xs), normalize(ys))
end
batch_size = 32
num_batches = 10000
data_train = Iterators.repeated(generate_data(batch_size), num_batches)
data_test = generate_data(100)


model = Chain(Dense(1,40, relu), Dense(40,40, relu), Dense(40, 1))
loss(x,y) = Flux.mse(model(x), y)

opt = ADAM()
ps = Flux.params(model)
Flux.train!(loss, ps, data_train, opt , cb = () -> @show loss(data_test...))