7

作为西澳大利亚大学学生项目的一部分,我正在开发一个神经网络系统来执行SED 拟合。

我通过称为MAGPHYS的 SED 拟合程序创建了一组大约 20,000 次运行。每次运行都有我们感兴趣的 42 个输入值和 32 个输出值(系统有更多输出,但我们不需要它们)

我一直在尝试使用 Keras 神经网络包,以便创建一个网络来学习此功能。

我当前的网络设计使用 4 个完全互连的隐藏层,每层之间有 30 个连接。每一层都使用 TanH 激活函数。我还有一个 42 维输入层和 32 维输出层,都使用 TanH 激活,总共 6 层。

model = Sequential()
loss = 'mse'
optimiser = SGD(lr=0.01, momentum=0.0, decay=0, nesterov=True)

model.add(Dense(output_dim=30, input_dim=42, init='glorot_uniform', activation='tanh'))

for i in range(0, 4):
    model.add(Dense(output_dim=30, input_dim=30, init='glorot_uniform', activation='tanh'))

model.add(Dense(output_dim=32, input_dim=30, init='glorot_uniform', activation='tanh'))
model.compile(loss=loss, optimizer=optimiser)

我一直在使用输入和输出数据的最小/最大归一化来压缩 0 到 1 之间的所有值。我正在使用随机梯度下降优化器,并且我已经尝试了各种损失函数,例如均方误差、均值绝对误差、平均绝对百分比误差等。

主要问题是,无论我如何构建我的网络,它只会生成大约所有训练输出值的平均值的输出值。它似乎并没有通过网络实际上正确地学习了该函数,它只是生成了平均值附近的值。更糟糕的是,我尝试过的一些网络设计,尤其是那些使用线性激活函数的网络设计,只会生成输出值的平均值,并且根本不会变化。

示例(对于 32 个输出之一):

Output   Correct
9.42609868658  =   9.647
9.26345946681  =   9.487
9.43403506231  =   9.522
9.35685760748  =   9.792
9.20564885211  =   9.287
9.39240577382  =   8.002

请注意所有输出都在 9.2 - 9.4 值附近,即使这些值非常不正确。

考虑到所有这些,是什么导致像我这样的网络产生这些都在平均水平附近的输出?

我可以尝试什么样的事情来解决这个问题并创建某种网络来实际生成正确的输出?

4

1 回答 1

6

除了 CAFEBABE 的评论之外,我只想对这个特定问题提出一些想法:

  1. 42 个输入功能并不是一大堆可以使用的功能。不是您必须解决的问题,但这意味着您需要更宽的隐藏层(即更多节点),以帮助类/标签的可分离性。此外,20K 的观测数据并不完全是一个大数据集。如果你能得到更多的数据,你应该。几乎总是如此。

  2. 如果您有最小/最大归一化的具体原因,则忽略这一点,但您可以考虑对您的输入进行 BatchNormalizing,这往往有助于网络准确预测的能力。这实质上允许激活的输入发生在更接近函数的中间,而不是末端。

  3. 您应该对优化进行更多试验。例如:

    • 您要进行多少个 epoch 的训练?仅通过一次数据是不够的。
    • 尝试不同的优化器,例如rmsproporadam或学习率。
    • 你也可以使用学习率调度器,就像这里一样,你可以在各个时期降低学习率,这样你就不会超过损失函数的最小值。
  4. 尝试一些不同的激活函数。最近的研究包括:ReLU、ELU、PReLU、SReLU。都在 keras 中可用。

  5. 还尝试包括一些正则化,以避免过度拟合。查看 Dropout 或 L2/L1

  6. 虽然拥有更深的模型(即更多层)通常会有所帮助,但将数据维度从 42 个特征减少到 30 个,可能会损害您分离数据的能力。尝试更大的,比如 100、500 或 1000。

您可以尝试的示例模型如下:

# imports 
from sklearn.cross_validation import train_test_split
from keras.models import Sequential
from keras.layers.core import Dense, Activation, Dropout
from keras.layers.normalization import BatchNormalization
from keras.layers.advanced_activations import ELU     

# data shapes
n_obs, n_feat = 20000, 42
n_hidden = 500 # play with this, bigger tends to give better separability
n_class = 32

# instantiate model
model = Sequential()

# first layer --- input
model.add(Dense(input_dim = n_feat, output_dim = n_hidden))
model.add(BatchNormalization())
model.add(ELU())
model.add(Dropout(p=0.2)) # means that 20% of the nodes are turned off, randomly

# second layer --- hidden
model.add(Dense(input_dim = n_hidden, output_dim = n_hidden))
model.add(BatchNormalization())
model.add(ELU())
model.add(Dropout(p=0.2))

# third layer --- output
model.add(Dense(input_dim = n_hidden, output_dim = n_class))
model.add(BatchNormalization())
model.add(Activation('softmax'))

# configure optimization
model.compile(optimizer = 'rmsprop', loss = 'categorical_crossentropy', metrics = ['accuracy'])

# split your data, so you test it on validation data
X_train, X_test, Y_train, Y_test = train_test_split(data, targets)

# train your model
model.fit(X_train, Y_train, validation_data = (X_test, Y_test))

祝你好运!

于 2016-07-15T22:35:18.950 回答