За время своего существования вакцины успешно спасли бесчисленное количество жизней. Они широко признаны во всем мире как эффективное средство борьбы с потенциально опасными для жизни заболеваниями, такими как оспа и полиомиелит.
В 1985–1996 годах проводилось исследование младенцев, родившихся в деревнях Буркина-Фассо. Целью исследования было определить влияние вакцинации на смертность в возрасте до 2 лет. Исследование показало, что смертность в возрасте до 2 лет была ниже у детей, которые были вакцинированы. Ссылку на оригинальное исследование можно найти здесь.
Теперь мы будем использовать данные, собранные в ходе этого исследования, для обучения модели логистической регрессии, которая может предсказать, подвергается ли вакцинированный ребенок риску смерти или нет. Первым шагом в этом процессе является понимание функций в наборе данных. Вы можете найти набор данных, Jupyter Notebook с соответствующим кодом и файл с справочной информацией и дескрипторами функций здесь.
Теперь, когда мы получили общее представление о том, что делает каждая функция в наборе данных, пришло время прочитать данные в нашем блокноте Jupyter и начать их анализ. Вы можете заметить, что имена столбцов в наборе данных довольно неоднозначны. Итак, переименуем их для ясности и удобства.
data = pd.read_excel("Biostatem_OMS.xls") data.rename(columns={'ZON':'region', 'NUMIND':'id', 'SEXE':'sex', 'DTP1':'dtp_age', 'RG':'rg_age', 'BCG':'bcg_age', 'AGMER':'mother_age', 'AGEND':'end_age', 'END':'end_status', 'MAT':'delivery', 'DISP':'dispensary', 'MALNU1':'malnutrition', 'DEATH':'death_cause', 'GRDTP1':'dtp_6months', 'GRBCG':'bcg_6months', 'GRRG':'rg_6months', 'FRESH':'birth_season', 'DIAR':'diarrhea', 'FEVE':'fever', 'COU':'cough'}, inplace=True) print(data.head())
Следующим шагом является обработка нулевых значений и очистка данных. Мы заметили, что в столбцах Доставка и Плохое питание большое количество пустых значений. Поэтому мы решили отказаться от них. Мы также удаляем столбец id, так как он имеет уникальные значения и не влияет на наш анализ. Столбцы dtp_age, rg_age и bcg_age также содержат большое количество нулевых значений. В этом случае мы можем предположить, что нуль в этих столбцах означает, что ребенку не вводили дозу вакцины, и, таким образом, нет записи о возрасте, в котором она была введена. Мы заполняем эти нулевые значения -1, чтобы указать, что вакцина не вводилась. Столбец death_cause имеет нулевые значения, соответствующие детям, оставшимся в живых в конце исследования. Мы заполняем эти пустые значения 0, чтобы указать, что ребенок жив. Столбец end_status имеет три уникальных значения — 1, 2 и 3 — соответствующие «мертвым», «живым» и «эмигрированным». Для целей нашего анализа и прогнозирования статус «эмигрировал» означает то же, что и оставшийся в живых ребенок. Итак, мы переназначаем записи с end_status 2 или 3 как 0, чтобы указать, что ребенок остался жив.
print(data.isnull().sum()) data.drop(columns=['delivery', 'id', 'malnutrition'], inplace=True) data['bcg_age'] = data['bcg_age'].fillna(-1) data['dtp_age'] = data['dtp_age'].fillna(-1) data['rg_age'] = data['rg_age'].fillna(-1) data['death_cause'] = data['death_cause'].fillna(0) data['end_status'] = data['end_status'].replace(2, 0) data['end_status'] = data['end_status'].replace(3, 0)
Теперь, когда у нас есть чистый набор данных, мы можем проверить корреляцию между различными функциями. Следующие столбцы имеют очень низкую корреляцию с выходной переменной end_status и поэтому будут отброшены:
- регион
- секс
- возраст_матери
- диспансер
- сезон рождения
corr_matrix = data.corr() print(corr_matrix) sns.heatmap(corr_matrix) data.drop(columns=['region', 'sex', 'mother_age', 'dispensary', 'birth_season'], inplace=True)
Теперь мы можем выполнить проектирование признаков, чтобы получить признаки с более высокой корреляцией и одновременно уменьшить размерность. Столбцы диарея, лихорадка и кашель показывают небольшую положительную корреляцию с end_status. Мы можем объединить эти столбцы в одну характеристику под названием болезнь. Это поможет уменьшить размерность. Ту же идею можно повторить для dtp_6months, rg_6months и bcg_6months. Мы можем получить более высокие значения корреляции, если закодируем dtp_age, rg_age и bcg_age как двоичные, а не числовые переменные. Поэтому мы заменяем все значения -1 на 0 и на 1 в противном случае.
sickness = np.empty(len(data), dtype='int32') for i in range(len(data)): if data.diarrhea[i] or data.fever[i] or data.cough[i]: sickness[i] = 1 else: sickness[i] = 0 vaccine_6months = np.zeros(len(data), dtype='int32') for i in range(len(data)): if data.dtp_6months[i] or data.rg_6months[i] or data.bcg_6months[i]: vaccine_6months[i] = 1 data.drop(columns=['diarrhea', 'fever', 'cough', 'dtp_6months', 'rg_6months', 'bcg_6months'], inplace=True) data['sickness'] = sickness data['vaccine_6months'] = vaccine_6months data.dtp_age = np.where(data.dtp_age == -1, 0, 1) data.rg_age = np.where(data.rg_age == -1, 0, 1) data.bcg_age = np.where(data.bcg_age == -1, 0, 1)
Наконец пришло время построить нашу классификационную модель. Итак, давайте начнем с разделения наших данных на наборы для обучения и тестирования с соотношением 80:20.
X = data.drop(columns=['end_status']) y = data['end_status'] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20)
Теперь мы можем использовать реализацию логистической регрессии, предлагаемую в библиотеке sklearn, для построения нашей модели и проверки ее точности.
from sklearn.linear_model import LogisticRegression LRModel = LogisticRegression() LRModel.fit(X_train, y_train) results = LRModel.predict(X_test) score = LRModel.score(X_test, y_test) print(score)