Вы делаете две очень основные ошибки:
- Ваша ультрапростая модель (однослойная сеть с одним блоком) вряд ли вообще может рассматриваться как нейронная сеть, не говоря уже о "глубокой"изучение "один (так как ваш вопрос помечен)
- Аналогично, ваш набор данных (всего 20 образцов) также очень мал
Понятно, что нейронные сети должны бытьнекоторая сложность, если они решают проблемы, даже такие «простые», как x*x
;и где они действительно сияют, когда питаются большими обучающими наборами данных.
Методология при попытке решить такие аппроксимации функций состоит не в том, чтобы просто перечислить (несколько возможных) входных данных и затем передать их в модель вместе с желаемымвыходы;помните, НН учатся на примерах, а не на символических рассуждениях.И чем больше примеров, тем лучше.Что мы обычно делаем в подобных случаях, так это генерируем большое количество примеров, которые мы впоследствии подаем на модель для обучения.
Сказав это, приведем довольно простую демонстрацию трехслойной нейронной сети вКерас для аппроксимации функции x*x
, используя в качестве входных данных 10 000 случайных чисел, сгенерированных в [-50, 50]
:
import numpy as np
import keras
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam
from keras import regularizers
import matplotlib.pyplot as plt
model = Sequential()
model.add(Dense(8, activation='relu', kernel_regularizer=regularizers.l2(0.001), input_shape = (1,)))
model.add(Dense(8, activation='relu', kernel_regularizer=regularizers.l2(0.001)))
model.add(Dense(1))
model.compile(optimizer=Adam(),loss='mse')
# generate 10,000 random numbers in [-50, 50], along with their squares
x = np.random.random((10000,1))*100-50
y = x**2
# fit the model, keeping 2,000 samples as validation set
hist = model.fit(x,y,validation_split=0.2,
epochs= 15000,
batch_size=256)
# check some predictions:
print(model.predict([4, -4, 11, 20, 8, -5]))
# result:
[[ 16.633354]
[ 15.031291]
[121.26833 ]
[397.78638 ]
[ 65.70035 ]
[ 27.040245]]
Ну, не так уж и плохо!Помните, что NN являются функциональными аппроксиматорами : мы не должны ожидать, что они точно воспроизводят функциональные отношения и не "знают", что результаты для 4
и -4
должны быть идентичными.
Давайте сгенерируем несколько новых случайных данных в [-50,50]
(помните, для всех практических целей это невидимые данные для модели) и нанесите их вместе с исходными, чтобы получитьболее общая картина:
plt.figure(figsize=(14,5))
plt.subplot(1,2,1)
p = np.random.random((1000,1))*100-50 # new random data in [-50, 50]
plt.plot(p,model.predict(p), '.')
plt.xlabel('x')
plt.ylabel('prediction')
plt.title('Predictions on NEW data in [-50,50]')
plt.subplot(1,2,2)
plt.xlabel('x')
plt.ylabel('y')
plt.plot(x,y,'.')
plt.title('Original data')
Результат:
Ну, это действительно похоже на хорошее приближение ...
Вы также можете взглянуть на этот поток для синусоидального приближения.
Последнее, что нужно иметь в виду, это то, что, хотя мы и получили приличное приближениедаже с нашей относительно простой моделью мы должны ожидать , а не экстраполяцию , то есть хорошую производительность за пределами [-50, 50]
;подробности см. в моем ответе в . Плохо ли глубокое обучение при подборе простых нелинейных функций вне рамок обучения?