Переоснащение и утечка данных в тензорном потоке / нейронной сети керас - PullRequest
4 голосов
/ 22 января 2020

Доброе утро, я новичок в машинном обучении и нейронных сетях. Я пытаюсь построить полностью подключенную нейронную сеть для решения проблемы регрессии. Набор данных состоит из 18 объектов и 1 метки, и все они являются физическими величинами.

Вы можете найти код ниже. Я загружаю рисунок эволюции функции потерь по эпохам (вы можете найти ее ниже). Я не уверен, есть ли переоснащение. Кто-то может объяснить мне, почему есть или нет переоснащение?

import pandas as pd
import numpy as np

from sklearn.ensemble import RandomForestRegressor
from sklearn.feature_selection import SelectFromModel
from sklearn import preprocessing

from sklearn.model_selection import train_test_split

from matplotlib import pyplot as plt

import keras
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, BatchNormalization
from tensorflow.keras.callbacks import EarlyStopping
from keras import optimizers
from sklearn.metrics import r2_score
from keras import regularizers
from keras import backend
from tensorflow.keras import regularizers
from keras.regularizers import l2

# =============================================================================
# Scelgo il test size
# =============================================================================
test_size = 0.2

dataset = pd.read_csv('DataSet.csv', decimal=',', delimiter = ";")

label = dataset.iloc[:,-1]
features = dataset.drop(columns = ['Label'])

y_max_pre_normalize = max(label)
y_min_pre_normalize = min(label)

def denormalize(y):
    final_value = y*(y_max_pre_normalize-y_min_pre_normalize)+y_min_pre_normalize
    return final_value

# =============================================================================
# Split
# =============================================================================

X_train1, X_test1, y_train1, y_test1 = train_test_split(features, label, test_size = test_size, shuffle = True)

y_test2 = y_test1.to_frame()
y_train2 = y_train1.to_frame()

# =============================================================================
# Normalizzo
# =============================================================================
scaler1 = preprocessing.MinMaxScaler()
scaler2 = preprocessing.MinMaxScaler()
X_train = scaler1.fit_transform(X_train1)
X_test = scaler2.fit_transform(X_test1)


scaler3 = preprocessing.MinMaxScaler()
scaler4 = preprocessing.MinMaxScaler()
y_train = scaler3.fit_transform(y_train2)
y_test = scaler4.fit_transform(y_test2)



# =============================================================================
# Creo la rete
# =============================================================================
optimizer = tf.keras.optimizers.Adam(lr=0.001)
model = Sequential()

model.add(Dense(60, input_shape = (X_train.shape[1],), activation = 'relu',kernel_initializer='glorot_uniform'))
model.add(Dropout(0.2))
model.add(Dense(60, activation = 'relu',kernel_initializer='glorot_uniform'))
model.add(Dropout(0.2))
model.add(Dense(60, activation = 'relu',kernel_initializer='glorot_uniform'))

model.add(Dense(1,activation = 'linear',kernel_initializer='glorot_uniform'))

model.compile(loss = 'mse', optimizer = optimizer, metrics = ['mse'])

history = model.fit(X_train, y_train, epochs = 100,
                    validation_split = 0.1, shuffle=True, batch_size=250
                    )

history_dict = history.history

loss_values = history_dict['loss']
val_loss_values = history_dict['val_loss']

y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)

y_train_pred = denormalize(y_train_pred)
y_test_pred = denormalize(y_test_pred)


plt.figure()
plt.plot((y_test1),(y_test_pred),'.', color='darkviolet', alpha=1, marker='o', markersize = 2, markeredgecolor = 'black', markeredgewidth = 0.1)
plt.plot((np.array((-0.1,7))),(np.array((-0.1,7))),'-', color='magenta')
plt.xlabel('True')
plt.ylabel('Predicted')
plt.title('Test')

plt.figure()
plt.plot((y_train1),(y_train_pred),'.', color='darkviolet', alpha=1, marker='o', markersize = 2, markeredgecolor = 'black', markeredgewidth = 0.1)
plt.plot((np.array((-0.1,7))),(np.array((-0.1,7))),'-', color='magenta')
plt.xlabel('True')
plt.ylabel('Predicted')
plt.title('Train')

plt.figure()
plt.plot(loss_values,'b',label = 'training loss')
plt.plot(val_loss_values,'r',label = 'val training loss')
plt.xlabel('Epochs')
plt.ylabel('Loss Function')
plt.legend()

print("\n\nThe R2 score on the test set is:\t{:0.3f}".format(r2_score(y_test_pred, y_test1)))

print("The R2 score on the train set is:\t{:0.3f}".format(r2_score(y_train_pred, y_train1)))
from sklearn import metrics

# Measure MSE error.  
score = metrics.mean_squared_error(y_test_pred,y_test1)
print("\n\nFinal score test (MSE): %0.4f" %(score))
score1 = metrics.mean_squared_error(y_train_pred,y_train1)
print("Final score train (MSE): %0.4f" %(score1))
score2 = np.sqrt(metrics.mean_squared_error(y_test_pred,y_test1))
print(f"Final score test (RMSE): %0.4f" %(score2))
score3 = np.sqrt(metrics.mean_squared_error(y_train_pred,y_train1))
print(f"Final score train (RMSE): %0.4f" %(score3))

enter image description here

РЕДАКТИРОВАТЬ:

I пробовал также сделать важные функции и вызвать n_epochs, вот результаты:

Важность функции:

enter image description here

Нет импорта функций:

enter image description here

Ответы [ 3 ]

6 голосов
/ 22 января 2020

Похоже, у вас нет переобучения! Ваши кривые обучения и проверки сходятся вместе и сходятся. Самым ярким признаком переоснащения, которое вы могли бы получить, было бы отклонение между этими двумя кривыми, что-то вроде этого: overfitting ecample

Поскольку ваши две кривые нисходящие и не расходятся, это указывает на то, что Тренировка NN полезна.

ОДНАКО ! Ваша кривая проверки подозрительно ниже кривой обучения. Это намекает на возможную утечку данных (данные поезда и теста были как-то смешаны). Больше информации о коротком блоге . В общем, вам следует разделить данные перед любой другой предварительной обработкой (нормализация, увеличение, перетасовка и т. Д. c ...) .

Другими причинами этого может быть некий тип регуляризации (отсев, BN и т. Д. c ..), который активен при вычислении точности обучения и деактивируется при вычислении точности валидации / теста.

1 голос
/ 22 января 2020

Нет, это не переобучение, так как ваши потери в проверке не увеличиваются.

Тем не менее, на вашем месте я был бы немного скептически настроен. Попробуйте обучить вашу модель еще большему количеству эпох и остерегайтесь потери проверки.

Что вам определенно следует сделать, это соблюдать следующее: - есть ли дубликаты или почти дубликаты в данных (создает утечку информации из поезда в разделение проверки теста) - есть ли функции, которые причинно связаны с целевая переменная

Редактировать:

Обычно в реальном наборе данных имеется некоторый случайный компонент, так что правила, которые соблюдаются в данных поезда, не на 100% верны для данных проверки. Ваш график показывает, что потери при проверке еще больше уменьшаются при уменьшении потерь в поездах. Обычно вы попадаете в какой-то момент обучения, когда правила, которые вы соблюдаете в данных поезда, слишком конкретны c, чтобы описать все данные. Вот когда начинается переоснащение. Следовательно, странно, что ваши потери при проверке больше не увеличиваются.

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

Давайте предположим, что существует некоторая утечка информации из набора поездов в набор проверки (например, посредством дублированных записей). Ваша модель изменит веса, чтобы описать очень специфические c правила. При применении вашей модели к новым данным она потерпит неудачу, поскольку наблюдаемые связи на самом деле не являются общими. Другая распространенная проблема с данными заключается в том, что признаки могут иметь обратную причинность.

То, что потери при проверке, как правило, ниже, чем ошибка поезда, вероятно, зависит от отсева и регуляризации, поскольку они применяются во время обучения, но не для прогнозирования / тестирования.

Я акцентировал внимание на этом, потому что крошечная ошибка или ошибка в данных может «испортить» всю вашу модель.

1 голос
/ 22 января 2020

Переоснащение происходит, когда модель не обобщает другие данные, кроме данных обучения. Когда это произойдет, у вас будет очень (!) Низкая потеря при обучении, но большая потеря при проверке. Вы можете думать об этом следующим образом: если у вас есть N баллов, вы можете подобрать полином N-1 так, чтобы у вас был нулевой тренировочный урон (ваша модель отлично бьет все ваши тренировочные баллы). Но если вы примените эту модель к некоторым другим данным, она, скорее всего, приведет к очень высокой ошибке (см. Изображение ниже). Здесь красная линия - наша модель, а зеленая - истинные данные (+ шум), и вы можете видеть на последнем рисунке, что мы получаем нулевую ошибку обучения. Во-первых, наша модель слишком проста (высокая последовательность / большая ошибка проверки), вторая - хорошая (низкая последовательность / низкая оценка), третья и последняя слишком сложные, то есть переоснащение (очень низкая последовательность / высокая ошибка проверки).

Нейронная сеть может работать таким же образом, поэтому, посмотрев на ваше обучение и ошибку проверки, вы можете сделать вывод, подходит ли она или нет

overfitting

...