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

пс. Скачать исходники можно здесь, а если вам нужно введение в логистическую регрессию, то можно начать со статьи 1.

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

Вот некоторые моменты, которые следует учитывать при работе с данными:
1. Нам потребуется преобразовать все столбцы на основе текста в индексы или числа.
2. Последний столбец — это наша классификация клиентов
3. Первый столбец не будет иметь значения
4. Нам нужно будет удалить строки, содержащие NaN

Теперь, когда мы визуализировали наши данные, давайте приступим.

Давайте начнем с открытия таблицы и загрузки CSV.

clear;
% open csv file
tbl = readtable(‘test.csv’);

Наш следующий шаг — загрузить наши столбцы в матрицу, но преобразовать текстовые столбцы в целые числа. Поскольку мы не можем использовать текст в уравнениях ;-)

% replace strings with labels
ds(:,1) = grp2idx(tbl{:,2});
ds(:,2) = grp2idx(tbl{:,3});
ds(:,3) = tbl{:,4};
ds(:,4) = grp2idx(tbl{:,5});
ds(:,5) = grp2idx(tbl{:,6});
ds(:,6) = tbl{:,7};
ds(:,7) = grp2idx(tbl{:,8});
ds(:,8) = tbl{:,9};
[ds(:,9),labels] = grp2idx(tbl{:,10});

Следующим шагом будет удаление всех строк, содержащих поля NaN.

% remove NaN
ds = rmmissing(ds);
[m,n] = size(ds);

На этом этапе в нашей командной строке давайте запустим corrplot, чтобы увидеть, какие столбцы лучше всего использовать.

corrplot(ds)

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

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

Ну что ж, посмотрим, как пойдет ;-)

Следующий шаг, давайте разделим наши матрицы X и Y, но выберем только столбцы 2, 4 и 8.

X = [ones(m,1) ds(:,[2 4 8])]; 
y = ds(:,n);

Теперь настройте некоторые параметры. Обратите внимание, что наши тета-данные теперь подходят для всех ярлыков категорий. Если эта лямбда-функция выглядит немного странно, то ознакомьтесь с моей статьей о регуляризации.

% setups
[m,n] = size(X);
lambda = 0.01;
thetas = zeros(length(labels),n);

Итак, теперь давайте выполним нашу оценку стоимости one vs all и получим наши лучшие тета от fminunc, которая выполнит для нас оптимизацию затрат. Обратите внимание, что мы написали comuteCost, и вы увидите это чуть позже.
Возможно, вы спросите, что отличает этот вариант от всех остальных?

Обратите внимание на (y == i).
Это возвращает матрицу, в которой все строки текущей категории (i) будут равны «1», а все остальные категории будут «0».
Чтобы полностью понять это , идите вперед и отлаживайте, но это умный маленький трюк, который вы можете использовать, чтобы выполнить один против всех.

% loop through labels and run cost optimisations
for i = 1:length(labels)
  itheta = zeros(n,1);
  options = optimset(‘GradObj’, ‘On’, ‘MaxIter’, 400);
  theta = fminunc(@(t)computeCost(t, X, (y == i), lambda), itheta,   options);
  thetas(i,:) = theta’;
end

Кроме того, обратите внимание, что мы собираем лучшие тета для каждой метки в матрице тета.

Наконец мы можем выполнить наш прогноз, и мы должны увидеть, что в итоге получаем точность 66,48%.

Нет, не здорово, но также неплохо видеть наши данные через коррплоты.

Вот служебные функции, которые вам также понадобятся для работы выше.

function [J,grad] = computeCost(theta, X, y, lambda)
  % get our hypothesis, apply sigmoid
  h = sigmoid(X*theta);
  m = size(X,1);
  
  % new theta for lambda, excluding col 1
  theta1 = [0; theta(2:size(theta),:)];
  
  % penalise thetas to reduce cost
  p = lambda*(theta1'*theta)/(2*m);
  J = ((-y)’*log(h) — (1-y)’*log(1-h))/m + p;
  grad = (X’*(h — y) + lambda * theta1)/m;
end
function g = sigmoid(z)
  g = 1 ./ (1 + exp(-z));
end
function p = predict(thetas, X)
  predict = sigmoid(X*thetas');
  [predictmax,p] = max(predict,[],2);
end

Если вам нужна дополнительная информация о приведенных выше уравнениях, то, опять же, вы можете посмотреть эту статью о регуляризации.