Рубрики
Без рубрики

Введение в машину обучения с Python и reft.it

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

Автор оригинала: Gareth Dwyer.

Примечание: этот учебник – это выдержка из Код с reft.it: Python Projects для начинающих , книга и набор учебных пособий для начинающих, чтобы получить практический опыт работы с программированием Python.

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

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

В конце этого учебника вы поймете фундаментальные идеи автоматической классификации и иметь программу, которая может учиться самостоятельно различать различные категории текста. Вы сможете использовать тот же код для изучения новых категорий (например, SPAM/Not-Spam или ClickBait/Non-Clickbait).

Обзор и требования

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

В этом руководстве мы будем:

  • Создайте несколько простых данных MOCK – текст для классификации как положительный или отрицательный
  • Объясните векторизация набора данных
  • Обложка, как классифицировать текст, используя классификатор машинного обучения
  • Сравните это с ручным классификатором

Установка

Создайте новый Python REPL и откройте main.py Файл, который rack создан для вас автоматически. Добавьте следующие два импорта в верхнюю и запустите REFL так, чтобы эти зависимости установлены.

from sklearn import tree
from sklearn.feature_extraction.text import CountVectorizer

В строке 1, мы импортируем дерево Модуль, который даст нам классификатор дерева решений, который может учиться у данных. В строке 2 мы импортируем вектора – то, что может повернуть текст в цифры. Мы опишем каждый из них более подробно в ближайшее время!

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

Создание некоторых данных

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

На следующих строках Main.py добавьте следующие строки кода.

positive_texts = [
    "we love you",
    "they love us",
    "you are good",
    "he is good",
    "they love mary"
]

negative_texts =  [
    "we hate you", 
    "they hate us",
    "you are bad",
    "he is bad",
    "we hate mary"
]

test_texts = [
    "they love mary",
    "they are good",
    "why do you hate mary",
    "they are almost always good",
    "we are very bad"
]

Мы создали три простых набора данных из пяти предложений каждый. Первый содержит положительные предложения; второй содержит отрицательные предложения; И последний содержит смесь положительных и отрицательных предложений.

Сразу явно очевидно для человека, какие предложения положительны, и которые негативны, но можем ли мы научить компьютеру рассказать им отдельно?

Мы будем использовать два списка Pложительные_текты и отрицательно_texts к Поезд Наша модель. То есть мы покажем эти примеры к компьютеру вместе с правильными ответами на вопрос «Это положительный текст или отрицательный?». Компьютер постарается найти правила, чтобы рассказать разницу, а затем мы проверим, насколько хорошо она сделала, давая ей test_texts Без ответов и попросите его угадать, является ли каждый пример положительным или отрицательным.

Понимание векторизации

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

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

[«Хорошая пицца хорошая»], [«Что такое пицца»]

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

{
    "nice": 0,
    "pizza": 1,
    "is": 2,
    "what": 3
}

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

[
    [2, 1, 1, 0], # two "nice", one "pizza", one "is", zero "what"
    [0, 1, 1, 1]  # zero "nice", one "pizza", one "is", one "what"
]

Каждое вектор предложений всегда такая же длина, как Всего Словарный размер. У нас всего четыре слова (во всех наших предложениях), поэтому каждое предложение представлено массивом длиной четыре. Каждая позиция в массиве представляет слово, и каждое значение представляет, как часто это слово появляется в этом предложении.

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

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

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

Давайте посмотрим, как достичь вышеприведенного с использованием оптимизированного вектора Scikit-Learn.

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

training_texts = negative_texts + positive_texts
training_labels = ["negative"] * len(negative_texts) + ["positive"] * len(positive_texts)

Наш набор данных теперь выглядит так:

['we hate you', 'they hate us', 'you are bad', 'he is bad', 'we hate mary', 'we love you', 'they love us', 'you are good', 'he is good', 'they love mary']
['negative', 'negative', 'negative', 'negative', 'negative', 'positive', 'positive', 'positive', 'positive', 'positive']

Две массивы (тексты и этикетки) связаны по индексу. Первый текст в первом массиве отрицателен и соответствует первой метке во втором массиве и так далее.

Теперь нам нужен векторный вектора, чтобы преобразовать тексты в цифры. Мы можем создать один в Scikit – учись с

vectorizer = CountVectorizer()

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

vectorizer.fit(training_texts)

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

print(vectorizer.vocabulary_)

(Обратите внимание на подчеркивание в конце. Scikit-Nearn использует это как конвенцию для атрибутов «помощника». Сопоставление явно только для целей отладки, и вам не нужно его использовать в большинстве случаев). Мой словарный сопоставление выглядит следующим образом:

{'we': 10, 'hate': 3, 'you': 11, 'they': 8, 'us': 9, 'are': 0, 'bad': 1, 'he': 4, 'is': 5, 'mary': 7, 'love':6, 'good': 2}

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

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

training_vectors = vectorizer.transform(training_texts)
testing_vectors = vectorizer.transform(test_texts)

Первая строка создает список векторов, которые представляют собой все тренировочные тексты, все еще в том же порядке, но теперь каждый текст – вектор цифр вместо строки.

Вторая строка делает то же самое с тестовыми векторами. Часть обучения машины не смотрит на наши тестовые тексты (которые будут обманывать) – это просто отображает слова к номерам, чтобы он мог работать с ними легче. Обратите внимание, что когда мы позвонили Fit () На векторе мы только показали это тренировочные тексты. Поскольку в тестовых текстах есть слова, которые не появляются в текстах тренировок, эти слова будут просто проигнорированы и не будут представлены в testing_vectors Отказ

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

Понимание классификации

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

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

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

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

Добавьте следующие строки в main.py :

classifier = tree.DecisionTreeClassifier()
classifier.fit(training_vectors, training_labels)
predictions = classifier.predict(testing_vectors)
print(predictions)

Аналогично в векторах мы сначала создаем классификатор, используя модуль, который мы импортировали в начале. Тогда мы называем Fit () На классификаторе и пройти в наших тренировочных векторах и связанных с ними этикетки. Дерево решений будет посмотреть на обоих и попытаться изучить правила, которые разделяют два вида данных.

Как только наш классификатор обучен, мы можем позвонить в прогнозировать () Способ и пройти в ранее невидимые данные. Здесь мы проходим в testing_vectors Какой список векторизованных тестовых данных о том, что компьютер не смотрел во время тренировки. Он должен попытаться применить правила, которые он узнал из учебных данных к этому новым «невидимым» данным. Машинное обучение довольно круто, но это не волшебство, поэтому нет никаких гарантий, что правила, которые мы узнали, будут еще хорошими.

Код выше производит следующий выход:

['positive' 'positive' 'negative' 'positive' 'negative']

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

"they love mary"
"they are good"
"why do you hate mary"
"they are almost always good"
"we are very bad"

Выходные карты на вход по индексу, поэтому первая выходная метка («положительный») соответствует первому входному тексту («они любят Мэри»), а последняя выходная этикетка («отрицательный») соответствует последнему входу. Текст («Мы очень плохо»).

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

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

Scikit-Surrey дерево Модуль содержит полезную функцию для помощи в визуализирующих деревьях. Добавьте следующий код в конец вашего reft:

import matplotlib.pyplot as plt
fig = plt.figure(figsize=(5,5))
tree.plot_tree(classifier,feature_names = vectorizer.get_feature_names(), rounded = True, filled = True) 
fig.savefig('tree.png')

В левой панели вы должны увидеть файл под названием «Tree.png». Если вы откроете его, график вашего дерева должен выглядеть следующим образом:

Визуализированное дерево решений

Выше показана дерево решений, которое выучило только два правила. Первое правило (верхняя площадь) о словах «ненависти». Правило – это «количество временных ненавистков» происходит в этом предложении меньше или равно 0,5 дюйма. Ни одно из наших предложений не содержит дублирующихся слов, поэтому каждое правило действительно будет только о том, появляется ли слово или нет (вы можете подумать об <= 0,5 правила как <1 в этом случае).

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

После того, как мы задали этот первый вопрос для каждого предложения в нашем наборе данных, у нас будет три предложения, для которых ответ «ложный», потому что три наших приговора на обучение содержат слово «ненависть». Эти три предложения идут прямо в дереве решений и в конечном итоге на первом узле листьев (конечный узел без стрелков не выходит вниз). Этот узел листьев имеет значение = [3,0] В этом, что означает, что три образца достигают этого узла, а три принадлежат к отрицательному классу и ноль до положительного класса.

Для каждого предложения, когда первое правило «True» (слово «ненависть», появляется менее чем в 0,5 раза или в нашем случае 0 раз), мы спускаемся по левой части дерева, к узлу, где значение = [2,5] Отказ Это не узел листьев (у него больше стрелок выходит на дно), поэтому мы еще не закончены. На данный момент у нас есть два негативных предложения и все еще пять положительных предложений.

Следующее правило «плохое 5». Точно так же, как и раньше, мы пойдем вниз по правильному пути, если у нас есть более 0,5 вхождений «плохого» и осталось, если у нас будет меньше 0,5 вхождений «плохого». За последние два негативных предложения мы все еще оцениваем (два, содержащие «плохое»), мы пойдем правильно и в конечном итоге на узле с значение = [2,0] Отказ Это еще один узел листьев, и когда мы получаем здесь, у нас есть два негативных предложения и нулевые положительные.

Все остальные данные будут оставаться влево, и мы в конечном итоге по адресу [0,5] или нулевые негативные предложения и пять положительных.

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

Создание ручного классификатора

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

def manual_classify(text):
    if "hate" in text:
        return "negative"
    if "bad" in text:
        return "negative"
    return "positive"

predictions = []
for text in test_texts:
    prediction = manual_classify(text)
    predictions.append(prediction)
print(predictions)

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

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

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

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

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

Вы можете вилочную репс здесь: https://repl.it/@garethdwyer1/machine-learning-intro Чтобы взломать на нем (это тот же код, поскольку мы ходили выше, но с добавленными комментариями.) Если вы предпочитаете, вся программа отображается в конце этого урока, поэтому вы можете скопировать его и работать оттуда.

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

from sklearn import tree
from sklearn.feature_extraction.text import CountVectorizer
import matplotlib.pyplot as plt

positive_texts = [
    "we love you",
    "they love us",
    "you are good",
    "he is good",
    "they love mary"
]

negative_texts =  [
    "we hate you", 
    "they hate us",
    "you are bad",
    "he is bad",
    "we hate mary"
]

test_texts = [
    "they love mary",
    "they are good",
    "why do you hate mary",
    "they are almost always good",
    "we are very bad"
]

training_texts = negative_texts + positive_texts
training_labels = ["negative"] * len(negative_texts) + ["positive"] * len(positive_texts)

vectorizer = CountVectorizer()
vectorizer.fit(training_texts)
print(vectorizer.vocabulary_)

training_vectors = vectorizer.transform(training_texts)
testing_vectors = vectorizer.transform(test_texts)

classifier = tree.DecisionTreeClassifier()
classifier.fit(training_vectors, training_labels)

print(classifier.predict(testing_vectors))

fig = plt.figure(figsize=(5,5))
tree.plot_tree(classifier,feature_names = vectorizer.get_feature_names(), rounded = True, filled = True) 
fig.savefig('tree.png') 

def manual_classify(text):
    if "hate" in text:
        return "negative"
    if "bad" in text:
        return "negative"
    return "positive"

predictions = []
for text in test_texts:
    prediction = manual_classify(text)
    predictions.append(prediction)
print(predictions)