我正在研究神经网络系统,以执行SED fitting作为西澳大利亚大学学生项目的一部分。
我通过称为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值附近,即使这些值非常不正确。
考虑到所有这一切,是什么原因导致像我这样的网络产生这些类似于平均值的输出?
我可以尝试采取哪些措施来解决此问题并创建某种网络,以实际生成正确的输出?
答案 0 :(得分:5)
除了CAFEBABE的评论之外,我只是想对这个具体问题提出一些看法:
42个输入功能并不是很多功能。不是你必须修复的东西,但它意味着你想拥有更宽的隐藏层(即更多的节点),以帮助分类/标签的可分离性。此外,20K观测并不是一个大型数据集。如果你能获得更多数据,你应该。这几乎总是如此。
如果您有最小/最大标准化的具体原因,那么忽略这一点,但您可以考虑批量标准化您的输入,这有助于网络准确预测的能力。这基本上允许激活使输入更接近函数的中间而不是结束。
您应该尝试更多优化。例如:
rmsprop
或adam
,或学习费率。 尝试一些不同的激活功能。最近的研究包括:ReLU,ELU,PReLU,SReLU。所有可用的keras。
还尝试包括一些正则化,以避免过度拟合。查看Dropout,或L2 / L1
虽然拥有更深层次的模型(即更多层)确实有帮助,但将数据维度从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))
祝你好运!