Нейронная сеть терпит неудачу на наборе данных игрушек - PullRequest
0 голосов
/ 12 мая 2018

Я создал следующий набор игрушечных данных: dataset plot

Я пытаюсь предсказать класс с помощью нейронной сети в кератах:

model = Sequential()
model.add(Dense(units=2, activation='sigmoid', input_shape= (nr_feats,)))
model.add(Dense(units=nr_classes, activation='softmax'))

model.compile(loss='categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

Сnr_feats и nr_classes установлены на 2. Нейронная сеть может предсказывать только с 50-процентной точностью, возвращая либо все 1, либо все 2.Использование логистической регрессии дает 100-процентную точность.

Я не могу найти, что здесь происходит не так.

Я загрузил ноутбук в github, если вы хотите быстро попробоватькое-что.

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

Я резко увеличил количество эпох, и точность, наконец, начинает улучшаться с 0,5 в эпоху 72 и сходится к 1,0 в эпоху 98. Это все ещекажется очень медленным для такого простого набора данных.

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

Я предварительно обработал свой фрейм данных следующим образом:

from sklearn.preprocessing import LabelEncoder

x_train = df_train.iloc[:,0:-1].values
y_train = df_train.iloc[:, -1]

nr_feats = x_train.shape[1]
nr_classes = y_train.nunique()

label_enc = LabelEncoder()
label_enc.fit(y_train)

y_train = keras.utils.to_categorical(label_enc.transform(y_train), nr_classes)

Обучение и оценка:

model.fit(x_train, y_train, epochs=500, batch_size=32, verbose=True)
accuracy_score(model.predict_classes(x_train),  df_train.iloc[:, -1].values)

РЕДАКТИРОВАНИЕ 2

После изменения выходного слоя на один нейрон с сигмовидной активацией и использованием потери binary_crossentropy, как предложил модеситт, точность все еще остается на уровне 0,5 в течение 200 эпох и сходится к 1,0 100 эпохам позже.

Ответы [ 2 ]

0 голосов
/ 12 мая 2018

Примечание: Прочтите раздел «Обновление» в конце моего ответа, если хотите узнать истинную причину. В этом сценарии две другие упомянутые мной причины действительны только в том случае, если для скорости обучения установлено низкое значение (меньше 1e-3).


Я собрал некоторый код. Он очень похож на ваш, но я просто немного его почистил и упростил для себя. Как видите, я использую плотный слой с одним юнитом с функцией активации sigmoid для последнего слоя и просто меняю оптимизатор с adam на rmsprop (это не так уж важно, вы можете использовать adam если хотите):

import numpy as np
import random

# generate random data with two features
n_samples = 200
n_feats = 2

cls0 = np.random.uniform(low=0.2, high=0.4, size=(n_samples,n_feats))
cls1 = np.random.uniform(low=0.5, high=0.7, size=(n_samples,n_feats))
x_train = np.concatenate((cls0, cls1))
y_train = np.concatenate((np.zeros((n_samples,)), np.ones((n_samples,))))

# shuffle data because all negatives (i.e. class "0") are first
# and then all positives (i.e. class "1")
indices = np.arange(x_train.shape[0])
np.random.shuffle(indices)
x_train = x_train[indices]
y_train = y_train[indices]

from keras.models import Sequential
from keras.layers import Dense


model = Sequential()
model.add(Dense(2, activation='sigmoid', input_shape=(n_feats,)))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

model.summary()

model.fit(x_train, y_train, epochs=5, batch_size=32, verbose=True)

Вот вывод:

Layer (type)                 Output Shape              Param #   
=================================================================
dense_25 (Dense)             (None, 2)                 6         
_________________________________________________________________
dense_26 (Dense)             (None, 1)                 3         
=================================================================
Total params: 9
Trainable params: 9
Non-trainable params: 0
_________________________________________________________________
Epoch 1/5
400/400 [==============================] - 0s 966us/step - loss: 0.7013 - acc: 0.5000
Epoch 2/5
400/400 [==============================] - 0s 143us/step - loss: 0.6998 - acc: 0.5000
Epoch 3/5
400/400 [==============================] - 0s 137us/step - loss: 0.6986 - acc: 0.5000
Epoch 4/5
400/400 [==============================] - 0s 149us/step - loss: 0.6975 - acc: 0.5000
Epoch 5/5
400/400 [==============================] - 0s 132us/step - loss: 0.6966 - acc: 0.5000

Как видите, точность никогда не увеличивается с 50%. Что если вы увеличите число эпох до 50:

Layer (type)                 Output Shape              Param #   
=================================================================
dense_35 (Dense)             (None, 2)                 6         
_________________________________________________________________
dense_36 (Dense)             (None, 1)                 3         
=================================================================
Total params: 9
Trainable params: 9
Non-trainable params: 0
_________________________________________________________________
Epoch 1/50
400/400 [==============================] - 0s 1ms/step - loss: 0.6925 - acc: 0.5000
Epoch 2/50
400/400 [==============================] - 0s 136us/step - loss: 0.6902 - acc: 0.5000
Epoch 3/50
400/400 [==============================] - 0s 133us/step - loss: 0.6884 - acc: 0.5000
Epoch 4/50
400/400 [==============================] - 0s 160us/step - loss: 0.6866 - acc: 0.5000
Epoch 5/50
400/400 [==============================] - 0s 140us/step - loss: 0.6848 - acc: 0.5000
Epoch 6/50
400/400 [==============================] - 0s 168us/step - loss: 0.6832 - acc: 0.5000
Epoch 7/50
400/400 [==============================] - 0s 154us/step - loss: 0.6817 - acc: 0.5000
Epoch 8/50
400/400 [==============================] - 0s 146us/step - loss: 0.6802 - acc: 0.5000
Epoch 9/50
400/400 [==============================] - 0s 161us/step - loss: 0.6789 - acc: 0.5000
Epoch 10/50
400/400 [==============================] - 0s 140us/step - loss: 0.6778 - acc: 0.5000
Epoch 11/50
400/400 [==============================] - 0s 177us/step - loss: 0.6766 - acc: 0.5000
Epoch 12/50
400/400 [==============================] - 0s 180us/step - loss: 0.6755 - acc: 0.5000
Epoch 13/50
400/400 [==============================] - 0s 165us/step - loss: 0.6746 - acc: 0.5000
Epoch 14/50
400/400 [==============================] - 0s 128us/step - loss: 0.6736 - acc: 0.5000
Epoch 15/50
400/400 [==============================] - 0s 125us/step - loss: 0.6728 - acc: 0.5000
Epoch 16/50
400/400 [==============================] - 0s 165us/step - loss: 0.6718 - acc: 0.5000
Epoch 17/50
400/400 [==============================] - 0s 161us/step - loss: 0.6710 - acc: 0.5000
Epoch 18/50
400/400 [==============================] - 0s 170us/step - loss: 0.6702 - acc: 0.5000
Epoch 19/50
400/400 [==============================] - 0s 122us/step - loss: 0.6694 - acc: 0.5000
Epoch 20/50
400/400 [==============================] - 0s 110us/step - loss: 0.6686 - acc: 0.5000
Epoch 21/50
400/400 [==============================] - 0s 142us/step - loss: 0.6676 - acc: 0.5000
Epoch 22/50
400/400 [==============================] - 0s 142us/step - loss: 0.6667 - acc: 0.5000
Epoch 23/50
400/400 [==============================] - 0s 149us/step - loss: 0.6659 - acc: 0.5000
Epoch 24/50
400/400 [==============================] - 0s 125us/step - loss: 0.6651 - acc: 0.5000
Epoch 25/50
400/400 [==============================] - 0s 134us/step - loss: 0.6643 - acc: 0.5000
Epoch 26/50
400/400 [==============================] - 0s 143us/step - loss: 0.6634 - acc: 0.5000
Epoch 27/50
400/400 [==============================] - 0s 137us/step - loss: 0.6625 - acc: 0.5000
Epoch 28/50
400/400 [==============================] - 0s 131us/step - loss: 0.6616 - acc: 0.5025
Epoch 29/50
400/400 [==============================] - 0s 119us/step - loss: 0.6608 - acc: 0.5100
Epoch 30/50
400/400 [==============================] - 0s 143us/step - loss: 0.6601 - acc: 0.5025
Epoch 31/50
400/400 [==============================] - 0s 148us/step - loss: 0.6593 - acc: 0.5350
Epoch 32/50
400/400 [==============================] - 0s 161us/step - loss: 0.6584 - acc: 0.5325
Epoch 33/50
400/400 [==============================] - 0s 152us/step - loss: 0.6576 - acc: 0.5700
Epoch 34/50
400/400 [==============================] - 0s 128us/step - loss: 0.6568 - acc: 0.5850
Epoch 35/50
400/400 [==============================] - 0s 155us/step - loss: 0.6560 - acc: 0.5975
Epoch 36/50
400/400 [==============================] - 0s 136us/step - loss: 0.6552 - acc: 0.6425
Epoch 37/50
400/400 [==============================] - 0s 140us/step - loss: 0.6544 - acc: 0.6150
Epoch 38/50
400/400 [==============================] - 0s 120us/step - loss: 0.6538 - acc: 0.6375
Epoch 39/50
400/400 [==============================] - 0s 140us/step - loss: 0.6531 - acc: 0.6725
Epoch 40/50
400/400 [==============================] - 0s 135us/step - loss: 0.6523 - acc: 0.6750
Epoch 41/50
400/400 [==============================] - 0s 136us/step - loss: 0.6515 - acc: 0.7300
Epoch 42/50
400/400 [==============================] - 0s 126us/step - loss: 0.6505 - acc: 0.7450
Epoch 43/50
400/400 [==============================] - 0s 141us/step - loss: 0.6496 - acc: 0.7425
Epoch 44/50
400/400 [==============================] - 0s 162us/step - loss: 0.6489 - acc: 0.7675
Epoch 45/50
400/400 [==============================] - 0s 161us/step - loss: 0.6480 - acc: 0.7775
Epoch 46/50
400/400 [==============================] - 0s 126us/step - loss: 0.6473 - acc: 0.7575
Epoch 47/50
400/400 [==============================] - 0s 124us/step - loss: 0.6464 - acc: 0.7625
Epoch 48/50
400/400 [==============================] - 0s 130us/step - loss: 0.6455 - acc: 0.7950
Epoch 49/50
400/400 [==============================] - 0s 191us/step - loss: 0.6445 - acc: 0.8100
Epoch 50/50
400/400 [==============================] - 0s 163us/step - loss: 0.6435 - acc: 0.8625

Точность начинает увеличиваться (обратите внимание, что если вы тренируете эту модель несколько раз, каждый раз может потребоваться разное количество эпох, чтобы достичь приемлемой точности, от 10 до 100 эпох).

Кроме того, в своих экспериментах я заметил, что увеличение количества единиц в первом плотном слое, например до 5 или 10 единиц, приводит к тому, что модель обучается быстрее (то есть быстро сходится).

Зачем нужно так много эпох?

Я думаю, что это из-за этих двух причин (вместе взятых):

1) Несмотря на то, что два класса легко разделяются, ваши данные состоят из случайных выборок, и

2) Количество точек данных по сравнению с размером нейронной сети (т. Е. Число обучаемых параметров, которое в приведенном выше примере кода составляет 9), относительно велико.

Следовательно, модели требуется больше эпох, чтобы выучить веса. Как будто модель очень ограничена и требует все больше и больше опыта, чтобы правильно находить подходящие веса. В качестве доказательства, просто попробуйте увеличить количество единиц в первом плотном слое. Вы почти гарантированно достигнете точности + 90% с менее чем 10 эпохами каждый раз, когда вы пытаетесь обучить эту модель. Здесь вы увеличиваете емкость, и, следовательно, модель сходится (то есть тренируется) гораздо быстрее (следует отметить, что она начинает переоснащаться, если емкость слишком велика или вы тренируете модель для слишком большого количества эпох. У вас должна быть схема проверки для мониторинга этот выпуск).

Примечание:

Не устанавливайте для аргумента high значение, меньшее, чем аргумент low в numpy.random.uniform, поскольку, согласно документации , в этом случае результаты будут "официально неопределенными" .

Обновление:

Еще одна важная вещь здесь (возможно, самая важная вещь в этом сценарии) - это скорость обучения оптимизатора. Если скорость обучения слишком низкая, модель сходится медленно. Попробуйте увеличить скорость обучения, и вы увидите, что достигли точности 100% менее чем за 5 эпох:

from keras import optimizers

model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=1e-1),
              metrics=['accuracy'])

# or you may use adam
model.compile(loss='binary_crossentropy',
              optimizer=optimizers.Adam(lr=1e-1),
              metrics=['accuracy'])
0 голосов
/ 12 мая 2018

Проблема в том, что ваши метки 1 и 2 вместо 0 и 1. Keras не выдаст ошибку, когда увидит 2, но не сможет предсказать 2.

Вычтите 1 из всех ваших значений y.В качестве примечания, в глубоком обучении часто используется 1 neuron с sigmoid для двоичной классификации (0 или 1) против 2 классов с softmax.Наконец, используйте binary_crossentropy для потери для задач двоичной классификации.

...