Обширное эссе о том, как выбрать правильную задачу и как разработать базовый классификатор

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

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

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

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

Выбор правильной задачи для ML

Хотя машинное обучение может решить множество проблем, это не универсальный подход. Даже если бы мы временно забыли о финансовых, временных и других затратах ресурсов, модели машинного обучения по-прежнему были бы хороши в одних вещах и ужасны в других.

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

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

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

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

В поисках практического применения

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

Я решил выбрать категоризацию слов, так как о ней не так часто писали, и у нее есть некоторое практическое применение. У нашей SEO-команды было интересное предложение — им нужно было классифицировать ключевые слова по трем типам:

  1. Информация — пользователи, которые ищут знания по теме (например, «что такое прокси-сервер»).
  2. Транзакционный — пользователи ищут продукт или услугу (например, «лучшие прокси»).
  3. Навигация — пользователи, которые ищут определенный бренд или его ответвление (например, Oxylabs).

Категоризация тысяч ключевых слов вручную немного утомительна. Такая задача кажется (почти) идеальной для машинного обучения, хотя есть неотъемлемая проблема, которую почти невозможно решить, о которой я расскажу позже.

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

Создание pre-MVP

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

Я бы предостерег от одной вещи: сначала нужно работать со всем набором данных. Поскольку, скорее всего, вы разрабатываете модель впервые, многое может пойти не так. В общем, лучше писать код и запускать его на небольшой выборке (например, 10% от общего числа), чтобы убедиться в отсутствии семантических ошибок и прочих ужасов.

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

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

Библиотеки

  1. Панды. Хотя это и не является строго необходимым, чтение и экспорт в CSV значительно облегчит нам жизнь.
  2. SciKit-Learn. Достаточно мощная и гибкая библиотека машинного обучения, которая станет основой нашей модели классификации. В этом руководстве мы будем использовать различные функции sklearn.
  3. NLTK (Инструментарий естественного языка). Поскольку мы будем обрабатывать естественный язык, NLTK отлично справится с этой задачей. Стоп-слова абсолютно необходимы из пакета.

Импорт

import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.feature_selection import SelectKBest, chi2
from nltk.corpus import stopwords

Линия 1

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

Линия 2

Из библиотеки SciKit-Learn мы возьмем несколько вещей, в первую очередь TfidfVectorizer.

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

Предложение 1: "Собака коричневая".

Предложение 2: "Собака черная".

Векторизация возьмет оба предложения и создаст индекс:

E(w) = 
[0, if "the"
1, if "dog"
2, if "is"
3, if "brown"
4, if "black"]

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

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

Линия 3

Логистическая регрессия — это один из способов обнаружения взаимосвязей между переменными. Поскольку наша задача является классическим примером классификации, логистические регрессии работают отлично, поскольку они берут некоторую входную переменную x(ключевое слово) и присваивают ей значение y (информационный/транзакционный/навигационный).

Существуют и другие варианты, такие как LinearSVC, который включает значительно более сложную математику. Проще говоря, SVC берет несколько кластеров точек данных и находит в каждом из них значения, наиболее близкие к противоположному кластеру (кластерам). Они называются опорными векторами.

Гиперплоскость (т. е. n-мерный геометрический объект в n+1-мерном пространстве) нарисована таким образом, что расстояния между ним и каждым опорным вектором равны максимизирован.

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

Линия 4

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

Строка 5

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

Chi2 (или хи-квадрат) — это статистический тест на независимость переменных, который помогает нам выбирать лучшие функции (отсюда SelectKBest) для обучение:

where: c is degrees of freedom (i.e. sample size minus one)
O is the observed value(s)
E is the expected value(s)

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

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

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

Строка 6

Наш окончательный импорт — из NLTK, который мы будем использовать только для списка стоп-слов. К сожалению, список по умолчанию не подходит для нашей задачи. Большинство таких списков включают такие слова, как «как», «что», «почему» и многие другие, которые, хотя и бесполезны в обычной категоризации, указывают на цель поиска.

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

Таким образом, удаление некоторых записей из списка стоп-слов жизненно важно. К счастью, стоп-слова NLTK — это просто текстовые файлы, которые можно редактировать в любом текстовом редакторе.

Загрузки NLTK по умолчанию хранятся в пользовательских каталогах, но при необходимости их можно изменить с помощью download_dir=.

Фреймы данных и стоп-слова

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

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

Прежде чем продолжить, было бы разумно выбрать несколько десятков ключевых слов из файла CSV и пометить их. Как только мы доберемся до рабочей модели, мы можем пометить остальные. Поскольку Pandas создает фреймы данных в табличном формате, проще всего просто добавить новый столбец «Категория» или «Ярлык» и присвоить каждой строке ключевого слова значение Информационное, Транзакционное или Навигация.

df = pd.read_csv('[KEYWORD_LIST].csv')
data = pd.DataFrame(df)

words = stopwords.words('english_adjusted')

Строка 1 и 2

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

После прочтения файла мы создаем объект dataframe из нашего CSV.

Линия 3

Мы будем использовать NLTK для захвата файла стоп-слов, однако мы не можем использовать его как есть. По умолчанию NLTK включает много слов, которые мы считаем важными для категоризации ключевых слов (например, «что», «как», «где» и т. д.). Таким образом, его нужно будет скорректировать в соответствии с нашими целями.

Хотя в таком случае нет жестких и быстрых правил, неопределенные и определенные артикли могут оставаться (например, «a», «an», «the» и т. д.), поскольку они не несут никакой информации. Однако все, что потенциально может показать намерение пользователя, должно быть удалено из файла по умолчанию.

Я создал копию под названием «english_adjusted», чтобы упростить себе задачу. Кроме того, если мне по какой-либо причине понадобится исходная версия, она всегда будет доступна без повторной загрузки.

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

Настройка конвейера

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

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

pipeline = Pipeline([('vect', TfidfVectorizer(ngram_range=(1, 3), stop_words=words)),
                    ('chi', SelectKBest(chi2, k='all')),
                    ('clf', LogisticRegression(C=1.0, penalty='l2', max_iter=1000, dual=False))])

Некоторые могут заметить, что я не разделяю набор данных на поезд и тестовое разделение с помощью scikit-learn. Опять же, это роскошь, которую дает природа проблемы. Инструменты SEO могут экспортировать тысячи (немаркированных) ключевых слов менее чем за минуту, а это означает, что вы можете приобрести тестовый набор отдельно без особых усилий.

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

Линия 1

Pipeline позволяет нам обрезать и упрощать длинные процессы в один объект, что значительно упрощает работу с настройками модели. Это также снизит вероятность совершения ошибок.

Мы начнем с определения нашего векторизатора. Выше я отметил, что мы будем использовать TFIDFVectorizer, так как он дает лучшие результаты благодаря способу взвешивания слов, найденных в документах. CountVectorizer — это вариант, однако его придется импортировать, и результаты могут отличаться.

Ngram_range – это интересная задача на рассуждение. Чтобы получить наилучшие результаты, вы должны решить, сколько токенов (в нашем случае слов) нужно подсчитать. Ngram_range из (1, 1) будет принимать одно слово (униграмма), из (1, 2) будет принимать как одно слово, так и два ближайших (биграмма) в комбинации, из (1, 3 ) будет состоять из одного слова, двух и трех (триграмм) в комбинации.

Я выбрал ngram_range(1, 3) по нескольким причинам. Во-первых, поскольку модель относительно проста и производительность не является проблемой, я могу позволить себе запускать больший диапазон ngram, поэтому нижнюю границу можно установить минимальной.

С другой стороны, как только мы удалим стоп-слова, мы должны подумать о том, какой верхней части ngram будет достаточно, чтобы подобрать значение из ключевых слов. Если возможно, мне будет проще выбрать самые сложные и самые простые примеры из набора данных. В нашем случае самые простые примеры — это любой вопрос («как получить прокси»), а самые сложные — существительные («парсер») или имена («Оксилабы»)

Так как мы будем убирать такие слова, как «to», мы получаем триграмму в вопросительных падежах («как получить прокси»), что совершенно ясно. Фактически, вы могли бы привести аргумент, что биграммы («как получить») достаточно, поскольку намерение все еще ясно.

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

Наконец, есть аргумент в пользу sublinear_tf, который является модификацией обычных вычислений TF-IDF. Если установлено значение True,вес вычисляется с помощью логарифмической функции: 1 + log(tf). Другими словами, частота терминов получает убывающую отдачу.

При использовании sublinear_tf слова, которые встречаются часто и во многих документах, не будут иметь такого большого веса. Поскольку у нас есть набор несколько случайных ключевых слов, мы никогда не знаем, какие из них получают предпочтение, однако часто это могут быть такие термины, как «как», «что» и т. Д., Которые мы хотели бы, чтобы они были сильно взвешены. .

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

Параметр Стоп-слова на данный момент говорит сам за себя, как мы обсуждали ранее.

Линия 2

Хотя технически это не новая строка, я буду выделять их для ясности и краткости. Теперь мы будем вызывать SelectKBest, о котором я довольно подробно писал выше. Нас интересует значение k.

Они будут разными, в зависимости от размера вашего набора данных. SelectKBest предназначен для оптимизации производительности и точности. В моем случае отправка «всех» работает, но обычно вам нужно выбрать достаточно большое N, соответствующее вашему собственному набору данных.

Линия 3

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

«C»значение — это гиперпараметр, который сообщает модели параметры, которые она должна выбрать. Гиперпараметры — очень сложные части модели, оказывающие огромное влияние на конечные результаты.

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

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

Параметр штрафа — это операция, которая будет использоваться для гиперпараметра. SciKit-Learn предлагает три типа штрафов — 'l1', 'l2' и 'elasticnet'. «Нет» также является вариантом, но его следует использовать с осторожностью, если вообще нужно.

L1’ – это абсолютная сумма величины всех коэффициентов. Проще говоря, он стягивает все коэффициенты к некоторой центральной точке. Если применяются большие штрафы, некоторые точки данных могут стать нулевыми (т. е. быть исключенными).

«L1» следует использовать в случаях, когда имеется мультиколлинеарность (несколько переменных коррелируют) или когда вы хотите упростить модель. Поскольку l1 исключает некоторые точки данных, модели почти всегда становятся проще. Однако это не работает, когда у вас уже есть относительно простое распределение точек данных.

«L2» — это другая версия аналогичного процесса. Это не абсолютная сумма, а сумма квадратов всех значений коэффициентов. Таким образом, все коэффициенты уменьшаются на одинаковое значение, но ни один из них не удаляется. «L2» — это параметр по умолчанию, поскольку он является наиболее гибким и редко вызывает проблемы.

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

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

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

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

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

Подгонка модели и вывод данных

Мы приближаемся к концу урока, когда мы, наконец, подойдем к модели и получим результат.

model = pipeline.fit(data.Keyword, data.Type)
chi = model.named_steps['chi']
clf = model.named_steps['clf']

doutput = pd.read_csv('[TEST_KEYWORD_LIST].csv')

doutput['Type'] = model.predict(doutput['Keyword'])

doutput.to_csv('[RESULT_LIST].csv')
##print('Accuracy score ' + str(model.score(x_test, y_test)))

Строка 1–3

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

Строка 4–8

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

Поскольку наш фрейм данных содержит только ключевые слова, мы добавляем новый столбец «тип» и запускаем model.predict, чтобы предоставить нам выходные данные.

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

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

Тем не менее, оценки полезны как эмпирическое правило и как быстрый способ оценить, оказали ли параметры какое-либо влияние на модель. Хотя существует множество методов оценки, базовая model.score использует R в квадрате, что полезно в большинстве случаев, когда мы настраиваем параметры.

Изучение результатов

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

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

Есть одна область, с которой модель боролась — ключевые слова для навигации. Если бы я мог предположить, модель правильно предсказывала категорию примерно в 5–10% случаев. Причин такого явления несколько.

Можно обвинить распределение набора данных, поскольку оно сильно несбалансировано:

  • Транзакции — 0,457353%
  • Информационная — 0,450735%
  • Навигация — 0,091912%

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

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

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

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

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

Поскольку разработка функций — это совершенно другая тема, которая заслуживает отдельной статьи, я приведу один пример. Навигационные ключевые слова редко будут запрашиваться как вопросы (кроме «что есть»), поскольку в противном случае они не имели бы смысла (например, «как получить Oxylabs», «как получить Oxylabs»).

Существует спорный вопрос о том, будет ли «как получить прокси Oxylabs» считаться транзакционным или навигационным. Однако он определенно вписывается в категорию транзакций, поэтому его можно считать таковым.

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

Кроме того, многие навигационные ключевые слова имеют значительно меньшую длину запроса, в основном состоящую из одного слова, в то время как другие категории имеют такую ​​же длину относительно редко.

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

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

Заключение

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

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

  1. Выбор правильной проблемы. Некоторые проблемы просто лучше решаются с помощью других подходов. Не поддавайтесь ажиотажу и пытайтесь решить все с помощью машинного обучения. С системами, основанными на правилах, вы можете сэкономить время и ресурсы, получая при этом еще лучшие результаты.
  2. Подготовка данных. Модель будет настолько хороша, насколько хороши данные. Если ваши данные помечены неправильно, недостоверны или ошибочны по какой-либо иной причине, никакие разработки и ресурсы не создадут что-то, что создаст надежные результаты.
  3. Выбор модели. Легко использовать по умолчанию логистическую регрессию или любую другую модель, потому что вы делали это так много раз. В Sci-Kit Learn есть и другие варианты, о которых я даже не упоминал, такие как PassiveAggressiveClassifier, в которых используются другие математические подходы. Опять же, я подчеркиваю важность выбора правильной проблемы, поскольку она должна решить, какой метод моделирования вы выберете.

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

Приложение: Исходный полный блок кода

import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from nltk.corpus import stopwords
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.feature_selection import SelectKBest, chi2

df = pd.read_csv('[KEYWORD_LIST].csv')
data = pd.DataFrame(df)

words = stopwords.words('english_adjusted')

pipeline = Pipeline([('vect', TfidfVectorizer(ngram_range=(1, 3), stop_words=words)),
                    ('chi', SelectKBest(chi2, k='all')),
                    ('clf', LogisticRegression(C=1.0, penalty='l2', max_iter=1000))])

model = pipeline.fit(data.Keyword, data.Type)
chi = model.named_steps['chi']
clf = model.named_steps['clf']

doutput = pd.read_csv('[TEST_KEYWORD_LIST].csv')

doutput['Type'] = model.predict(doutput['Keyword'])

doutput.to_csv('[RESULT_LIST].csv')
##print('accuracy score ' + str(model.score(x_test, y_test)))

Приложение II: Train_test_split

Импорт

import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split
from sklearn.feature_selection import SelectKBest, chi2
from nltk.corpus import stopwords

Как обычно, нам нужно импортировать сам train_test_split (строка 5).

Настройка разделения

x_train, x_test, y_train, y_test = train_test_split(data.Keyword, data.Type, test_size=0.3)

pipeline = Pipeline([('vect', TfidfVectorizer(ngram_range=(1, 3), stop_words=words)),
                    ('chi', SelectKBest(chi2, k='all')),
                    ('clf', LogisticRegression(C=1.0, penalty='l2', max_iter=1000, dual=False))])

Линия 1

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

Возьмем фрейм данных, созданный на предыдущих шагах, и присвоим имена столбцам (в моем наборе данных они назывались «Ключевое слово» и «Тип», о чем свидетельствуют параметры).

Наконец, SciKit-Learn решает проблемы с разделением данных за нас, позволяя автоматически разделять оба набора. train_test_split принимает значения с плавающей запятой и целые числа, которые представляют собой проценты, используемые либо для размера тестового набора, либо для размера обучающего набора. Если для обоих оставить значение Нет, по умолчанию будет установлено значение 0,25.

Для достижения наилучших результатов потребуется некоторая доработка. Я пробовал много разных сплитов, но 0,3 дал наилучшие результаты. Как правило, вы обнаружите, что многие модели лучше всего работают при сплитах от 0,2 до 0,3.

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

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

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

Все остальное в этом блоке кода следует тем же шагам, что и в исходном руководстве.

Подгонка модели и вывод данных (снова)

model = pipeline.fit(x_train, y_train)
chi = model.named_steps['chi']
clf = model.named_steps['clf']

doutput = pd.DataFrame({'Keyword': x_test, 'Type': model.predict(x_test)})

doutput.to_csv('[RESULT_LIST].csv')
##print('Accuracy score ' + str(model.score(x_test, y_test)))

Линия 1

Вместо того, чтобы обучать нашу модель непосредственно на помеченном наборе данных, мы будем обучать ее на ранее разделенном наборе данных, назвав x_train и y_train. Строки 2 и 3 остаются идентичными.

Линия 4

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

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