我正在使用 Julia 的 Flux 库来学习神经网络。根据train!
(其中train!
需要参数(loss, params, data, opt)
)的文档:
对于 data 中的每个数据点 d,通过反向传播计算相对于 params 的损失梯度并调用优化器 opt。
(参见来源train!
:https ://github.com/FluxML/Flux.jl/blob/master/src/optimise/train.jl )
对于基于传统的神经网络Dense
——比方说具有一维输入和输出,即具有一个特征——这很容易理解。中的每个元素data
都是一对单个数字,是一维输入/输出值的独立样本。 train!
一次对每对一维样本进行一个前向和反向传播。在此过程中,loss
函数会在每个样本上进行评估。(我有这个权利吗?)
我的问题是:这如何扩展到循环神经网络?以具有一维(即一个特征)输入和输出的 RNN 为例。似乎在如何构造输入和输出数据方面存在一些歧义,并且结果会根据结构而变化。举个例子:
x = [[1], [2], [3]]
y = [4, 5, 6]
data = zip(x, y)
m = RNN(1, 1)
opt = Descent()
loss(x, y) = sum((Flux.stack(m.(x), 1) .- y) .^ 2)
train!(loss, params(m), data, opt)
(loss
函数取自:https ://github.com/FluxML/Flux.jl/blob/master/docs/src/models/recurrence.md )
在此示例中,当train!
循环遍历每个样本 ( for d in data
) 时, 的每个值都是来自和d
的一对单个值,例如。 基于这些单一值进行评估。这与本案相同。x
y
([1], 4)
loss
Dense
另一方面,考虑:
x = [[[1], [2], [3]]]
y = [[4, 5, 6]]
m = RNN(1, 1)
opt = Descent()
loss(x, y) = sum((Flux.stack(m.(x), 1) .- y) .^ 2)
train!(loss, params(m), zip(x, y), opt)
请注意,这里唯一的区别是x
和y
嵌套在一对额外的方括号中。结果只有一个d in data
,它是一对序列:([[1], [2], [3]], [4, 5, 6])
。 loss
可以在这个版本的 上进行评估d
,并且它返回一个 1-d 值,这是训练所需的。但是返回的值loss
与前一个案例的三个结果中的任何一个都不同,因此训练过程结果不同。
关键是这两种结构在某种意义上都是有效的,loss
并且可以train!
毫无错误地处理它们。从概念上讲,我可以论证两种结构都是正确的。但结果不同,我认为只有一种方法是正确的。换句话说,对于训练一个 RNN,每个应该d in data
是一个完整的序列,还是一个序列中的单个元素?