Будучи студенткой университета, я считаю, что самым ценным ресурсом для меня является время. Между занятиями, проектами и общественными мероприятиями становится все труднее найти время для физической активности. Более того, когда я становлюсь старше, мне становится все труднее случайно заниматься каким-либо организованным спортом. Именно благодаря сочетанию этих причин, я думаю, спортивные программы так хорошо работают в университетской среде. Никаких обязательств или предварительного планирования, просто играйте с теми, кто появляется.

К сожалению, это не только снижает удобство спортивной программы, но и является источником ее самых больших головных болей. Под этим я подразумеваю, что если по какой-либо причине вы решите поиграть в баскетбол в четверг днем, вы можете прийти и обнаружить, что у 20 других людей есть такая же идея. Теперь вам нужно дождаться завершения нескольких игр, прежде чем вы сможете даже коснуться мяча!

К счастью, учебный центр моей школы решил периодически твитить количество пользователей, которые в настоящее время занимаются спортом. Это помогает, потому что дает учащимся некоторую информацию, помогающую им в принятии решений. Хотя я лично обнаружил, что этот инструмент был несколько неэффективным, поскольку для того, чтобы добраться до центра отдыха кампуса, требуется почти 30 минут, а частота, с которой делаются твиты, слишком мала, чтобы прогнозировать количество сотрудников на заданное время.

Эта проблема казалась созревшей для решения, которое могло бы эффективно моделировать и обобщать отношения. Будучи студентом-программистом, интересующимся машинным обучением и наукой о данных, я подумал, что попытаюсь разработать такое решение. Мои поиски выглядели многообещающе почти сразу, когда я наткнулся на аккаунт в Твиттере с почти такой же целью. Этой учетной записью управляет Деметри Пананос, в которой он использует данные из другой учетной записи Twitter, которая твитит информацию о количестве сотрудников из тренажерного зала и мезонина кардио. Прочитав github repo, я вдохновился на создание чего-то подобного самому. Деметри не только создал модель, которая могла прогнозировать использование, но также разработал некоторую инфраструктуру, поддерживающую последовательное обучение. Этот конвейер фиксирует каждый твит и использует API для получения информации о погоде во время твита. Хранение всей этой информации в экземпляре SQLite.

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

Далее пришло время создать модель. Сначала я загрузил вышеупомянутый набор данных.

f = open('training_data.pickle', 'rb')
data = pickle.load(f)
f.close()
pd.set_option('display.max_columns', None)

Затем наборы данных разделяются, чтобы можно было использовать перекрестное тестирование.

weather = pd.concat([data['hour'],data['day'],data['month'],
data['year'],data['temp'],data['dewpoint'],data['humidity']], axis=1)
weather_basketball_train, weather_basketball_test, basketball_train, basketball_test = train_test_split(weather, data['basketball'], test_size=0.33, random_state=42)
weather_volleyball_train, weather_volleyball_test, volleyball_train, volleyball_test = train_test_split(weather, data['volleyball'], test_size=0.33, random_state=42)
weather_badminton_train, weather_badminton_test, badminton_train, badminton_test = train_test_split(weather, data['badminton'], test_size=0.33, random_state=42)

Теперь, когда данные разделены на наборы для оценки и тестирования, функции должны быть встроены в соответствии с их типом. Это означает, что мы не хотим, чтобы такая информация, как дата и время, рассматривалась как числовая, а вместо этого как категориальная метка. Это делается ниже.

CATEGORICAL_COLUMNS = ['year', 'month', 'day','hour']
NUMERIC_COLUMNS = ['temp', 'dewpoint','humidity']
feature_columns = []
for feature_name in CATEGORICAL_COLUMNS:
  vocabulary = data[feature_name].unique()
  feature_columns.append(tf.feature_column.categorical_column_with_vocabulary_list(feature_name, vocabulary))
for feature_name in NUMERIC_COLUMNS:
  feature_columns.append(tf.feature_column.numeric_column(
  feature_name, dtype=tf.float32))

Затем необходимо создать функцию ввода, чтобы ввод можно было использовать с библиотекой Tensorflow.

def make_input_fn(data_df, label_df, num_epochs=10, shuffle=True, batch_size=32):
  def input_function():
    ds = tf.data.Dataset.from_tensor_slices((dict(data_df,
    label_df))
    if shuffle:
      ds = ds.shuffle(1000)
    ds = ds.batch(batch_size).repeat(num_epochs)
    return ds
  return input_function
train_input_fn_basketball = make_input_fn(weather_basketball_train, basketball_train)
eval_input_fn_basketball = make_input_fn(weather_basketball_test, basketball_test, num_epochs=1, shuffle=False)
train_input_fn_volleyball = make_input_fn(weather_volleyball_train, volleyball_train)
eval_input_fn_volleyball = make_input_fn(weather_volleyball_test, volleyball_test, num_epochs=1, shuffle=False)
train_input_fn_badminton = make_input_fn(weather_badminton_train, badminton_train)
eval_input_fn_badminton = make_input_fn(weather_badminton_test, badminton_test, num_epochs=1, shuffle=False)

Наконец, все три модели можно обучить и оценить.

basketball_linear_est = tf.estimator.LinearRegressor(feature_columns=feature_columns)
basketball_linear_est.train(train_input_fn_basketball)
result = basketball_linear_est.evaluate(eval_input_fn_basketball)
badminton_linear_est = tf.estimator.LinearRegressor(feature_columns=feature_columns)
badminton_linear_est.train(train_input_fn_badminton)
result = badminton_linear_est.evaluate(eval_input_fn_badminton)
volleyball_linear_est = tf.estimator.LinearRegressor(feature_columns=feature_columns)
volleyball_linear_est.train(train_input_fn_volleyball)
result = volleyball_linear_est.evaluate(eval_input_fn_volleyball)

Последний шаг — предоставить модели входной тензор и посмотреть, что он предсказывает! Попробуйте сами на блокноте Google Colab! Это был первый шаг в серии шагов, которые я надеюсь выполнить для оптимизации этого инструмента прогнозирования. Недавно через реддит я узнал, что Деметри скоро больше не будет поддерживать созданного им бота. Я надеюсь сначала оптимизировать свою модель для падений в спорте, исследуя более сложные архитектуры моделей и, возможно, дополнительные функции, которые могут обеспечить вывод. Но при условии, что все сделано правильно, моей конечной целью было бы объединить оба этих проекта под одной крышей.