В этой статье я помогу вам использовать машинное обучение вместе с калькулятором или анкетой, чтобы узнать больше о ваших пользователях. После прочтения вы будете знать все, что вам нужно, чтобы заполнить пустые поля необязательных вопросов с обоснованными предположениями относительно того, что могли бы ответить пользователи. Для этого я использовал Python Pandas, но все концепции должны быть перенесены на любой язык, который вы используете. Таким образом, продолжайте чтение, если установите следующие флажки.

☑ Вы хотите повысить точность результатов калькулятора или викторины.

☑ Его предполагаемое использование - как можно больше узнать об отдельных пользователях.

☑ Вы рассматриваете возможность внедрения или уже содержит дополнительные вопросы

☑ Вы храните историю своих ответов в форме, которую можно рассматривать как фрейм данных

☑ У вас есть опыт работы с машинным обучением

Поставил галочки или просто любопытно? Отлично - давайте погрузимся!

Алгоритмы машинного обучения уже созданы для вашего удобства. После того, как ваши данные подготовлены и выбран правильный алгоритм, для построения модели и прогнозирования потребуется всего 3–7 строк общего кода. Таким образом, большая часть вашей работы будет заключаться в выборе лучшего алгоритма и гиперпараметров, в то время как ваш код будет посвящен преобразованию ваших данных в удобный для алгоритмов формат.

Выбор алгоритма

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

Однако, поскольку ответы на различные вопросы викторины могут быть в разных формах, выбор между алгоритмами, которые принимают непрерывные или категориальные данные, может оказаться сложным в этом контексте. Категориальные вопросы предполагают ограниченное количество возможных ответов, например целые числа от 0 до 10 или буквы от a до d. С другой стороны, непрерывные ответы могут принимать форму любой строки с плавающей запятой или строки «свободный ответ». Примеры алгоритмов, принимающих категориальные значения, включают логистическую регрессию и наивный байесовский алгоритм, в то время как линейная регрессия, деревья решений и большинство других алгоритмов принимают непрерывные данные. Мы будем называть их категориальными или непрерывными алгоритмами соответственно.

Непрерывные алгоритмы более универсальны

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

С вопросами, связанными с бесплатными ответами, сложно работать

Большинству из вас следует просто отбросить вопросы с бесплатными ответами из своей обучающей выборки и игнорировать их при принятии решения, какой алгоритм запустить. Если ваш набор данных огромен, ваша анкета содержит множество вопросов с бесплатными ответами, и у вас есть необходимое терпение и опыт, однако вы можете провести анализ настроений на основе ответов на бесплатные ответы и, следовательно, принять непрерывный алгоритм. В этой статье я не буду объяснять, как это сделать. Если вам нужна помощь в этом, оставьте комментарий ниже или напишите мне сообщение - я хотел бы поговорить с вами о вашем проекте!

Как только вы определились с алгоритмом, самое время писать код!

Вот код для начала:

import pandas as pd
import numpy as np
from sklearn import preprocessing
df = pd.read_pickle(r'C:\file_location.p')

Подготовка данных

Мой фрейм данных содержал так много столбцов, которые можно удалить, что я решил создать относительно короткий список столбцов, называемый «функциями», которые я планировал использовать для построения своих моделей. Затем я создал новый фрейм данных под названием «new_df» для хранения только этих столбцов.

new_df = df.filter(features, axis=1)

Но сначала вам нужно решить, какие столбцы включить в «функции»…

Массивы / списки

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

example_list_0 = []
example_list_1 = []
for ar in new_df[‘example_list’]:
    example_list_0.append(ar[0])
    example_list_1.append(ar[1])
new_df[‘example_list’] = example_list_0
new_df[‘example_list_1’] = example_list_1
features.append('example_list_1')

Нет необходимости удалять все нерелевантные столбцы

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

Схожие и повторяющиеся столбцы

Мой фрейм данных содержал общее количество ответов каждого пользователя по определенным группам ответов. Точно так же напрямую связанные столбцы окажутся очень вредными для построения вашей модели. То есть предположим, что третий столбец содержит итоги для 2 вопросов, и перед внедрением машинного обучения, когда один из вопросов оставлен пустым, ему присваивается произвольное значение, например ноль.

column_A + column_B = column_C

Затем данные обучения покажут, что, если пользователь оставляет один из вопросов, например, column_B пустым, тогда column_A = column_C. Затем модель предсказывает, что все пробелы равны нулю, хотя это просто не так. Таким образом, следует отбросить все формы напрямую связанных или повторяющихся столбцов.

Связанное с этим беспокойство, с которым вы, возможно, уже знакомы, заключается в том, что при построении регрессионных моделей следует учитывать столбцы, содержащие очень близкие ответы. Это связано с тем, что построение регрессионных моделей с нормами l1 отбросит ценные вопросы, которые слишком похожи, такие как, например, размер и длина обуви, даже если они являются ценными предикторами. Эту проблему проще всего решить, используя l2 norm или отбрасывая один из столбцов.

Недостаточно или неверно данных

Столбцы с более чем 50% пропусков также следует отбросить. С этим процентом можно играть по мере увеличения размера ваших данных. Кроме того, следует отбросить все бесполезные столбцы, в которых данные по какой-либо причине неправильные, искаженные, одинаковые для всех пользователей или нечитаемые.

Моральные соображения

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

Теперь, когда вы выбрали столбцы…

Вы захотите подготовить свои данные соответственно в зависимости от того, принимают ли они категориальные или непрерывные значения.

Для непрерывных алгоритмов

Только чтение, если вы выбрали непрерывный алгоритм.

Да или нет вопросов

«Нет» и «Да» можно заменить на 0 и 1 соответственно.

new_df[‘example_question’] = 
    new_df.example_question.map(dict(YES=1,NO=0))

Нулевые значения должны быть заполнены средним значением всех нулей и единиц в столбце.

new_df[['example_question']] = 
    df[['example_question']].fillna(new_df.example_question.mean())

А как насчет "может быть"?

«Может быть» можно просто представить как цифру 1, а нажатие «да» будет представлено цифрой 2. Важно, чтобы числа нечетко отражали значение категорий. То есть, не имеет смысла заказывать «нет», «да» и «возможно» как 0, 1 и 2 соответственно, поскольку «возможно» следует ассоциировать с меньшим количеством, чем «да».

Правдивые или ложные вопросы

Pandas, естественно, читает «false» как 0 и «true» как 1. Это замечательно, но если ваш столбец содержит нулевые значения, вам нужно будет найти среднее значение для их заполнения. Наилучший способ найти это среднее - преобразовать false и true в 0 и 1 соответственно, как если бы вы делали «нет» и «да».

Любые другие категориальные вопросы

Непрерывные алгоритмы способны понимать только категории, поддающиеся количественной оценке. То есть, если категории представляют собой шаги по спектру, например «никогда», «редко», «иногда» и т. Д., Тогда они могут быть представлены цифрами 0, 1, 2 и т. Д. Соответственно. Затем пустые значения могут быть заполнены средним значением, как в приведенных выше случаях. Однако, если категории не имеют числового отношения друг к другу, например, список имен, то вряд ли существует числовое представление, которое имело бы смысл, поэтому эти вопросы следует исключить из ваших обучающих данных.

Для категориальных алгоритмов

Для тех, кто использует категориальный алгоритм…

Да или нет вопросов

«Нет» и «Да» можно заменить на 0 и 1 соответственно.

new_df[‘example_question’] = 
    new_df.example_question.map(dict(YES=1,NO=0))

Нулевые значения должны быть заполнены режимом всех 0 и 1 в столбце.

new_df[['sample_question']] = 
    df[['example_question']].fillna(new_df.example_question.mode())

А как насчет "может быть"?

«Может быть» можно просто представить как число 1, подталкивая «да» к представлению числом 2. При использовании категориального алгоритма порядок этих чисел значительно менее важен, чем при использовании непрерывного. То есть упорядочивание «нет», «возможно» и «да» как 0, 1 и 2 соответственно поможет людям запомнить, какое число связано с какой категорией, но не поможет модели. Так что не стесняйтесь назначать ответы на числа свободно.

Правдивые или ложные вопросы

Панды естественно читают false как 0 и true как 1. Это здорово! Но, конечно, все равно не помешает преобразовать их в 0 и 1, так же, как вы это делали с нет и да. Нулевые значения аналогичным образом могут быть заменены режимом ненулевых значений.

Любые категоричные вопросы

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

Хорошая работа! Вы успешно подготовили данные, поэтому самое сложное осталось позади.

Машинное обучение

Следуя типичному процессу машинного обучения…

  1. Разделите данные на обучающие и тестовые наборы с помощью sklearn's train_test_split. Если вы собираетесь выбирать гиперпараметры, то вам следует выбрать и наборы проверки (если вы будете использовать набор проверки для выбора гиперпараметров). Однако, оглядываясь назад, я мог бы предложить использовать перекрестную проверку для разделения ваших данных, если вы работаете с таким же небольшим объемом данных.
from sklearn.model_selection import train_test_split

train_features, test_features, 
    train_goal, test_goal = \
    train_test_split(temp_df[features], temp_df[goal], test_size=.2, 
    random_state=6)

Если вы собираетесь выбирать гиперпараметры, на этом этапе вы можете разделить свой обучающий набор на обучающий и проверочный набор следующим образом. Однако, если ваши данные находятся на меньшей стороне, вам следует вместо этого рассмотреть возможность использования перекрестной проверки. Я проиллюстрирую, как это сделать, в случае деревьев решений ниже.

train_features, validation_features, train_goal, 
    validation_goal = \
    train_test_split(train_features, 
    train_goal, test_size=1/8, random_state=6)

Примечание. На этом этапе я столкнулся со странной проблемой, когда мои наборы для обучения, тестирования и проверки получали значения nan. Я исправил это с помощью следующего кода, но, поскольку я никогда не определял корень проблемы, я сомневаюсь, что это лучший способ справиться с ней. Мне было бы очень интересно услышать о ваших переживаниях и мыслях.

test_features = np.nan_to_num(test_features)
train_features = np.nan_to_num(train_features)
validation_features = np.nan_to_num(validation_features)

2. Постройте свою модель и сделайте прогноз!

Вот пример кода для моделей линейной регрессии и дерева решений.

Линейная регрессия

from sklearn.linear_model import LinearRegression
scaler = preprocessing.StandardScaler().fit(train_features)
train_features = scaler.transform(train_features)
test_features = scaler.transform(test_features)
validation_features = scaler.transform(validation_features)
 
model = LinearRegression().fit(train_features, train_goal)
prediction = model.predict(test_features)
validation_prediction = model.predict(validation_features)

Деревья решений

Здесь я включаю код для поиска гиперпараметров с использованием 6-кратной перекрестной проверки.

from sklearn.model_selection import GridSearchCV
hyperparameters = {‘min_samples_leaf’: [1, 10, 50, 100, 200, 300], 
    'max_depth’: [1, 5, 10, 15, 20]}
search =
    GridSearchCV(DecisionTreeClassifier(random_state=6), 
    hyperparameters,cv=6,return_train_score=True)
search.fit(train_features, train_goal)
print(search.best_params_)

Я обнаружил, что мои идеальные гиперпараметры - max_depth = 5 и min_samples_leaf = 50.

from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier(random_state=1, max_depth=5,
    min_samples_leaf=50)
decision_tree_model = clf.fit(train_features, train_goal)
test_dec_pred = decision_tree_model.predict(test_features)
val_dec_pred = decision_tree_model.predict(validation_features)

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

Для этого вам нужно будет вычислить среднеквадратичную ошибку (RMSE) прогнозов вашей модели и ближайших лучших прогнозов.

Чтобы вычислить RMSE среднего…

from sklearn.metrics import mean_squared_error

mean = train_goal.mean()
test_mean = pd.Series(mean for _ in range(test_goal.size))
mean_test_rmse = mean_squared_error(test_goal, test_mean) ** (1/2)

А вашей модели…

test_rmse = mean_squared_error(test_goal, test_pred) ** (1/2)

Точность тестирования

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

test_percent_error_reduced = 1 - test_rmse / mean_test_rmse

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

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

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

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

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

Благодарим вас за то, что вы были со мной в этом процессе - надеюсь, вы сочли, что оно того стоит. Если вам нужна конкретная помощь на каком-либо этапе этого процесса или его реализации, я снова хотел бы услышать о вашем проекте, а моя компания Permutable предлагает консультационные услуги, поэтому, пожалуйста, не стесняйтесь обращаться к нам.