Этот набор данных в репозитории UCI ML содержит демографические данные, такие как возраст, пол, раса и т. Д., Примерно 45000 человек. Я собираюсь поделиться своим подходом к прогнозированию того, превышает ли доход человека 50 тысяч или нет.
Для этого проекта я использовал python и Jupyter Notebook. Вначале я импортировал соответствующие библиотеки (до того, как Бог создал небо и землю). Кроме того, установите размер визуализаций по своему усмотрению. . Я использовал вероятностный метод для работы с категориальными переменными. Полный код этого проекта можно найти здесь.
import pandas as pd import numpy as np import sklearn as sk import seaborn as sns import matplotlib.pyplot as plt %matplotlib inline plt.rcParams["figure.figsize"] = (20,10)
Давайте импортируем набор обучающих данных и приступим. Нам придется добавлять названия столбцов вручную, поскольку в этом наборе данных их нет.
data = pd.read_csv('adult.data') data.info() data.columns = ['age','work-class','fnlwgt','education','edu-num','marital', 'occup','relatnip','race','sex','gain','loss','hours','citizenship','>50k']
Результат указанной выше ячейки. Можно сделать вывод, что нам не нужно сильно беспокоиться об отсутствующих значениях.
<class 'pandas.core.frame.DataFrame'> RangeIndex: 32560 entries, 0 to 32559 Data columns (total 15 columns): 39 32560 non-null int64 State-gov 32560 non-null object 77516 32560 non-null int64 Bachelors 32560 non-null object 13 32560 non-null int64 Never-married 32560 non-null object Adm-clerical 32560 non-null object Not-in-family 32560 non-null object White 32560 non-null object Male 32560 non-null object 2174 32560 non-null int64 0 32560 non-null int64 40 32560 non-null int64 United-States 32560 non-null object <=50K 32560 non-null object dtypes: int64(6), object(9) memory usage: 3.7+ MB
Поскольку последний столбец имеет тип объекта, нам нужно определить используемую уникальную метку и затем сопоставить ее с целочисленным типом.
data['>50k'].unique()
Соответствующий вывод:
array([' <=50K', ' >50K'], dtype=object)
Теперь сопоставим метку, соответствующую доходу, меньшему или равному 50k, с 0, а другую - с 1. Мы также снова получим информацию и проверим, был ли изменен тип данных столбца на int.
data['>50k'] = data['>50k'].map({' <=50K':0,' >50K':1}) data.info()
Как вы можете заключить из выходных данных, тип данных этих столбцов был изменен на 64-битный целочисленный тип.
<class 'pandas.core.frame.DataFrame'> RangeIndex: 32560 entries, 0 to 32559 Data columns (total 15 columns): age 32560 non-null int64 work-class 32560 non-null object fnlwgt 32560 non-null int64 education 32560 non-null object edu-num 32560 non-null int64 marital 32560 non-null object occup 32560 non-null object relatnip 32560 non-null object race 32560 non-null object sex 32560 non-null object gain 32560 non-null int64 loss 32560 non-null int64 hours 32560 non-null int64 citizenship 32560 non-null object >50k 32560 non-null int64 dtypes: int64(7), object(8) memory usage: 3.7+ MB
Теперь я написал функцию, направленную на получение вероятности дохода, превышающей 50К, по любому значению категориальной переменной. Например, какова вероятность того, что доход превысит 50 000 для каждого пола, статуса гражданства и т. Д. Для достижения этой цели я рассчитал среднее значение столбца «› 50 000 ». Поскольку единственными возможными значениями являются 0 и 1, среднее значение будет соответствовать вероятности получения 1.
def rep_mean(var,data): l = list(data[var].unique()) d = dict() for obj in l: d[obj] = data[data[var]==obj]['>50k'].mean() return d
Давайте проверим эту функцию на столбцах рабочего класса, так как она бывает категориальной.
temp1 = rep_mean('work-class',data) temp1
На выходе возвращается словарь.
{' Self-emp-not-inc': 0.2849271940181031, ' Private': 0.21867289390200917, ' State-gov': 0.27216653816499614, ' Federal-gov': 0.38645833333333335, ' Local-gov': 0.29479216435738176, ' ?': 0.10403050108932461, ' Self-emp-inc': 0.557347670250896, ' Without-pay': 0.0, ' Never-worked': 0.0}
Этот словарь можно сопоставить со столбцом рабочего класса.
data['work-class'] = data['work-class'].map(temp1) data.info()
Как вы можете заключить из выходных данных, тип данных был изменен на 64-битное число с плавающей запятой.
<class 'pandas.core.frame.DataFrame'> RangeIndex: 32560 entries, 0 to 32559 Data columns (total 15 columns): age 32560 non-null int64 work-class 32560 non-null float64 fnlwgt 32560 non-null int64 education 32560 non-null object edu-num 32560 non-null int64 marital 32560 non-null object occup 32560 non-null object relatnip 32560 non-null object race 32560 non-null object sex 32560 non-null object gain 32560 non-null int64 loss 32560 non-null int64 hours 32560 non-null int64 citizenship 32560 non-null object >50k 32560 non-null int64 dtypes: float64(1), int64(7), object(7) memory usage: 3.7+ MB
Я сделал то же самое для других категориальных столбцов, также известных как объект. Полную реализацию можно найти здесь. Я создал несколько фиктивных переменных, сложив значения нескольких столбцов и просуммировав произведение вероятностей и коэффициента корреляции.
data['net'] = data['gain']+data['loss'] x = data.corr() x
Я решил не отображать здесь корреляционную таблицу, поскольку она не отображалась четко. Я сгруппировал эти переменные вместе, потому что они были достаточно коррелированы друг с другом.
data['thresh1'] = 1000*(0.368866*data['education']+0.351885*data['occup']) data['thresh2'] = 1000*(0.447396*data['marital']+0.453578*data['relatnip'])
Я тестировал множество алгоритмов. Наконец, я выбрал режим Gradient Boosting, хотя он не очень хорошо работал с данными обучения. Однако он не страдает от чрезмерной подгонки, в отличие от деревьев решений и случайного леса. Весь код и вывод можно найти здесь на Github.