我对机器学习有点新意,我想做一个简单的实验来更熟悉神经网络自动编码器:制作一个非常基本的自动编码器来学习身份功能 .
我正在使用Keras让生活更轻松,所以我先做了这个以确保它有效:
# Weights are given as [weights, biases], so we give
# the identity matrix for the weights and a vector of zeros for the biases
weights = [np.diag(np.ones(84)), np.zeros(84)]
model = Sequential([Dense(84, input_dim=84, weights=weights)])
model.compile(optimizer='sgd', loss='mean_squared_error')
model.fit(X, X, nb_epoch=10, batch_size=8, validation_split=0.3)
正如预期的那样,在列车和验证数据中损失均为零:
Epoch 1/10
97535/97535 [==============================] - 27s - loss: 0.0000e+00 - val_loss: 0.0000e+00
Epoch 2/10
97535/97535 [==============================] - 28s - loss: 0.0000e+00 - val_loss: 0.0000e+00
然后我尝试做同样的事情,但没有初始化身份函数的权重,期望经过一段时间的训练后,它将学习它 . 它没有 . 我让它在不同的配置中运行200个时代,使用不同的优化器,丢失函数以及添加L1和L2活动正则化器 . 结果各不相同,但我得到的最好的仍然非常糟糕,看起来没有原始数据,只是在同一数值范围内 . 数据只是一些数字在1.1左右振荡 . 我不知道激活层是否对这个问题有意义,我应该使用它吗?
如果一层的“神经网络”无法学习像身份函数这样简单的东西,我怎么能指望它学习更复杂的东西呢?我究竟做错了什么?
编辑
为了获得更好的上下文,这里有一种生成与我正在使用的数据集非常相似的数据集的方法:
X = np.random.normal(1.1090579, 0.0012380764, (139336, 84))
我怀疑值之间的差异可能太小 . 损失函数最终具有不错的值(大约 1e-6
),但结果的精确度不足以使其具有与原始数据类似的形状 . 也许我应该以某种方式扩展/规范它?谢谢你的建议!
更新
最后,正如所建议的那样,问题在于数据集在84个值之间的变化太小,因此得到的预测实际上在绝对值(损失函数)方面相当不错,但是将其与原始数据进行比较,变化是遥远 . 我通过将样本平均值周围的84个值标准化并除以样本的标准偏差来解决它 . 然后我使用原始均值和标准差来对另一端的预测进行非规范化 . 我想这可以通过几种不同的方式完成,但我通过使用在张量上操作的一些Lambda层将这种规范化/非规范化添加到模型本身中来实现 . 这样,所有数据处理都被整合到模型中,这使得它更好地使用 . 如果您想查看实际代码,请与我们联系 .
1 回答
我相信这个问题可能是时代的数量,也可能是你对X进行初始化的方式 . 我用我的X运行你的代码100个纪元并打印出权重的argmax()和最大值,它真的很接近身份功能 .
我正在添加我使用的代码段
我得到了:
当我只使用5个数字作为输入并打印实际重量时,我得到了这个: