首页 文章

Autoencoder不学习身份功能

提问于
浏览
7

我对机器学习有点新意,我想做一个简单的实验来更熟悉神经网络自动编码器:制作一个非常基本的自动编码器来学习身份功能 .

我正在使用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 回答

  • 3

    我相信这个问题可能是时代的数量,也可能是你对X进行初始化的方式 . 我用我的X运行你的代码100个纪元并打印出权重的argmax()和最大值,它真的很接近身份功能 .

    我正在添加我使用的代码段

    from keras.models import Sequential
    from keras.layers import Dense
    import numpy as np
    import random
    import pandas as pd
    
    X = np.array([[random.random() for r in xrange(84)] for i in xrange(1,100000)])
    model = Sequential([Dense(84, input_dim=84)], name="layer1")
    model.compile(optimizer='sgd', loss='mean_squared_error')
    model.fit(X, X, nb_epoch=100, batch_size=80, validation_split=0.3)
    
    l_weights = np.round(model.layers[0].get_weights()[0],3)
    
    print l_weights.argmax(axis=0)
    print l_weights.max(axis=0)
    

    我得到了:

    Train on 69999 samples, validate on 30000 samples
    Epoch 1/100
    69999/69999 [==============================] - 1s - loss: 0.2092 - val_loss: 0.1564
    Epoch 2/100
    69999/69999 [==============================] - 1s - loss: 0.1536 - val_loss: 0.1510
    Epoch 3/100
    69999/69999 [==============================] - 1s - loss: 0.1484 - val_loss: 0.1459
    .
    .
    .
    Epoch 98/100
    69999/69999 [==============================] - 1s - loss: 0.0055 - val_loss: 0.0054
    Epoch 99/100
    69999/69999 [==============================] - 1s - loss: 0.0053 - val_loss: 0.0053
    Epoch 100/100
    69999/69999 [==============================] - 1s - loss: 0.0051 - val_loss: 0.0051
    [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83]
    [ 0.85000002  0.85100001  0.79799998  0.80500001  0.82700002  0.81900001
      0.792       0.829       0.81099999  0.80800003  0.84899998  0.829       0.852
      0.79500002  0.84100002  0.81099999  0.792       0.80800003  0.85399997
      0.82999998  0.85100001  0.84500003  0.847       0.79699999  0.81400001
      0.84100002  0.81        0.85100001  0.80599999  0.84500003  0.824
      0.81999999  0.82999998  0.79100001  0.81199998  0.829       0.85600001
      0.84100002  0.792       0.847       0.82499999  0.84500003  0.796
      0.82099998  0.81900001  0.84200001  0.83999997  0.815       0.79500002
      0.85100001  0.83700001  0.85000002  0.79900002  0.84100002  0.79699999
      0.838       0.847       0.84899998  0.83700001  0.80299997  0.85399997
      0.84500003  0.83399999  0.83200002  0.80900002  0.85500002  0.83899999
      0.79900002  0.83399999  0.81        0.79100001  0.81800002  0.82200003
      0.79100001  0.83700001  0.83600003  0.824       0.829       0.82800001
      0.83700001  0.85799998  0.81999999  0.84299999  0.83999997]
    

    当我只使用5个数字作为输入并打印实际重量时,我得到了这个:

    array([[ 1.,  0., -0.,  0.,  0.],
           [ 0.,  1.,  0., -0., -0.],
           [-0.,  0.,  1.,  0.,  0.],
           [ 0., -0.,  0.,  1., -0.],
           [ 0., -0.,  0., -0.,  1.]], dtype=float32)
    

相关问题