нелинейная регрессия нейронной сети - квадратичная функция оценивается неправильно

Я в основном использовал ИНС для классификации и только недавно начал пробовать их для моделирования непрерывных переменных. В качестве упражнения я сгенерировал простой набор пар (x, y), где y = x^2, и попытался обучить ИНС для изучения этой квадратичной функции.

Модель ANN:

Эта ИНС имеет 1 входной узел (т. е. x), 2 скрытых слоя, в каждом из которых по 2 узла, и 1 выходной узел. Все четыре скрытых узла используют нелинейную функцию активации тангенса, а выходной узел не имеет функции активации (поскольку это регрессия).

Данные:

Для обучающего набора я случайным образом сгенерировал 100 чисел между (-20, 20) для x и вычислил y=x^2. Для тестового набора я случайным образом сгенерировал 100 чисел между (-30, 30) для x, а также вычислил y=x^2. Затем я преобразовал все x так, чтобы они были сосредоточены вокруг 0, а их минимум и максимум были приблизительно равны -1,5 и 1,5. Я также преобразовал все y аналогичным образом, но сделал их минимум и максимум равными -0,9 и 0,9. Таким образом, все данные попадают в этот средний диапазон функции активации тангенса, а не выходят за крайние значения.

Проблема:

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

Спасибо!

Прилагается код, который я использовал для всего, и на изображении показан график масштабированного обучения x по сравнению с прогнозируемым y. Как видите, восстанавливается только половина параболы.

import numpy as np, pandas as pd
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
import matplotlib.pyplot as plt

seed = 10
n = 100
X_train = np.random.uniform(-20, 20, n)
Y_train = X_train ** 2
X_test = np.random.uniform(-30, 30, n)
Y_test = X_test ** 2

#### Scale the data

x_cap = max(abs(np.array(list(X_train) + list(X_test))))
y_cap = max(abs(np.array(list(Y_train) + list(Y_test))))
x_mean = np.mean(np.array(list(X_train) + list(X_test)))
y_mean = np.mean(np.array(list(Y_train) + list(Y_test)))

X_train2 = (X_train-x_mean) / x_cap
X_test2 = (X_test-x_mean) / x_cap
Y_train2 = (Y_train-y_mean) / y_cap
Y_test2 = (Y_test-y_mean) / y_cap

X_train2 = X_train2 * (1.5 / max(X_train2))
Y_train2 = Y_train2 * (0.9 / max(Y_train2))

# define base model
def baseline_model1():
# create model
model1 = Sequential()
model1.add(Dense(2, input_dim=1, kernel_initializer='normal', activation='tanh'))
model1.add(Dense(2, input_dim=1, kernel_initializer='normal', activation='tanh'))
model1.add(Dense(1, kernel_initializer='normal'))
# Compile model
model1.compile(loss='mean_squared_error', optimizer='adam')
return model1

np.random.seed(seed)
estimator1 = KerasRegressor(build_fn=baseline_model1, epochs=100, batch_size=5, verbose=0)

estimator1.fit(X_train2, Y_train2)
prediction = estimator1.predict(X_train2)
plt.scatter(X_train2, prediction)

введите здесь описание изображения


person kullback    schedule 22.07.2018    source источник


Ответы (2)


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

person NHG    schedule 22.01.2020

Ваша сеть очень чувствительна к исходным параметрам. Следующее поможет:

  • Измените свой kernel_initializer на glorot_uniform. Ваша сеть очень мала, и glorot_uniform будет работать лучше в соответствии с активациями tanh. форма Glorot поможет вам изначально в более разумном диапазоне (поскольку он учитывает разветвление каждого слоя).

  • Обучите свою модель большему количеству эпох (например, 1000).

person rvinas    schedule 22.07.2018