- Вопрос или проблема
- Ответ или решение
- 1. Анализ данных
- 1.1 Качество данных
- 1.2 Баланс классов
- 1.3 Предобработка данных
- 2. Архитектура модели
- 2.1 Сложность модели
- 2.2 Регуляризация
- 3. Обучение модели
- 3.1 Параметры обучения
- 3.2 Эпохи и обратная связь
- 4. Оценка результатов
- 4.1 Визуализация
- 4.2 Смешение данных
- 5. Перспективное направление
- 5.1 Альтернативные модели
- Выводы
Вопрос или проблема
Я в данный момент нахожусь в процессе освоения Data Science, машинного обучения и особенно нейронных сетей (при этом у меня “чистый” опыт в области программной инженерии). Я создал несколько моделей на классических наборах данных, таких как MNIST и MNIST Fashion, которые работали прекрасно, и хотел бы заняться более сложной задачей в качестве вызова: прогнозированием спортивных событий/футбольных матчей. Я нашел несколько статей, где уже пытались это сделать с помощью глубоких нейронных сетей с результатами около ~0.65 до 0.7 точности. Это уровень, которого я тоже хотел бы достичь. Однако я не могу повысить точность своей модели выше примерно 0.507. Вот что я сделал:
У меня есть наборы данных из нескольких тысяч матчей в лигах по всему миру (Премьер Лига, Бундеслига и т.д.) за последние 10 сезонов. В качестве входных данных я использую следующее:
- День недели матча
- Сезон (год)
- Номер круга
- ID лиги (one hot encoded)
- Ночной матч (да/нет)
- ID площадки (one hot encoded)
- ID домашних и выездных команд (one hot encoded)
- Очки домашних и выездных команд за сезон
Как видите, некоторые из моих данных закодированы с использованием one hot encoding. Все точки данных (включая данные, которые не закодированы) размещены в np массивах одинакового размера. Поэтому все данные дополнены нулями до одинакового размера, чтобы гарантировать ту же самую форму ввода для каждого набора данных размером (10, 480)
. Поскольку я добавляю больше наборов данных, последнее число увеличивается, так как появляется больше ID команд, ID площадок и т.д., и поэтому требуется больше размера массива/дополнения. Я не совсем уверен, является ли это наилучшим решением, но, насколько я понял, нейронные сети действительно зависят от того, чтобы ввод имел одинаковую форму, так что это было лучшим решением в моих глазах.
Модель затем строится следующим образом:
def build_model(input_shape, dropout=0.2, hidden_layers=1, hidden_sizes=[64], learning_rate=0.01, optimizer="adam", last_layer_activation="softmax"):
if optimizer == 'adam':
optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)
elif optimizer == 'adagrad':
optimizer = tf.keras.optimizers.Adagrad(learning_rate=learning_rate)
elif optimizer == 'sgd':
optimizer = tf.keras.optimizers.SGD(learning_rate=learning_rate)
elif optimizer == 'rmsprop':
optimizer = tf.keras.optimizers.RMSprop(learning_rate=learning_rate)
elif optimizer == 'adadelta':
optimizer = tf.keras.optimizers.Adadelta(learning_rate=learning_rate)
elif optimizer == 'adamax':
optimizer = tf.keras.optimizers.Adamax(learning_rate=learning_rate)
else:
raise ValueError(f"Unknown optimizer {optimizer}")
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=input_shape))
model.add(tf.keras.layers.Dropout(dropout))
for i in range(hidden_layers):
model.add(tf.keras.layers.Dense(hidden_sizes[i], activation='relu'))
model.add(tf.keras.layers.Dense(3, activation=last_layer_activation))
model.compile(optimizer=optimizer,
loss="categorical_crossentropy",
metrics=['accuracy'])
return model
Данные затем делятся на обучающую и валидационную выборки с соотношением 80:20 и обучаются с использованием model.fit(x_train, y_train, epochs=100, callbacks=callbacks, batch_size=64, validation_data=(x_val, y_val))
с использованием EarlyStop. Я также пробовал большие размеры пакетов.
Модель затем выводит массив, закодированный с использованием one hot encoding: [Победа дома, Ничья, Победа в гостях]
.
Я пробовал настраивать гиперпараметры модели (указанные в параметрах функции) с помощью KerasTuner, но безуспешно. Я не могу добиться точности выше примерно 0.507 максимум.
Кроме того, моя точность валидации, а также потеря очень шумные, как вы можете видеть на этом графике (где я пытался обучаться чуть дольше 100 эпох):
Я бы ожидал некоторого шума (примерно на уровне обучающих данных) – из-за случайного фактора в спорте – но не такого сильного шума. Точность обучения действительно растет немного дальше, что – если я правильно понял – говорит о переобучении, что я пытался уменьшить, используя слои Dropout.
Есть ли идеи о том, как я мог бы улучшить эту модель дальше? Мои данные неэффективны, например, следует ли мне включить состав каждой команды? Слишком мало данных? Слишком много данных? Подходит ли другая сеть для этой задачи лучше?
Спасибо!
Обновление 1: На основе аналогичных проблем я попробовал некоторые вещи, чтобы исключить некоторые причины:
- Я пробовал поменять местами обучающие и валидационные наборы данных, чтобы посмотреть, есть ли какая-либо разница в предобработке между ними. Результат тот же.
- Я также сгенерировал случайные наборы данных в качестве значений y / результатов, закодированных с использованием one hot encoding, используя
np.eye(3)[np.random.choice(3, size=len(x_train))]
. Как и ожидалось, модель застревает около 0.33. Следовательно, модель действительно работает, просто не очень хорошо.
Я думаю, что вы строите график точности валидации в зависимости от числа шагов. По мере увеличения числа шагов точность растет, но в конце эпохи записывается средняя точность, которая меньше, чем точность на последнем шаге. Вот почему вы видите резкое снижение точности после каждой эпохи, но в начале следующей эпохи точность снова возрастает.
- Судя по всему, происходит переобучение, так как точности на обучающей и валидационной выборках различаются, поэтому вы можете попробовать использовать регуляризацию, это повысит точность валидации.
- Нарисуйте график потерь при обучении в зависимости от числа примеров, чтобы проверить, следует ли увеличить количество обучающих примеров.
Ответ или решение
Для достижения более высокой точности в предсказаниях спортивных событий с использованием нейронных сетей Keras, важно определить и устранить возможные проблемы в вашем подходе. Давайте подробно рассмотрим факторы, которые могут влиять на низкую точность (около 0.5) вашей модели, и предложим пути их решения.
1. Анализ данных
1.1 Качество данных
Качество и полнота ваших данных имеют первостепенное значение. Рассмотрите возможность добавления дополнительных признаков, которые могут оказать влияние на исход матча. Например, информация о составе команд, травмах игроков, статистике предыдущих встреч, домашних и выездных формах команд.
1.2 Баланс классов
Имейте в виду, что если ваши классы (победа дома, ничья, победа на выезде) не сбалансированы, это может привести к смещению модели. Проверьте распределение классов в целевой переменной и, если это необходимо, применяйте методы, такие как увеличение выборки для меньшинственных классов или потеря (loss) с учетом веса классов.
1.3 Предобработка данных
Проверьте, что ваша предобработка данных корректная. Убедитесь, что все категориальные переменные правильно закодированы, и не забудьте нормализовать численные переменные, чтобы предотвратить доминирование некоторых признаков при обучении.
2. Архитектура модели
2.1 Сложность модели
Ваша модель может оказаться слишком простой для решения данной задачи. Рассмотрите возможность увеличения количества слоев или нейронов в скрытых слоях. Попробуйте разные функции активации, помимо ReLU, такие как Leaky ReLU или ELU, которые могут помочь улучшить усвоение данных.
2.2 Регуляризация
Для борьбы с переобучением рассмотрите возможность добавления L1 или L2 регуляризации к слоям Dense, а также добавления дополнительных слоев Dropout. Это может помочь модели лучше обобщать данные.
3. Обучение модели
3.1 Параметры обучения
Обратите внимание на степень обучения и размер батча. Возможно, стоит попробовать уменьшить скорость обучения (например, до 0.001) и проверить, как это отразится на результате. Также протестируйте различные размеры батча. Размер батча 64 может быть слишком большим для вашего набора данных, что может вызвать нестабильность.
3.2 Эпохи и обратная связь
Увеличьте количество эпох, но учитывайте возможность переобучения. Используйте функции обратной связи, такие как ReduceLROnPlateau
, чтобы уменьшить скорость обучения, когда валидационная точность перестает увеличиваться.
4. Оценка результатов
4.1 Визуализация
Тщательно проанализируйте графики ошибок и точности. Понять, как себя ведет ваш алгоритм в каждой эпохе, поможет выявить моменты, когда происходит переобучение. Проверьте, как ведет себя функция потерь во время обучения и валидации.
4.2 Смешение данных
Экспериментируйте с перемешиванием данных между обучающим и валидационным наборами, чтобы убедиться, что модель не может запомнить отдельные матчи или команды.
5. Перспективное направление
5.1 Альтернативные модели
Если после всех манипуляций точность все еще не достигает желаемого уровня, рассмотрите возможность использования других алгоритмов машинного обучения, таких как случайные леса, градиентные бустинговые модели или даже ансамбли моделей.
Выводы
Работа с предсказаниями в спорте — это сложная задача, требующая тщательной работы с данными и экспериментирования с архитектурой модели. Не стесняйтесь пробовать разные подходы и не забывайте о важности анализа полученных результатов. Успехов вам в дальнейшем исследовании!