Keras: простая нейронная сеть с простыми данными не работает
Я пытаюсь создать очень простую нейронную сеть: один скрытый слой с двумя нейронами. Для очень простых данных: только одна функция.
import numpy as np
X=np.concatenate([np.linspace(0,10,100),np.linspace(11,20,100),np.linspace(21,30,100)])
y=np.concatenate([np.repeat(0,100),np.repeat(1,100),np.repeat(0,100)])

Вот модель
from keras.models import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Dense(2, activation='sigmoid'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='sgd', metrics=['accuracy'])
model.fit(X, y, epochs=200)
По идее, эта модель должна работать. Но даже после 1000 эпох точность все еще составляет 0,667.
Epoch 999/1000
10/10 [==============================] - 0s 1ms/step - loss: 0.5567 - accuracy: 0.6667
Epoch 1000/1000
10/10 [==============================] - 0s 2ms/step - loss: 0.5566 - accuracy: 0.6667
Я думаю, что я что-то не так сделал. Не могли бы вы предложить некоторые модификации?
Похоже, что там много локальных минимумов и инициализация может изменить итоговую модель. Это тот случай, когда при тестировании с пакетом nnet
в R. Мне пришлось тестировать много семян, я нашел эту модель (среди прочих).

И это структура, которую я хотел создать с помощью keras: один скрытый слой с 2 нейронами. Функция активации - сигмовидная.
Поэтому мне интересно, есть ли у keras такая же проблема с инициализацией. С этим пакетом nnet
в R я подумал, что это не «идеальный» пакет. И я подумал, что керас будет более производительным. Если инициализация важна, проверяет ли keras другую инициализацию? Если не почему? Может быть, потому что в целом с большим количеством данных (и большего количества функций) он работает лучше (без тестирования множества инициализаций)?
Например, с kmeans вроде тестируются разные инициализации.
Ответы
Этот вопрос показывает важность нормализации входных данных для нейронных сетей. Без нормализации обучение нейронных сетей иногда затруднено, потому что оптимизация может застрять на некоторых локальных минимумах.
Я хочу начать с визуализации набора данных. Набор данных является одномерным, и после его нормализации с помощью стандартной нормализации он выглядит следующим образом.
X_original = np.concatenate([np.linspace(0, 10, 100), np.linspace(
11, 20, 100), np.linspace(21, 30, 100)])
X = (X_original - X_original.mean())/X_original.std()
y = np.concatenate(
[np.repeat(0, 100), np.repeat(1, 100), np.repeat(0, 100)])
plt.figure()
plt.scatter(X, np.zeros(X.shape[0]), c=y)
plt.show()

Это означает, что одноуровневые сети, такие как логистическая регрессия, не могут классифицировать этот набор данных. Но нейронная сеть с двумя слоями с последующей нелинейной активацией должна иметь возможность классифицировать набор данных.
Теперь с нормализацией и приведенным ниже сценарием обучения модель может легко научиться классифицировать точки.
model = Sequential()
model.add(Dense(2, activation='sigmoid'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer=keras.optimizers.Adam(1e-1), metrics=['accuracy'])
model.fit(X, y, epochs=20)
Train on 300 samples
Epoch 1/20
300/300 [==============================] - 1s 2ms/sample - loss: 0.6455 - accuracy: 0.6467
Epoch 2/20
300/300 [==============================] - 0s 79us/sample - loss: 0.6493 - accuracy: 0.6667
Epoch 3/20
300/300 [==============================] - 0s 85us/sample - loss: 0.6397 - accuracy: 0.6667
Epoch 4/20
300/300 [==============================] - 0s 100us/sample - loss: 0.6362 - accuracy: 0.6667
Epoch 5/20
300/300 [==============================] - 0s 115us/sample - loss: 0.6342 - accuracy: 0.6667
Epoch 6/20
300/300 [==============================] - 0s 96us/sample - loss: 0.6317 - accuracy: 0.6667
Epoch 7/20
300/300 [==============================] - 0s 93us/sample - loss: 0.6110 - accuracy: 0.6667
Epoch 8/20
300/300 [==============================] - 0s 110us/sample - loss: 0.5746 - accuracy: 0.6667
Epoch 9/20
300/300 [==============================] - 0s 142us/sample - loss: 0.5103 - accuracy: 0.6900
Epoch 10/20
300/300 [==============================] - 0s 124us/sample - loss: 0.4207 - accuracy: 0.9367
Epoch 11/20
300/300 [==============================] - 0s 124us/sample - loss: 0.3283 - accuracy: 0.9833
Epoch 12/20
300/300 [==============================] - 0s 124us/sample - loss: 0.2553 - accuracy: 0.9800
Epoch 13/20
300/300 [==============================] - 0s 138us/sample - loss: 0.2030 - accuracy: 1.0000
Epoch 14/20
300/300 [==============================] - 0s 124us/sample - loss: 0.1624 - accuracy: 1.0000
Epoch 15/20
300/300 [==============================] - 0s 150us/sample - loss: 0.1375 - accuracy: 1.0000
Epoch 16/20
300/300 [==============================] - 0s 122us/sample - loss: 0.1161 - accuracy: 1.0000
Epoch 17/20
300/300 [==============================] - 0s 115us/sample - loss: 0.1025 - accuracy: 1.0000
Epoch 18/20
300/300 [==============================] - 0s 126us/sample - loss: 0.0893 - accuracy: 1.0000
Epoch 19/20
300/300 [==============================] - 0s 121us/sample - loss: 0.0804 - accuracy: 1.0000
Epoch 20/20
300/300 [==============================] - 0s 132us/sample - loss: 0.0720 - accuracy: 1.0000
Поскольку модель очень проста, выбор скорости обучения и оптимизатора влияет на скорость обучения. С оптимизатором SGD и скоростью обучения 1e-1 обучение модели может занять больше времени, чем оптимизатору Adam с такой же скоростью обучения.