Потери нейронной сети перестают снижаться

Я тренирую модель NN, и через некоторое время убыток перестает снижаться. Хотя убыток действительно уменьшается, но этого недостаточно, чтобы делать хорошие прогнозы, и я пробовал несколько вещей, но ни один из них не имеет большого значения.

Все мои попытки заканчивались поражением против. шаги, похожие на рисунок ниже, только шаги, необходимые для сглаживания, могут отличаться:

Потери нейронной сети перестают снижаться

Вот то, что я уже пробовал:

  1. Снижение скорости обучения. Я увеличил скорость обучения от 1e-3 до 1e-8, и все они достигли одинакового значения потерь. Теперь в моем коде я даже использую tf.train.exponential_decay (), поэтому скорость обучения снижается по шагам, но это не помогает.

  2. Изменение количества слоев (я пробовал от 2 до 4 скрытых слоев) и узлов каждого слоя. Не помогает также уменьшить окончательную величину потерь.

  3. Изменение размера партии. Это немного помогло. Я сместил размер партии с 20000 до 1 и выбрал тот, который может достичь наименьшего значения потерь быстрее всего, а именно размер партии 1000. Но опять же, наименьшее значение потерь - это то, которое я показываю цифрой, которая недостаточно.

  4. Изменение коэффициента регуляризации («бета» в коде). На самом деле это не имеет значения, поскольку в моем случае проблема переоснащения не возникает. Это не подходит.

Вот мой код:

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import with_statement

#import scipy
from sklearn import preprocessing
from pdb import set_trace as bp

import argparse
import sys
import numpy as np
import csv

import pandas as pd
import tensorflow as tf


beta = 0.001
training_batch_size = 1000

train_predict_file = "./Data/training_data_3Param.csv"
CV_file = "./Data/CV_data_3Param.csv"
result_file = "hyper_param_result_LRdecay.txt"


def model_fn(features, labels, mode, params):
  """Model function for Estimator."""

  first_hidden_layer = tf.layers.dense(features["x"], 100, activation=tf.nn.leaky_relu)

  second_hidden_layer = tf.layers.dense(first_hidden_layer, 100, activation=tf.nn.leaky_relu)

  third_hidden_layer = tf.layers.dense(second_hidden_layer,100, activation=tf.nn.leaky_relu)

  fourth_hidden_layer = tf.layers.dense(third_hidden_layer, 100, activation=tf.nn.leaky_relu)

  output_layer = tf.layers.dense(fourth_hidden_layer, 3)

  predictions = tf.reshape(output_layer, [-1,3])
  if labels != None:
      labels = tf.reshape(labels, [-1,3])

  var = [v for v in tf.trainable_variables() if "kernel" in v.name]

  # Provide an estimator spec for `ModeKeys.PREDICT`.
  if mode == tf.estimator.ModeKeys.PREDICT:
    return tf.estimator.EstimatorSpec(
        mode=mode,
        predictions = {"par": predictions})

  # Calculate loss using mean squared error
  regularizer = tf.nn.l2_loss(var[0]) + tf.nn.l2_loss(var[1]) + tf.nn.l2_loss(var[2])

  loss = tf.losses.mean_squared_error(labels, predictions)

  batch = tf.Variable(0)

  learning_rate = tf.train.exponential_decay(
          0.001, #base Learning Rate
          batch * training_batch_size, 
          1e6, #decay step
          0.96, #decay rate
          staircase=True)

  optimizer = tf.train.GradientDescentOptimizer(
      learning_rate=learning_rate)

  train_op = optimizer.minimize( 
      loss=(loss+(beta/2)*regularizer) , global_step=tf.train.get_global_step())

  # Calculate root mean squared error as additional eval metric
  eval_metric_ops = {
      "rmse": tf.metrics.root_mean_squared_error(
          tf.cast(labels, tf.float32), predictions)
  }

  # Provide an estimator spec for `ModeKeys.EVAL` and `ModeKeys.TRAIN` modes.
  return tf.estimator.EstimatorSpec(
      mode=mode,
      loss=loss,
      train_op=train_op,
      eval_metric_ops=eval_metric_ops)


def main(unused_argv):

  train_predict_data_interim = []
  CV_data_interim = []  
  with open(train_predict_file) as f:
      csvreader = csv.reader(f)
      for row in csvreader:
          train_predict_data_interim.append(row)  

  with open(CV_file) as f:
      csvreader = csv.reader(f)
      for row in csvreader:
          CV_data_interim.append(row)  


  train_predict_data_interim = pd.DataFrame(train_predict_data_interim)
  CV_data_interim = pd.DataFrame(CV_data_interim)
  min_max_scaler = preprocessing.MinMaxScaler(feature_range=(-1,1))

  train_predict_data_transformed = min_max_scaler.fit_transform(train_predict_data_interim) 
  CV_data_transformed = min_max_scaler.fit_transform(CV_data_interim)

  train_predict_data_transformed = pd.DataFrame(train_predict_data_transformed)
  CV_data_transformed = pd.DataFrame(CV_data_transformed)

  train_data_interim = train_predict_data_transformed.sample(frac=0.9996875)
  predict_data_interim = train_predict_data_transformed.loc[~train_predict_data_transformed.index.isin(train_data_interim.index), :]

  a = len(train_predict_data_transformed.columns)
  train_labels_interim = train_data_interim.iloc[:, a-3:a] 
  train_features_interim = train_data_interim.iloc[:, :a-3] 
  train_features_numpy = np.asarray(train_features_interim, dtype=np.float32)
  train_labels_numpy = np.asarray(train_labels_interim, dtype=np.float32)


  # Instantiate Estimator
  nn = tf.estimator.Estimator(model_fn=model_fn, model_dir = "/tmp/nmos_3Param_LRdecay_bs%s_beta%s" %(training_batch_size, beta))
  train_input_fn = tf.estimator.inputs.numpy_input_fn(
      x = {"x": train_features_numpy},
      y=train_labels_numpy,
      batch_size = training_batch_size,
      num_epochs= None,
      shuffle=True)

  # Train
  nn.train(input_fn=train_input_fn, steps=448000)

  test_features_interim = CV_data_transformed.iloc[:, :a-3]
  test_features_numpy = np.asarray(test_features_interim, dtype=np.float32)

  test_labels_interim = CV_data_transformed.iloc[:, a-3:a]
  test_labels_numpy = np.asarray(test_labels_interim, dtype=np.float32)

  # Score accuracy
  test_input_fn = tf.estimator.inputs.numpy_input_fn(
      x = {"x": test_features_numpy},
      y=test_labels_numpy,
      batch_size = 1,
      num_epochs= 1,
      shuffle=False)

  ev = nn.evaluate(input_fn=test_input_fn)
  print("Loss: %s" % ev["loss"])
  print("Root Mean Squared Error: %s" % ev["rmse"])


  prediction_features_interim = predict_data_interim.iloc[:, :a-3]
  prediction_features_numpy = np.asarray(prediction_features_interim, dtype=np.float32)
  prediction_labels_interim = predict_data_interim.iloc[:, a-3:a]
  prediction_labels_numpy = np.asarray(prediction_labels_interim, dtype=np.float32)

  print ('-' * 30, 'prediction_labels_numpy', '-' * 30)
  print (prediction_labels_numpy)
  prediction_lables_str = np.char.mod('%f',prediction_labels_numpy)

  with open(result_file,'a') as f:
      f.write('-' * 50)
      f.write('\n')
      f.write("batch_size = %s beta = %s\n" %(training_batch_size, beta))
      f.write("Loss: %s\n" % ev["loss"])
      f.write("Root Mean Squared Error: %s\n" % ev["rmse"])
      f.write("%s\n" %(prediction_lables_str))

  # Print out predictions
  predict_input_fn = tf.estimator.inputs.numpy_input_fn(
      x= {"x": prediction_features_numpy},
      num_epochs=1,
      batch_size = 1,
      shuffle=False)
  predictions = nn.predict(input_fn=predict_input_fn)#, yield_single_examples=False)
  for i, p in enumerate(predictions):
    print("Prediction %s: %s" % (i + 1, p["par"]))
    with open(result_file,'a') as f:
        f.write("Prediction %s: %s \n" % (i + 1, p["par"]))




if __name__ == '__main__':
  tf.logging.set_verbosity(tf.logging.INFO)
  parser = argparse.ArgumentParser()
  parser.register("type", "bool", lambda v: v.lower() == "true")
  FLAGS, unparsed = parser.parse_known_args()
  tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)

Большая часть main () нормализует данные в диапазоне (-1,1), как данные обучения, так и данные перекрестной проверки.

Необработанные данные обучения выглядят так:

Потери нейронной сети перестают снижаться

Чтобы быть более наглядным с сюжетом, я рисую данные обучения (функции): Потери нейронной сети перестают снижаться

Обычно одна строка данных представляет собой линию на графике. Первые 65 столбцов - это функции, а последние три столбца данных - это метки, которые не отображаются. Итак, это случай регрессии NN с 65 входами и 3 выходами.

Я все еще могу попробовать что-нибудь еще, например:

  1. Используйте разные функции активации.
  2. Я не думаю, что увеличение количества тренировочных наборов сработает, поскольку потеря CV похожа на ошибку тренировки, но я могу попробовать.
  3. Пересекаются ли признаки (например, умножаются признаки 1 и 2 и т. д.)?

Но я бы с радостью попросил некоторых экспертов взглянуть на этот случай, и, возможно, мне здесь не хватает чего-то очевидного. Пожалуйста, поделитесь своими мыслями, и я ценю любые обсуждения. Спасибо!

Потеря означает потерю тренировки или потерю теста?

Denziloe 12.09.2018 00:30

Попробуйте заменить GradientDescentOptimizer на AdamOptimizer. Начните со скорости обучения по умолчанию и посмотрите, добьетесь ли вы лучших результатов.

Mad Wombat 12.09.2018 00:34

См. stats.stackexchange.com/questions/352036/… (я все же просил закрыть вопрос, это ОТ).

catastrophic-failure 12.09.2018 00:35

@Denziloe, здесь я имею в виду потерю тренировок. Потеря при испытании (потеря CV) очень похожа на потерю поезда, когда потеря поезда выравнивается.

yuonger741 12.09.2018 01:07

@ catastrophic-failure Что означает ОТ?

yuonger741 12.09.2018 01:12

Это означает не по теме, т.е. не соответствует размеру сайта.

catastrophic-failure 12.09.2018 01:16

Довольно сложно взглянуть на ваш код и дать вам четкую причину, по которой ваша сеть не работает. Как правило, вы должны сначала убедиться, что каждая часть вашей нейронной сети делает то, что должна делать. Часто, когда я обнаруживаю, что нейронная сеть «застревает», или потери расходятся, или происходит что-то напуганное, это происходит потому, что я каким-то образом испортил этап ввода данных. Например, если я ввожу горячие векторы, я, возможно, забыл обнулять их после каждой партии. Убедившись, что все части работают должным образом, займитесь настройкой гиперпараметров.

enumaris 12.09.2018 01:51

@enumaris, я действительно проверил структуру, обучив 65 функций одной метке, и она работала очень хорошо (как потери обучения, так и потери CV довольно низкие).

yuonger741 12.09.2018 02:19
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
8
608
0

Другие вопросы по теме