Вопрос или проблема
Я пытаюсь создать нейронную сеть с помощью Keras для предсказания теннисистов ATP, которые получат более 1 миллиона долларов призовых, основываясь на их весе и росте (из набора данных, который я собрал несколько недель назад), но столкнулся с странным поведением, особенно в отношении валидационной точности. Иногда она достигает 84-85%, что разумно, поскольку SVM и GaussianNB кажутся способными достигать только 83,3% в лучшем случае (посмотрите этот пост для получения дополнительной информации), но иногда она составляет всего около 15%. И точность, как правило, вообще не меняется, если я добавляю мощность или увеличиваю количество эпох. Я думаю, что одна из самых странных тенденций в этой проблеме заключается в том, что потеря, по сравнению с полученной низкой точностью, оказывается довольно небольшой:
Весь код доступен в этой репозитории (особенно в ATP NN.ipynb
и atp_python_2018-08-27_1-1500.json
), но основная его часть:
model = Sequential()
model.add(Dense(20, activation = 'relu', input_shape = (2,)))
model.add(Dense(20, activation = 'relu'))
model.add(Dense(2))
model.compile(optimizer="adam", loss="categorical_crossentropy", metrics = ['accuracy'])
model_training = model.fit(x = hw_a, y = prize_a_bin, epochs = 4, validation_split = 0.1)
Сначала я думал, что это происходит из-за того, что разбиение на валидацию, выполняемое Keras, может получать немного неправильные наборы, которые не совсем согласованы с остальными данными, поскольку миллионеры составляют только 10% от всего набора данных, но, похоже, это не так, странность сохраняется. Единственный шаблон, который я как-то могу распознать, заключается в том, что нормальная производительность и странная дополняют друг друга, т.е. если одна составляет 85%, то другая будет 100% – 85% = 15%. Это связано с какой-то ошибкой, которую я совершил?
Кстати, поскольку я новичок в Keras, нужно ли было мне указывать функцию активации последнего слоя? Я предполагаю, что по умолчанию он использует либо softmax, либо sigmoid, но, похоже, нет разницы, если я укажу любое из них. Интересно, почему, используя только один класс (либо миллионер, либо нет), нужно изменять y
в to_categorical
и иметь два нейрона – вместо одного – в выходном слое.
Я не могу найти ваш скрипт, скрытый в вашем репозитории, который является вашим набором данных, который полон всего… вам следует лучше организовать свою работу, если вы планируете задавать вопросы на SO.
Это был бы ответ от ветерана, но я не таковым являюсь.
Вам следует использовать binary_crossentropy
в качестве функции потерь, и тогда, я думаю, вы сможете не использовать to_categorical
.
Тогда последний слой должен иметь активацию sigmoid
.
Дополнительно
Попробуйте использовать только один нейрон в последнем слое: Dense(1, activation='sigmoid')
Проблема с точностью может заключаться в том, как вы разбиваете данные: возможно, только образцы из одного класса попадают в валидацию или в тренировочные данные. Я предлагаю вам использовать train_test_split
из sklearn с фиксированным random_state
или чем-то подобным.
Попробуйте эти вещи и посмотрите, поможет ли это:
1.) Явно укажите функцию активации в последнем слое как sigmoid
.
2.) Функция потерь должна быть binary_crossentropy
.
3.) Попробуйте использовать другую метрику вместо accuracy
.
4.) В входном и скрытом слое попробуйте использовать leaky_relu
.
5.) Также укажите batch_size
при подгонке модели.
Дайте знать, если хоть что-то из этого сработает.
Удачи!
Ответ или решение
Проблема с непостоянной точностью в вашей нейронной сети Keras для предсказания миллионеров в теннисе может быть связана с несколькими факторами, и в этом ответе мы рассмотрим, как вы можете улучшить свою модель и добиться более стабильных и высоких результатов.
1. Подбор функции потерь
В вашем коде используется функция потерь categorical_crossentropy
, которая предназначена для многоклассовой классификации. Поскольку ваша задача заключается в бинарной классификации (миллионер или нет), вам следует переключиться на использование функции потерь binary_crossentropy
. Это обеспечит более корректное обучение модели для данной задачи. Вы можете изменить строку компиляции модели следующим образом:
model.compile(optimizer="adam", loss="binary_crossentropy", metrics=['accuracy'])
2. Активация выходного слоя
Выходной слой вашей модели должен содержать одну нейронную единицу с функцией активации sigmoid
, так как вы решаете задачу бинарной классификации. Таким образом, изменения в коде будут следующими:
model.add(Dense(1, activation='sigmoid'))
3. Подготовка данных
Важно убедиться, что ваши данные корректно разделены на обучающую и валидационную выборки. Возможно, вы столкнулись с проблемой, когда данные распределяются неравномерно, и в одной из выборок может оказаться больше экземпляров одного класса. Рекомендую использовать train_test_split
из библиотеки sklearn
для более надежного разделения данных:
from sklearn.model_selection import train_test_split
# Разделение данных.
X_train, X_val, y_train, y_val = train_test_split(hw_a, prize_a_bin, test_size=0.1, random_state=42, stratify=prize_a_bin)
Обратите внимание на параметр stratify
, который поможет сохранить пропорции классов в обеих выборках.
4. Увеличение количества эпох и управление переменной степенью обучения
Поскольку ваша модель может не обучаться должным образом за 4 эпохи, попробуйте увеличить это значение. Убедитесь, что вы используете параметр batch_size
, который может помочь в обучении и избегании переобучения. Установите значение параметра epochs
на 50 или более и добавьте параметр batch_size
:
model_training = model.fit(x=X_train, y=y_train, epochs=50, validation_data=(X_val, y_val), batch_size=32)
5. Использование других метрик и функции активации
Попробуйте использовать leaky_relu
в скрытых слоях, так как он может помочь улучшить обучение:
from keras.layers import LeakyReLU
model.add(Dense(20))
model.add(LeakyReLU(alpha=0.1))
model.add(Dense(20))
model.add(LeakyReLU(alpha=0.1))
Также рассмотрите использование других метрик для оценки качества модели, таких как AUC
, которые могут предоставить более полное представление о вашей модели.
Вывод
Следуя этим рекомендациям, вы увеличите шансы на получение более стабильной и точной модели. Самое главное — это правильное разделение данных и выбор подходящих функций потерь и активации. Надеюсь, что эти изменения помогут вам достичь высоких результатов в вашей задаче предсказания миллионеров в теннисе. Удачи!