Я пытаюсь создать NN с Keras и Tensorflow, чтобы предсказать окончательную позицию на графике песни, учитывая набор из 5 функций.
Поработав с ним в течение нескольких дней, я понял, что, хотя моя MAE снижалась, это произошло потому, что модель только что научилась предсказывать среднее значение моего тренировочного набора для всех входных данных, и это было оптимальным решением. (Это показано на диаграмме рассеяния ниже)
Это случайная выборка из 50 точек данных из моего тестового набора в сравнении с тем, что, по мнению сети, должно быть
Сначала я понял, что это, вероятно, потому, что моя сеть была слишком сложной. У меня был один входной слой с формой (5,)
и один узел в выходном слое, но затем 3 скрытых слоя с более чем 32 узлами в каждом.
Затем я удалил лишние слои и переместился в один скрытый слой с парой узлов, как показано здесь:
self.model = keras.Sequential([
keras.layers.Dense(4,
activation='relu',
input_dim=num_features,
kernel_initializer='random_uniform',
bias_initializer='random_uniform'
),
keras.layers.Dense(1)
])
Обучение этому с оптимизатором градиентного спуска все еще приводит к тому же прогнозу, который делается все время.
Тогда мне пришло в голову, что, возможно, настоящая проблема, которую я пытаюсь решить, недостаточно сложна для сети, что, возможно, она линейно разделима. Так как это лучше отреагировало бы на отсутствие скрытого слоя вообще, просто на регулярной линейной регрессии, я попробовал это. Я изменил свою модель на:
inp = keras.Input(shape=(num_features,))
out = keras.layers.Dense(1, activation='relu')(inp)
self.model = keras.Model(inp,out)
Это тоже ничего не изменило. Мое МАЕ, прогнозируемое значение у всех одинаковое.
Я пробовал так много разных вещей, различные сочетания функций оптимизации, скорости обучения, конфигурации сети, и ничто не может помочь. Я почти уверен, что данные хорошие, но на всякий случай я привел их пример.
chartposition,tagcount,dow,artistscore,timeinchart,finalpos
121,3925,5,35128,7,227
131,4453,3,85545,25,130
69,2583,4,17594,24,523
145,1165,3,292874,151,187
96,1679,5,102593,111,540
134,3494,5,1252058,37,370
6,34895,7,6824048,22,5
Образец моего набора данных, finalpos - это значение, которое я пытаюсь предсказать. Набор данных содержит ~ 40 000 записей, разделение 80/20 - обучение / тестирование
def __init__(self, validation_split, num_features, should_log):
self.should_log = should_log
self.validation_split = validation_split
inp = keras.Input(shape=(num_features,))
out = keras.layers.Dense(1, activation='relu')(inp)
self.model = keras.Model(inp,out)
optimizer = tf.train.GradientDescentOptimizer(0.01)
self.model.compile(loss='mae',
optimizer=optimizer,
metrics=['mae'])
def train(self, data, labels, plot=False):
early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=20)
history = self.model.fit(data,
labels,
epochs=self.epochs,
validation_split=self.validation_split,
verbose=0,
callbacks = [PrintDot(), early_stop])
if plot: self.plot_history(history)
Весь код, относящийся к созданию и обучению сети
def normalise_dataset(df, mini, maxi):
return (df - mini)/(maxi-mini)
Нормализация входных данных. Мои данные тестирования и обучения нормализованы до максимума и минимума набора тестирования
График моих потерь в сравнении с кривыми проверки с сетью из одного скрытого слоя с адамоптимизатором, скорость обучения 0,01
Тот же график, но с линейной регрессией и оптимизатором градиентного спуска.