Сегодня мы увидим некоторые важные методы для обработки немного более сложных данных, чем примеры, которые я использовал раньше из sklearndata-set, с использованием различных функций pandas. Этот пост поможет вам организовать сложный набор данных для решения реальных проблем, и в конечном итоге мы рассмотрим пример логистической регрессии данных. Подробнее об очистке данных вы можете прочитать в этом сообщении.

Вы можете скачать файл данных из моего репозитория на github под названием bank.csv или из исходного источника, где доступно подробное описание набора данных.

Прежде чем описывать файл данных, давайте импортируем его и посмотрим на основную форму.

import pandas as pd
bankdf = pd.read_csv('bank.csv',sep=';') # check the csv file before to know that 'comma' here is ';'
print bankdf.head(3)
print list(bankdf.columns)# show the features and label 
print bankdf.shape # instances vs features + label (4521, 17) 

Выход такой, как показано ниже

Из выходных данных мы видим, что набор данных имеет 16 функций, а метка обозначена 'y'. Подробное описание возможностей находится в основном репозитории. Обзор набора данных, который находится в основном репозитории, представлен

Эти данные связаны с кампаниями прямого маркетинга португальского банковского учреждения. Маркетинговые кампании основывались на телефонных звонках. Часто требовалось более одного контакта с одним и тем же клиентом, чтобы получить доступ, будет ли продукт (срочный банковский депозит) подписан («да») или нет («нет»).

Мы можем построить график seaborncount, чтобы увидеть, как на выходе доминирует один из классов.

import matplotlib.pyplot as plt
import seaborn as sns
sns.set(font_scale=1.5)
countplt=sns.countplot(x='y', data=bankdf, palette ='hls')
plt.show()

Мы можем подсчитать число с помощью фрагмента кода ниже

count_no_sub = len(bankdf[bankdf['y']=='no'])
print count_no_sub
>>> 4000

Поскольку метка набора данных дается в терминах «да» и «нет», необходимо заменить их числами, возможно, на 1 и 0 соответственно, чтобы их можно было использовать при моделировании данных. На первом этапе мы конвертируем выходные метки набора данных из двоичных строк да / нет в целые числа 1/0.

bankdf['y'] = (bankdf['y']=='yes').astype(int)  # changing yes to 1 and no to 0
print bankdf['y'].value_counts()
>>> 0    4000
    1     521
Name: y, dtype: int64

Поскольку выходные метки теперь преобразованы в целые числа, мы можем использовать groupbyfeature панд, чтобы еще немного исследовать набор данных. В зависимости от метки вывода (да / нет) мы можем видеть, как меняются числа в функциях.

out_label = bankdf.groupby('y')
print out_label.agg(np.mean)
# above two lines can be written using a single line of code
#print bankdf.groupby('y').mean()
>>>
    age   balance   day  duration campaign pdays previous
y                                                                       
0  40.99 1403.2117 15.948 226.347 2.862  36.006  0.471 
1  42.49 1571.9558 15.658 552.742 2.266  68.639  1.090

Во-первых, здесь мы видим только 7 функций из 16, так как остальные функции являются объектами, а не целыми числами или числами с плавающей запятой. Вы можете проверить это набрав bankdf.info(). Мы видим, что функция «продолжительность», которая сообщает нам о продолжительности последнего звонка в секундах, более чем вдвое больше для клиентов, которые купили продукты, чем для клиентов, которые этого не сделали. «Кампания», которая обозначает количество звонков, сделанных в течение текущей кампании, меньше для клиентов, купивших продукты. groupby может дать нам важную информацию о взаимосвязи между функциями и ярлыками. Заинтересованные могут проверить аналогичную операцию «groupby» для функции «образование», чтобы убедиться, что у клиентов с высшим образованием самый высокий «баланс» (средний годовой баланс в евро)!

Некоторые функции набора данных имеют множество категорий, которые можно проверить с помощью uniquemethod объекта series. Примеры приведены ниже.

print bankdf["education"].unique()
print bankdf["marital"].unique()
>>> ['primary' 'secondary' 'tertiary' 'unknown']
    ['married' 'single' 'divorced']

Эти переменные известны как категориальные переменные, а в терминах pandas они называются объектами. Чтобы получить информацию с помощью категориальных переменных, нам нужно преобразовать их в фиктивные переменные, чтобы их можно было использовать для моделирования. Мы делаем это с помощью pandas.get_dummies характерная черта. Сначала мы создаем список категориальных переменных

cat_list = ['job','marital','education','default','housing','loan','contact','month','poutcome']

Затем мы конвертируем эти переменные в фиктивные переменные, как показано ниже.

for ele in cat_list:
 add = pd.get_dummies(bankdf[ele], prefix=ele)
 bankdf1 = bankdf.join(add)# join columns with old dataframe
 bankdf = bankdf1
#print bankdf.head(3)
#print bankdf.info()

Мы создали фиктивные переменные для каждой категориальной переменной, и распечатка заголовка нового фрейма данных приведет к следующему

Вы можете понять, как категориальные переменные преобразуются в фиктивные переменные, которые готовы к использованию при моделировании этого набора данных. Но здесь у нас есть небольшая проблема. Фактические категориальные переменные все еще существуют, и их необходимо удалить, чтобы фрейм данных был готов для машинного обучения. Мы делаем это, сначала преобразовывая заголовки столбцов нового фрейма данных в список с использованием tolist() attribute. Затем мы создаем новый список заголовков столбцов без категориальной переменной и переименовываем заголовки. Мы делаем это с помощью следующего кода

bank_vars = bankdf.columns.values.tolist() # column headers are converted into a list
to_keep = [i for i in bank_vars if i not in cat_list] #create a new list by comparing with the list of categorical variables - 'cat_list'
print to_keep # check the list of headers to make sure no categorical variable remains

Мы готовы создать новый фрейм данных без категориальных переменных, и мы делаем это с помощью -

bank_final = bankdf[to_keep]

Обратите внимание, что для создания нового фрейма данных мы передаем список («to_keep») оператору индексации («bankdf»). Если вы не передадите оператору индексации список имен столбцов, он вернет keyerror. Чтобы выбрать несколько столбцов в качестве фрейма данных, мы должны передать список оператору индексации. Однако вы можете выбрать один столбец как «серию» и увидеть его ниже.

bank_final = bankdf[to_keep] # to_keep is a 'list'
print type(bank_final) 
>>> <class 'pandas.core.frame.DataFrame'>
bank_final = bankdf['age']
print type(bank_final)
>>> <class 'pandas.core.series.Series'>
bank_final = bankdf['age','y']
print type(bank_final)
>>> KeyError: ('age', 'y')

Мы можем проверить заголовки столбцов нового фрейма данных bank-final.

print bank_final.columns.values
>>> ['age' 'balance' 'day' 'duration' 'campaign' 'pdays' 'previous' 'y' 'job_admin.' 'job_blue-collar' 'job_entrepreneur' 'job_housemaid' 'job_management' 'job_retired' 'job_self-employed' 'job_services' 'job_student' 'job_technician' 'job_unemployed' 'job_unknown' 'marital_divorced' 'marital_married' 'marital_single' 'education_primary' 'education_secondary' 'education_tertiary' 'education_unknown' 'default_no' 'default_yes' 'housing_no' 'housing_yes' 'loan_no' 'loan_yes' 'contact_cellular' 'contact_telephone' 'contact_unknown' 'month_apr' 'month_aug' 'month_dec' 'month_feb' 'month_jan' 'month_jul' 'month_jun' 'month_mar' 'month_may' 'month_nov' 'month_oct' 'month_sep' 'poutcome_failure' 'poutcome_other' 'poutcome_success' 'poutcome_unknown']

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

bank_final_vars=bank_final.columns.values.tolist()# just like before converting the headers into a list
Y = ['y']
X = [i for i in bank_final_vars if i not in Y]

Поскольку функций слишком много, мы можем выбрать некоторые из наиболее важных функций с помощью рекурсивного исключения функций (RFE) в разделе sklearn, который работает в два этапа. В своих последующих сообщениях я могу обсудить, почему выбор функций невозможен с помощью логистической регрессии, но пока давайте воспользуемся RFE, чтобы выбрать несколько важных функций. Сначала в RFE передается классификатор с количеством функций, которые нужно выбрать, а затем вызывается метод соответствия. Это изображено в приведенном ниже коде.

model = LogisticRegression()
rfe = RFE(model, 15) # we have selected here 15 features 
rfe = rfe.fit(bank_final[X], bank_final[Y])

Мы можем использовать атрибут support_, чтобы определить, какие функции выбраны.

print rfe.support_
>>> [False False False False False False False False False False False False True False False False False False False False  True False False False False False  True False False False False  True False False  True False False  True False  True  True  True  True False False  True  True  True False  True  True]

rfe.support_ создает массив, в котором выбранные функции помечены как True, и вы можете увидеть 15 из них, поскольку мы выбрали 15 лучших функций. Другой атрибут RFE - ranking_, где значение 1 в массиве выделит выбранные функции.

print rfe.ranking_
>>> [33 37 32 35 23 36 31 18 11 29 27 30  1 28 17  7 12 10  5  9  1 21 16 25 22  4  1 26 24 13 20  1 14 15  1 34  6  1 19  1  1  1  1  3  2  1  1  1 8  1  1]

Мы можем явно распечатать названия функций, выбранных с помощью RFE, с кодом ниже

rfe_rankinglist = rfe.ranking_.tolist()
selected_columns = []
for im in range(len(X)):
 if rfe_rankinglist[im]==1:
  selected_columns.append(X[im]) 
print selected_columns
>>> ['job_retired', 'marital_married', 'default_no', 'loan_yes', 'contact_unknown', 'month_dec', 'month_jan', 'month_jul', 'month_jun', 'month_mar', 'month_oct', 'month_sep', 'poutcome_failure', 'poutcome_success', 'poutcome_unknown']

Наконец, мы можем перейти к атрибутам .fit () и .score (), чтобы проверить, насколько хорошо работает модель.

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

X_new = bank_final[selected_columns]
Y = bank_final['y']
X_old = bank_final[X]
clasf = LogisticRegression()
clasf_sel = LogisticRegression()
clasf.fit(X_old,Y)
clasf_sel.fit(X_new,Y)
print "score using all features", clasf.score(X_old,Y)
print "score using selected features", clasf_sel.score(X_new,Y)

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

  • Мы научились использовать pandas для решения некоторых проблем, которые может иметь реалистичный набор данных.
  • Мы научились преобразовывать строки («да», «нет») в двоичные переменные (1, 0).
  • Как groupby атрибут фрейма данных pandas может помочь нам понять некоторые ключевые связи между функциями и метками.
  • Преобразование категориальных переменных в фиктивные переменные и их использование при моделировании набора данных.
  • Как выбрать часть фрейма данных, передав список оператору индексации.
  • Использование RFE для выбора некоторых основных характеристик сложного набора данных.

Подробнее об очистке и обработке данных читайте в моем посте Обработка данных с помощью pandas. Чтобы узнать больше об использовании Pandas Groupby и Crosstab, вы можете проверить мой пост, посвященный анализу данных о глобальном терроризме. Надеюсь, этот пост поможет вам быть более уверенным в работе с реалистичным набором данных. Оставайся сильным и счастливым. Ваше здоровье !!