Преобразование данных в одной строке кода

Мотивация

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

Разве не было бы неплохо, если бы вы могли быстро создавать функции, используя произвольный код Python? Вот тут-то и пригодится Пэтси.

Что такое Пэтси?

Patsy - это библиотека Python, которая позволяет преобразовывать данные с помощью произвольного кода Python.

С Пэтси вы можете использовать понятный человеку синтаксис, такой как life_expectancy ~ income_group + year + region (продолжительность жизни зависит от группы дохода, года и региона).

Чтобы установить Пэтси, введите:

pip install patsy

Начиная

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

Наша задача - спрогнозировать продолжительность жизни региона в конкретный год.

Поскольку группа доходов, регион и год могут играть большую роль в определении ожидаемой продолжительности жизни, мы будем использовать Пэтси, чтобы преобразовать эти 3 характеристики в матрицу.

В приведенном выше коде

  • outcome - это объект DesignMatrix, представляющий life_expectancy, переменную, которую мы хотим предсказать.
>>> outcome
DesignMatrix with shape (140, 1)
  life_expectancy
         60.73805
         59.74837
         68.94266
         46.45793
         54.71871
  [135 rows omitted]
  Terms:
    'life_expectancy' (column 0)
  (to view full data, use np.asarray(this_obj))
  • predictors - это DesignMatrix объект, представляющий комбинацию income_group, region и year
>>> predictors
DesignMatrix with shape (140, 11)
  Columns:
    ['Intercept',
     'income_group[T.Low income]',
     'income_group[T.Lower middle income]',
     'income_group[T.Upper middle income]',
     'region[T.Europe & Central Asia]',
     'region[T.Latin America & Caribbean]',
     'region[T.Middle East & North Africa]',
     'region[T.North America]',
     'region[T.South Asia]',
     'region[T.Sub-Saharan Africa]',
     'year']
  Terms:
    'Intercept' (column 0)
    'income_group' (columns 1:4)
    'region' (columns 4:10)
    'year' (column 10)
  (to view full data, use np.asarray(this_obj))

Прохладный! Похоже, у нас есть матрица признаков формы (140, 11). 140 указывает, что имеется 140 примеров, а 11 указывает, что имеется 11 функций. Вот эти 11 функций:

  • Перехват (столбец 0) - массив единиц
  • income_group (столбцы с 1 по 4)
  • region (столбцы с 4 по 10)
  • year (столбец 10)

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

Значит, категориальный столбец:

   income_group
1. low_income   
2. upper_middle_income
3. lower_middle_income
4. low_income
5. upper_middle_income

… Преобразуется в матрицу нулей и единиц:

   low_income  lower_middle_income  upper_middle_income
1.     1               0                     0
2.     0               0                     1
3.     0               1                     0
4.     1               0                     0
5.     0               0                     1                                

Хорошо, я вижу, как легко создавать элементы с Пэтси. Но как я могу использовать эти функции?

Функции, созданные Пэтси, могут быть легко использованы популярными библиотеками машинного обучения, такими как scikit-learn. Другими словами, вы можете рассматривать объект DesignMatrix как массив NumPy.

Это означает, что вы можете разделить объект DesignMatrix на набор поездов и набор тестов, используя train_test_split:

… И передать набор поездов и набор тестов в модель машинного обучения.

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

Чтобы установить Yellowbrick, введите:

pip install yellowbrick

В сюжете выше

  • y - ось, которая представляет реальные значения
  • ŷ - это ось, на которой представлены прогнозируемые значения.
  • Черная пунктирная линия - это подогнанная линия, созданная текущей моделью.
  • Серая пунктирная линия - это то место, где была бы подобранная линия, если бы прогнозируемые значения точно соответствовали реальным значениям.

Линейная модель довольно хорошо следует наблюдаемым целям. Оценка R2 составляет 0,911. Давайте создадим функцию, чтобы мы могли наблюдать подобранную линию с учетом уравнения.

Что произойдет, если мы спрогнозируем целевые значения, используя только столбец income_group?

Оценка R² довольно низкая. Мы можем увидеть, стал ли результат лучше, объединив income_group столбец и region столбец:

Результат тоже не очень хороший. Попробуем совместить income_group и year:

Ага! Сочетание функций income_group и year дает очень хороший результат. Это может быть связано с тем, что группа доходов и год сильно влияют на ожидаемую продолжительность жизни в стране за год.

Встроенные функции

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

Чтобы продемонстрировать эти функции, давайте переключимся на набор данных Bikeshare и возьмем только 2k выборок из данных.

Обратите внимание, что столбцы season, year, month, hour, holiday, workingday и weather являются категориальными переменными. Однако, поскольку их тип данных является целым числом, Пэтси считает их числовыми переменными.

DesignMatrix with shape (2000, 4)
  Intercept  year  hour  temp
          1     0     4  0.58
          1     1     0  0.46
          1     0     0  0.44
          1     1     7  0.64
          1     1     3  0.44
  [1995 rows omitted]
  Terms:
    'Intercept' (column 0)
    'year' (column 1)
    'hour' (column 2)
    'temp' (column 3)
  (to view full data, use np.asarray(this_obj))

Укажите категориальные переменные

Чтобы решить указанную выше проблему, мы можем указать некоторые столбцы как категориальные, используя C(column):

DesignMatrix with shape (2000, 26)
  Columns:
    ['Intercept',
     'C(year)[T.1]',
     'C(hour)[T.1]',
     'C(hour)[T.2]',
     ....
     'C(hour)[T.22]',
     'C(hour)[T.23]',
     'temp']
  Terms:
    'Intercept' (column 0)
    'C(year)' (column 1)
    'C(hour)' (columns 2:25)
    'temp' (column 25)
  (to view full data, use np.asarray(this_obj))

Теперь функции представлены лучше.

Стандартизировать

Мы также можем стандартизировать конкретную функцию (вычесть среднее значение и разделить на стандартное отклонение) с помощью метода standardize:

Эта функция преобразует исходное распределение humidity:

… В этот раздачу:

Вы можете найти другие встроенные методы, которые Пэтси предоставляет здесь.

Пользовательские функции

Помимо встроенных функций, вы также можете написать свою собственную функцию, например, умножение столбца на два:

Первые 5 строк функции thetemp:

  temp
  0.58
  0.46
  0.44
  0.64
  0.44

Первые 5 рядов элемента multiply_by_two(temp):

  multiply_by_two(temp)
  1.16
  0.92
  0.88
  1.28
  0.88

Операторы

Помимо оператора +, вы можете использовать другие операторы для объединения функций другими способами.

- Оператор

Этот оператор используется для удаления терминов справа. Например, использование month + temp — 1 удалит перехват:

DesignMatrix with shape (2000, 2)
  month  temp
      9  0.58
     10  0.46
      5  0.44
      6  0.64
      1  0.44
  [1995 rows omitted]
  Terms:
    'month' (column 0)
    'temp' (column 1)
  (to view full data, use np.asarray(this_obj))

: Оператор

Этот оператор вычисляет взаимодействие между каждым термином слева и каждым термином справа. Например, использование riders ~ month:temp разделит значения в столбце month на значения в столбце temp.

DesignMatrix with shape (2000, 2)
  Intercept  month:temp
          1        5.22
          1        4.60
          1        2.20
          1        3.84
          1        0.44
  [1995 rows omitted]
  Terms:
    'Intercept' (column 0)
    'month:temp' (column 1)

Если на каждой стороне несколько терминов, каждый член слева будет разделен на каждый член справа. Например,

(C(year) + C(hour) + C(workingday)) : temp

расширяется до:

C(year):temp + C(hour):temp + C(workingday):temp

Давайте изобразим приведенное выше уравнение и посмотрим, как выглядит результат:

Мы получили R² 0,709. Это неплохой результат!

* Оператор

a:b включает взаимодействие между a и b, но не включает сами функции a и b. Если вы хотите включить и переменные, и взаимодействие между переменными, используйте a * b.

Например,

month * temp

сокращение для:

month + temp + month:temp

** Оператор

Этот оператор вычисляет * набора терминов с самим собой n раз.

Например,

(temp + humidity + windspeed)**3

расширяется до:

(temp + humidity + windspeed) * (temp + humidity + windspeed) * (temp + humidity + windspeed)

Построим уравнение riders ~ (C(year) + C(hour) + C(workingday) + temp) ** 3 и посмотрим, как оно выглядит:

Ух ты! Мы получили R² 0,812, что является довольно хорошей оценкой. Означает ли это, что чем больше функций, тем лучше результат? Давайте попробуем заменить 3 на 6 и посмотрим, что произойдет.

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

Вы можете найти всех операторов и их использование здесь.

Заключение

Поздравляю! Вы только что узнали, как использовать Patsy для создания функций с произвольным кодом Python. Я надеюсь, что этот инструмент поможет вам поэкспериментировать с различными комбинациями функций и понять их влияние на результаты.

Не стесняйтесь играть и создавать исходный код здесь:



Мне нравится писать об основных концепциях науки о данных и играть с различными алгоритмами и инструментами анализа данных. Вы могли связаться со мной в LinkedIn и Twitter.

Пометьте это репо, если хотите проверить коды всех моих статей. Следуйте за мной на Medium, чтобы быть в курсе моих последних статей по науке о данных, таких как: