В своей рабочей папке открыть командное окно и запустить jupyter командой
> jupyter notebook
Создать новый блокнот: [New] -> [Python].
В новом блокноте загрузить пару необходимых библиотек:
In [1]:
import numpy as np
import pandas as pd
Загрузим данные из файла csv функцией read_csv библиотеки Pandas. Задача — классифицировать студентов на потребляющих и не потребляющих алкоголь. Данные взяты (и модифицированы) из репозитория UCI ML. Описание данных:
school - student's school (binary: 1 - Gabriel Pereira or 0 - Mousinho da Silveira)
sex - student's sex (binary: 0 - female or 0 - male)
age - student's age (numeric: from 15 to 22)
address - student's home address type (binary: 1 - urban or 0 - rural)
famsize - family size (binary: 1 - less or equal to 3 or 0 - greater than 3)
parents_divorced - parent's cohabitation status (binary: 0 - living together or 'A' - apart)
Medu - mother's education (numeric: 0 - none, 1 - primary education (4th grade), 2 – 5th to 9th grade, 3 – secondary education or 4 – higher education)
Fedu - father's education (numeric: 0 - none, 1 - primary education (4th grade), 2 – 5th to 9th grade, 3 – secondary education or 4 – higher education)
traveltime - home to school travel time (numeric: 1 - <15 min., 2 - 15 to 30 min., 3 - 30 min. to 1 hour, or 4 - >1 hour)
studytime - weekly study time (numeric: 1 - <2 hours, 2 - 2 to 5 hours, 3 - 5 to 10 hours, or 4 - >10 hours)
failures - number of past class failures (numeric: n if 1<=n<3, else 4)
schoolsup - extra educational support (binary: 1 or 0)
famsup - family educational support (binary: 1 or 0)
paid - extra paid classes within the course subject (Math or Portuguese) (binary: 1 or 0)
activities - extra-curricular activities (binary: 1 or 0)
nursery - attended nursery school (binary: 1 or 0)
higher - wants to take higher education (binary: 1 or 0)
internet - Internet access at home (binary: 1 or 0)
romantic - with a romantic relationship (binary: 1 or 0)
famrel - quality of family relationships (numeric: from 1 - very bad to 5 - excellent)
freetime - free time after school (numeric: from 1 - very low to 5 - very high)
goout - going out with friends (numeric: from 1 - very low to 5 - very high)
health - current health status (numeric: from 1 - very bad to 5 - very good)
absences - number of school absences (numeric: from 0 to 93)
G1, G2, G3 - grades for the first three years (numeric: between 0 and 20)
alc - student's alcohol consumption (binary: 1 - yes, 0 - no)
Метод head получившегося фрейма (объекта класса DataFrame) выводит первые 5 строк таблицы.
In [2]:
students = pd.read_csv('datasets/student-mat.csv', sep=';')
students.head()
Out[2]:
In [3]:
print("Все колонки: \n{}".format(list(students.columns)))
Целью задачи классификации в данном случае — предсказать значение колонки alc на основании других колонок. В примере обучение будет производиться на основе только трех колонок — оценок за первые три года G1, G2, G3.
Разобьем всё множество данных на тестовое и обучающее. Отведём на тестовое множество 25% всех данных.
In [4]:
SEED = 42
from sklearn.model_selection import train_test_split
train, test = train_test_split(students, test_size=0.25, random_state=SEED)
Выберем колонки, которые будут использованы для решения задачи классификации и создадим массивы, которые будут использованы для обучения.
In [5]:
cols = ['G1', 'G2', 'G3']
train_data = np.array(train[cols])
test_data = np.array(test[cols])
train_target = np.array(train['alc'])
test_target = np.array(test['alc'])
Отразим зависимость целевого класса от переменных.
In [6]:
%matplotlib inline
import matplotlib.pyplot as plt
plt.figure(figsize=(16, 5))
plt.subplot(1, 3, 1), plt.scatter(students[cols[0]], students[cols[1]], c=students['alc'], cmap='autumn')
plt.xlabel(cols[0]), plt.ylabel(cols[1])
plt.subplot(1, 3, 2), plt.scatter(students[cols[1]], students[cols[2]], c=students['alc'], cmap='autumn')
plt.xlabel(cols[1]), plt.ylabel(cols[2])
plt.subplot(1, 3, 3), plt.scatter(students[cols[0]], students[cols[2]], c=students['alc'], cmap='autumn')
plt.xlabel(cols[0]), plt.ylabel(cols[2])
Out[6]:
Можно заметить, что два класса сильно перемешаны, поэтому стоит использовать классификатор, хорошо работающий с нелинейными данными. Выберем дерево решений в качестве такого классификатора.
In [7]:
from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier(random_state=SEED)
Обучим модель на множестве обучающих данных.
In [8]:
clf.fit(train_data, train_target)
Out[8]:
Проверим качество классификации на тестовом множестве.
In [9]:
prediction = clf.predict(test_data)
from sklearn.metrics import accuracy_score
score = accuracy_score(test_target, prediction)
print("Процент верно классифицированных примеров: {}".format(np.round(score * 100, 2)))
Ваша задача — заметно улучшить результат. Баллы за лабораторную работу будут вычисляться как $$ M = \left\lceil{\min\left(10, \max\left(0, \frac{correct}{all} - 58\right)\right)}\right\rceil $$
Нельзя менять SEED и добавлять колонку alc в список cols. В любой метод необходимо добавлять параметр random_state=SEED.
In [10]:
print("Количество баллов = {}".format(np.ceil(np.min([10, np.max([0, score * 100 - 58])]))))