Перейти к содержимому

Конвейер классификации

Конвейер классификации объединяет подготовку табличных данных и модель классификации.

Это удобно, когда исходные данные лежат в DataFrame, но модель не может работать с ними напрямую. Например, в таблице могут быть пропуски, строковые значения и числовые признаки в разных масштабах.

Рассмотрим небольшую таблицу покупателей.

В ней есть признаки:

  • Возраст;
  • Город;
  • Доход.

И есть целевой столбец:

  • Купил.

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

uses MLABC;
begin
var csvText := '''
Возраст,Город,Доход,Купил
25,Москва,85000,Да
32,Казань,62000,Нет
,Москва,91000,Да
41,Самара,54000,Нет
29,Казань,73000,Да
36,Самара,58000,Да
27,Москва,88000,Да
45,Казань,51000,Нет
31,Самара,76000,Да
38,Москва,60000,Нет
28,Казань,82000,Да
43,Самара,56000,Нет
''';
var df := DataFrame.FromCsvText(csvText);
var features := ['Возраст', 'Город', 'Доход'];
var (trainDf, testDf) :=
df.TrainTestSplit(testRatio := 0.25, seed := 42);
trainDf.Print;
var pipe :=
DataPipeline.BuildClassification(
'Купил',
features,
new Imputer(['Возраст']),
new OrdinalEncoder('Город'),
new MinMaxScaler,
new LogisticRegression
);
pipe.Fit(trainDf);
var pred := pipe.Predict(testDf);
var ytest := pipe.GetEncodedLabels(testDf);
Println('Accuracy:', Metrics.Accuracy(ytest, pred):0:3);
pipe.GetTransformedFeatures(trainDf).Println;
end.

В программе создаётся такой конвейер:

DataFrame
→ Imputer
→ OrdinalEncoder
→ MinMaxScaler
→ LogisticRegression

Каждый этап выполняет свою работу.

Imputer(['Возраст']) заполняет пропуск в столбце Возраст.

OrdinalEncoder('Город') преобразует названия городов в числа.

MinMaxScaler масштабирует числовые признаки так, чтобы значения попали в диапазон от 0 до 1.

LogisticRegression обучается предсказывать значение столбца Купил.

Команда

pipe.Fit(trainDf);

запускает обучение всего конвейера на обучающей таблице trainDf.

При этом конвейер:

  1. запоминает, как заполнять пропуски;
  2. запоминает, как кодировать города;
  3. настраивает масштабирование признаков;
  4. кодирует целевой столбец Купил;
  5. обучает модель LogisticRegression.

Команда

var pred := pipe.Predict(testDf);

получает предсказания для тестовой таблицы.

Важно, что testDf проходит через те же самые этапы подготовки данных, которые были настроены при Fit.

Сначала программа выводит обучающую таблицу:

Возраст Город Доход Купил
25 Москва 85000 Да
NA Москва 91000 Да
43 Самара 56000 Нет
45 Казань 51000 Нет
38 Москва 60000 Нет
29 Казань 73000 Да
28 Казань 82000 Да
32 Казань 62000 Нет
31 Самара 76000 Да

В столбце Возраст есть пропуск NA. Он будет заполнен конвейером.

Затем программа выводит точность модели:

Accuracy: 0.667

Это означает, что модель правильно предсказала примерно 66.7% объектов из тестовой выборки.

Строка

pipe.GetTransformedFeatures(trainDf).Println;

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

0.00 0.00 0.85
0.44 0.00 1.00
0.90 0.50 0.13
1.00 1.00 0.00
0.65 0.00 0.23
0.20 1.00 0.55
0.15 1.00 0.78
0.35 1.00 0.28
0.30 0.50 0.63

Это уже не исходный DataFrame, а числовая матрица признаков.

Первый столбец соответствует возрасту. После MinMaxScaler минимальный возраст 25 стал равен 0.00, а максимальный возраст 45 стал равен 1.00.

Второй столбец соответствует городу. После кодирования и масштабирования:

Москва → 0.00
Самара → 0.50
Казань → 1.00

Третий столбец соответствует доходу. Минимальный доход стал равен 0.00, максимальный — 1.00, остальные значения расположились между ними.

Именно к этой числовой матрице применяется модель LogisticRegression.

Целевой столбец Купил тоже кодируется, потому что модель классификации работает с числовыми метками классов.

В этом примере первое встреченное значение — Да, поэтому:

Да → 0
Нет → 1

Метод

pipe.GetEncodedLabels(testDf)

возвращает правильные ответы тестовой выборки уже в закодированном виде. Поэтому их можно сравнить с предсказаниями модели:

Metrics.Accuracy(ytest, pred)

Конвейер классификации позволяет описать весь процесс в одном месте:

сырые данные → подготовка признаков → обучение модели → предсказание класса

Это делает код короче, понятнее и уменьшает вероятность ошибки при работе с обучающими, тестовыми и новыми данными.