В течение этого осеннего семестра 2018 года я вместе с Юргеном Сито разработал MIT Smart Confessions, веб-сайт, который использует машинное обучение (ML) как для генерации признаний MIT, так и для прогнозирования реакций, которые можно было бы получить из их признаний. Это было написано в рамках класса 6.s198 (Практика глубокого обучения), который проводили Натали Лао и Хэл Абельсон.

В этом посте я расскажу о том, что такое MIT Smart Confessions, о работе, связанной с созданием этого веб-приложения, а также о результатах и ​​идеях, которые я получил от работы над этим проектом.

Если вы просто хотите увидеть код этого проекта, перейдите на этот Github для API или на этот Github для веб-сайта.

Что такое признание Массачусетского технологического института?

MIT Confessions - это страница в Facebook, которая позволяет студентам MIT анонимно публиковать признания - короткие, обычно секретные отрывки текста. Люди, которые следят за этой страницей (обычно филиалы Массачусетского технологического института), затем могут реагировать или отвечать на анонимные признания. Ниже приведены несколько примеров того, что вы ожидаете увидеть на странице признаний Массачусетского технологического института:

Цель проекта: предсказывать и генерировать признания

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

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

Учитывая, что подсказкой проекта в 6.s198 было «работа над проектом машинного обучения по вашему выбору», я подумал, что это будет прекрасная возможность узнать больше о машинном обучении и поработать над тем, что мне было интересно. Так началась идея создания MIT Smart Confession, и Юрген Сито присоединился ко мне, чтобы работать над этим проектом.

Сбор данных из Facebook: большое препятствие

Сбор данных

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

  • Признания Массачусетского технологического института: Это, вероятно, первая и исходная страница признаний Массачусетского технологического института. Он был основан 19 февраля 2013 года, и по состоянию на 2 декабря у него было 28 527 лайков; Далее следует 29 275 страниц; и 17 755 опубликованных признаний с ярлыками¹.
  • Своевременные признания Массачусетского технологического института: Эта страница признаний началась из-за того, что Признания Массачусетского технологического института была приостановлена ​​примерно на год, и закрылась из-за возвращения признаний из Массачусетского технологического института. Он был основан 27 октября 2017 года, и по состоянию на 2 декабря у него было 2960 лайков; Далее следует 3,335 страниц; и 7 422 опубликованных признания с ярлыками¹.
  • Летние признания Массачусетского технологического института: Летом обе вышеуказанные страницы признаний перестали публиковаться, поэтому Летние признания Массачусетского технологического института начинались как способ побудить людей писать сообщения в течение лета. Он был основан 29 мая 2018 года и по состоянию на 2 декабря набрал 914 лайков; 1057 страниц следует; и 2 462 опубликованных признания с ярлыками¹.

Теперь, когда все, что происходило с Facebook, и по мере того, как Facebook росла как компания, они начали вводить массу дополнительных ограничений на то, как можно извлекать из них данные. Они создали так много препятствий для парсинга, что вы в значительной степени вынуждены использовать их Graph API (если вы не хотите выполнять много ручной работы). Например, вот некоторые из их действий, которые затрудняют получение данных от них, если вам интересно:

  • Очистка данных не является вариантом, потому что Facebook не только лениво загружает контент на данной веб-странице, но также загружает страницу таким образом, что имена HTML class и id являются случайными, а структура div несколько случайна (или действительно сложно понять), а уровень вложенности элементов HTML невероятно глубок и запутан.
  • Другая причина, по которой парсинг не является вариантом, заключается в том, что Facebook определит, очищает ли бот данную страницу, и остановит его продолжение, и даже если кому-то удастся создать бота, который скребет как человек, они все равно столкнутся с проблемами, указанными выше.
  • Если у вас более 21000 признаний, то потребуется очень много времени, чтобы вручную собрать всю необходимую информацию о каждом признании.

Итак, используя Graph API, который, в свою очередь, имеет дополнительные ограничения, мне приходилось сообщать администратору каждой страницы признаний, просить их сгенерировать для меня access token, а затем использовать его для извлечения данных в течение 1-2-часового окна, которое у меня было. до истечения срока действия этого токена доступа. Согласование с людьми, признавшимися, было очень сложно, учитывая, что они хотят сохранить свою личность в секрете, они студенты MIT (т.е. они заняты), и им пришлось сгенерировать access token таким образом, чтобы я мог только получить информацию что я хотел получить (т.е. информацию о странице и признательные сообщения). В итоге я получил access token от MIT Confessions, что очень помогло собрать около 1500 примеров. MIT Summer Confessions предоставил около 3000 признаний в файле CSV, которые я объединил с тем, что я получил от MIT Confessions. Мы не смогли согласовать токен доступа, потому что либо я был занят, когда они отправили его мне, либо они были заняты, когда я был готов собрать данные с помощью access token. В конце концов, MIT Timely Confessions так и не вернулся ко мне.

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

Если вас интересуют данные, вы можете найти их здесь.

Наблюдения за данными

В совокупности мы можем наблюдать за данными следующее:

  • Данные сильно искажены в сторону низких значений. То есть, гораздо более вероятно, что любое данное признание получит 0 лайков, чем 1 лайк, что имеет больше шансов, чем 2, которое имеет больше шансов, чем 3, и т. Д. Это становится особенно более искаженным, когда мы начинаем погружаться в нестандартные реакции facebook (любовь, ух ты, ха-ха, грусти, злой).
  • Около 67% собранных признаний получают 0 отзывов (включая комментарии). Опять же, это показано, насколько искажены данные.
  • Признания, которые вызывают наибольшую реакцию, состоят от 75 до 175 символов. Чем дольше это, тем труднее получить признание на признание. Ниже этого, это скорее вопрос случая и остроумия человека, написавшего признание.
  • Большинство признаний состоит из 74–144 символов.
  • Большинство реакций обратно коррелируют друг с другом. то есть чем больше лайков, тем меньше всего остального. Это имеет смысл. Есть смешные признания (много ха-ха), приятные признания, милые признания и т. Д .; Каждое признание в той или иной степени передает определенные чувства сообщества MIT.
  • Реакция Facebook, не связанная с подобной реакцией, началась 24 февраля 2016 года, так что это означает, что мы не знаем реакции признаний до этой даты.

Кроме того, вот несколько графиков, которые дополнительно демонстрируют следующие наблюдения:

Как вы думаете, можно ли найти в данных какой-либо другой шаблон? Вы можете найти данные в репозитории API Github и провести дополнительный анализ (также проверьте каталог /data/analysis, чтобы увидеть больше графиков, если вы хотите сгенерировать больше графиков - была извлечена CSV-версия данных).

Очистка данных

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

Немного предыстории машинного обучения

Алгоритм машинного обучения - это, по сути, функция h, которая ожидает ввода input и выдает результат prediction. В контексте контролируемого обучения этот алгоритм учится, получая истинный ожидаемый результат y (который мы называем меткой, поэтому с этого момента я буду использовать label), из которого он может вычислить loss ( число, описывающее, насколько плох этот прогноз, вычисляется с использованием функции потерь) и используйте это значение loss, чтобы лучше предсказать, когда он в следующий раз увидит то же самое input снова. С учетом сказанного, алгоритм машинного обучения - это просто набор математических вычислений, которые приводят к заданному результату prediction, поэтому все входные и выходные данные являются числами! Однако часто наши входные данные не являются числами (например, изображения, тексты, категории, трехмерные карты и т. Д.) Или не являются числами, которые мы хотим (например, вам может быть дано число, но вы хотите отклонение от среднего в качестве входных данных) . Итак, чтобы добраться до input, нам нужно предварительно обработать raw_data и очистить raw_data, чтобы преобразовать его в input. Итак, в целом:

convert raw data: raw_data -> input 
create prediction: h(input) -> prediction
compute loss: loss_function(prediction, label) -> loss
update h based on loss

Критическим шагом является обновление h после вычисления потерь. Это шаг обратного распространения в нейронных сетях.

Наша проблема

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

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

  • Что касается длины символа, то среднее количество символов в любых признаниях составляло 229.16 символа, но, если посмотреть дальше, у нас было несколько выбросов, которые искажали среднее значение. Итак, мы решили вырезать все признания, у которых в генераторе было более 600 символов, и все, что имеет более 400 символов в предсказании. Таких было всего несколько. Среднее значение без признаний, состоящих из более 600 символов, составляет 159.45 символов. Среднее значение без признаний, состоящих из более чем 400 символов, составляет 136.07 символов.
  • Что касается ярлыков, у нас определенно было слишком много ярлыков с низкими значениями и слишком мало с высокими значениями. Итак, я решил удалить некоторые перенасыщенные значения (особенно те, у которых было 0 реакций) и - некоторые эксперты по машинному обучению, вероятно, съежатся от этой идеи - продублировать некоторые из редких значений (например, признания, у которых было более 50 реакций, были довольно редкими. ) для предсказателя. Это не было проблемой для генератора, поскольку он не работает с этикетками.
  • При обучении некоторые символы отвлекают, поэтому мы решили убрать многие знаки препинания (но сохранили следующее: !?.,). В идеале мы также хотим удалить слова, которые появляются слишком часто, но это может нарушить наш алгоритм генерации, поэтому мы оставили их (такие слова, как I, you, me и т. Д.).

У нас просто не было достаточно данных для работы (4555 - это очень мало! Нам нужно гораздо больше). Итак, мы были ограничены в том, что мы могли с этим сделать. Как вы увидите, наши модели сильно переоснащены.

Модели машинного обучения

Для наших нужд, связанных с машинным обучением, мы писали наши программы на python3 и использовали модули python Keras и Tensorflow.

Обзор: Слово к последовательностям и наоборот

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

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

Кроме того, мы использовали Предварительную обработку последовательностей Кераса: pad_sequences. Суть работы ML с текстом заключается в том, что ML всегда ожидает ввода одного и того же размера (за некоторыми исключениями). Итак, что нам нужно было сделать, так это дополнить последовательности так, чтобы количество элементов в последовательностях соответствовало самой длинной последовательности в наборе данных, и использовать это в качестве нашего входного размера. Мы дополняем последовательности фиктивным словом блокнот (которое в нашем случае мы использовали 0 в качестве индекса слова блокнота).

Например: допустим, у нас есть 3 слова «я», «нравится» и «чай». Затем мы используем токенизатор, чтобы получить следующее слово для индексации карты:

   I <-> 1
like <-> 2
 tea <-> 3

Тогда, если у нас есть следующее предложение: «Я люблю, как чай», то оно будет преобразовано в последовательность [1, 2, 2, 2, 3]. Наконец, если самое длинное предложение - «Мне нравится, мне нравится, мне нравится, я люблю чай» (всего 9 слов), то мы получаем дополненную последовательность [1, 2, 2, 2, 3, 0, 0, 0, 0] (добавляйте 5 нулей к правильной длине совпадения 9).

Наконец, нам нужно было выполнить вложение слов, которое преобразует индекс в вектор чисел. Например, он может преобразовать 1 в некоторый вектор [0.12, -0.05, 1.14, 1.02] (это всего лишь пример). Итак, наша последовательность ([1, 2, 2, 2, 3]) станет примерно такой:

[
  [0.12, -0.05, 1.14, 1.02],
  [0.52, 1.05, -2.14, 0.02],
  [0.52, 1.05, -2.14, 0.02],
  [0.52, 1.05, -2.14, 0.02],
  [3.52, -1.5, 0.14, -0.07],
]

Я составил эти векторы, чтобы показать вам пример.

Первая модель: классификатор

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

«Ведро» - это диапазон количества реакций. Если мы смотрим на количество лайков, которые получит признание, то диапазон корзины может составлять 0-10 лайка или 11-20 лайка. Наша модель пытается предсказать наиболее вероятный сегмент. Итак, если бы два вышеупомянутых сегмента были единственными, результат был бы примерно таким:

 0-10: 0.1
11-20: 0.9

То есть с 10% шансом, что признание получит от 0 до 10 лайков, и с вероятностью 90%, что оно получит от 11 до 20 лайков.

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

Результаты обучения от классификатора

Мы обучили модель для 75 эпох с размером пакета 64.

  • Потеря валидации изменилась с: 0,13 до 0,23 → увеличилась
  • Точность валидации увеличилась с 0,96 до 0,96 → осталась без изменений
  • Потеря тренировки увеличилась с 0,13 до 0,00
  • Точность обучения увеличилась с: 0,96 до 0,99.

Модель имела такую ​​высокую точность в данных поезда и почти произвольные результаты из данных валидации. Несмотря на то, что точность высока, это не лучший показатель качества. Большинство наших данных выглядят одинаково, поэтому модель может легко научиться почти всегда предсказывать одно и то же, фактически не изучая данные. Конечно, это может быть связано с типом используемой модели. Например, если бы мы также использовали LSTM, это могло бы дать лучшие результаты. Наконец, учитывая, что мы работаем с текстом, уровень сложности чрезвычайно высок, а количество примеров очень мало пропорционально. У нас было около 9000 слов, и каждый пример представляет собой комбинацию некоторых подмножеств слов. Если бы во всех примерах было от 40 до 200 слов, то нам потребовалось бы от 1,66 * 1⁰¹¹⁰ до 9,64 * 1⁰⁴¹⁴ возможных последовательностей слов. Конечно, только небольшой процент из них будет иметь смысл (см. Теорию информации), но это все равно будет огромное количество последовательностей слов на выбор. Кроме того, наши метки - это количество реакций, которое для каждой реакции может доходить до бесконечности (таким образом, увеличивая пространство выборки еще больше). Если у нас есть всего 4555 примеров, чтобы попытаться изучить этот дистрибутив, переобучить очень легко.

Вторая модель: генератор долгосрочной краткосрочной памяти (LSTM)

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

Юрген Сито запустил модель LSTM, показанную выше. Некоторые из ключевых особенностей LSTM заключаются в том, что входные данные дополняются до, а не после. Так, например, последовательность предложений[1, 2, 3] будет дополнена как [0, 0, 0, 1, 2, 3], если максимальная длина была 6. В дополнение к этому, метки для LSTM являются индексами слов. Чтобы извлечь метки, мы разбиваем наше предложение на подпоследовательности, начиная с индекса 0 и до конца последовательности (с минимальной длиной последовательностей 2), и используем последний индекс в качестве метки. Например, для приведенного выше примера мы получим две последовательности входов[1, 2] и [1, 2, 3], дополним их как [0, 0, 0, 0, 1, 2] и [0, 0, 0, 1, 2, 3], а затем получим следующие пары меток входа: [0, 0, 0, 0, 1], [2] и [0, 0, 0, 1, 2], [3]².

Результаты обучения от LSTM

Мы обучили модель для 250 эпох с размером партии 32, используя признания, у которых всего есть не менее 25 реакций:

  • Потеря валидации увеличилась с: 6.50 до 5.3870 → уменьшилась!
  • Точность проверки увеличена с 0,05 до 0,5185 → увеличена!
  • Потери в обучении увеличились с: 6,87 до 0,1697.
  • Точность обучения увеличилась с 0,04 до 0,9632.

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

Некоторые прогнозы моделей

Вы также можете сделать прогноз на mit-smart-confessions.herokuapp.com/. Это может не сработать в первый (или второй, или третий) раз, когда вы попытаетесь, потому что серверы Heroku переходят в спящий режим, а затем долго просыпаются после того, как вы делаете запрос к серверу, но в конечном итоге это должно сработать. 😅

Результаты классификатора

Это признания, взятые недавно со страницы MIT Confessions. Принцип работы классификатора состоит в том, что вы даете ему text предложение и предсказываете сегменты для каждого типа реакции.

Text: “b1 freshman lack nuke power must elevate”
Output: 2–17 wow, 0 sad, 16–18 like, 3–12 love
Expected: 6 wow, 2 sad, 1 like, 1 love

Text: “Bow down you lowly phytoplankton, for I am your new sardine king.”
Output: 8–10 like, 6–27 haha, 0 love
Expected: 7 like, 6 haha, 1 love

Text: “Watching all these YouTubers promote science for the masses is truly humbling. Shoutout to ElectroBOOM, 3Blue1Brown, VSauce, GreatScott, minutephysics, Veritasium, CGPGrey, numberphile, SciShow and infinitely many others!”
Output: 1–2 like, 0 love
Expected: 53 like, 15 love

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

Результаты генератора

Генератор работает так: вы присваиваете ему seed text, который представляет начало предложения, и length, чтобы указать, сколько дополнительных слов нужно добавить к исходному тексту. Затем он будет одно за другим предсказывать следующие слова, которые нужно добавить.

Этот исходный текст был выбран произвольно.

Seed text: Roast that
Output: Roast that 6 check mit midterms harder than international olympiads of course

Seed text: People
Output: People who answer questions in large lectures where did you find such confidence bullshitters ? the animations are named asdf , …

Seed text: I love the
Output: I love the freshmen on my floor , they all have such funny and unique personalities ! so proud of them getting through their first real fight …

Seed text: MIT Midterms are
Output: mit midterms are by just being a p-set due at a potato, but it a few and we used to be bitter in a place like this, but just showing someone kindness, whether or not they are a friend, makes this place more rewarding. I feel like once a few years have gone by a lot of us lose sight of that. Keep doing nice things, it doesn’t take that much time or effort, and we can turn this place around, but unreadable enough that lazy female will have literally a plane and take.

Результаты генератора, хотя и более интересны, все же показывают переоснащение. Я думаю, если вы достаточно стары (с точки зрения того, сколько лет вы провели в Массачусетском технологическом институте) и участвовали в то время в MIT Confessions, вы бы знали, что некоторые из этих «разумных» предсказаний на самом деле являются частями признаний, которые были опубликованы в мимо. Вы можете сказать, пытаетесь ли вы ввести что-то бессмысленное (например, «вы, что я, что вы кофе»); это дало бы нечто столь же бессмысленное.

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

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

1. Недостаток данных: проклятие с самого начала

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

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

2. Пробелы в знаниях в процессах машинного обучения.

Первым нашим инстинктом при запуске этого проекта было найти что-то в Интернете, быстро скопировать и вставить, обучить (не заботясь о методах) и увидеть результаты. Тогда мы могли бы это улучшить.

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

Я считаю, что любой проект машинного обучения, который принимает очистку данных как должное, обречен на неудачу (или не полностью раскрывает свой потенциал). Я думаю, что в этом проекте еще есть много возможностей улучшить данные (например, в 2017 году у MIT Confessions было меньше подписчиков, чем в 2018 году, как это влияет на количество реакций?).

3. Модельная архитектура

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

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

4. Отладка Keras и Tensorflow.

Это может быть очень сложно. Кодовая база keras и tensorflow велика, и многие части работают для разных целей. Хочу выделить три важных ошибки, затруднявших разработку кода:

Tensorflow не работает с Python 3.7.x

Эта ошибка связана с тем, что Python 3.7.0 добавляет больше зарезервированных ключевых слов из Python 3.6.7. Это небольшое обновление должно быть обратно совместимо с Python 3.6.x (если по какой-либо причине вы не используете недавно введенные ключевые слова - async и await, которые считаются обратно несовместимыми по синтаксису).

Поскольку Google «улучшает» Python с помощью большего количества ключевых слов, используя несколько другой интерпретатор (или, может быть, python просто проигнорировал его, честно говоря, я не совсем уверен в том, как эта часть работает в фоновом режиме), это вызывает проблемы в Python 3.7.x из недавно введенные ключевые слова. Примечательно, что проблема с тензорным потоком связана с новым ключевым словом async, которое тензорный поток использует в своей кодовой базе.

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

Вот несколько ссылок на эту ошибку:

Лучшее исправление, которое я нашел, - это просто перейти на python 3.6.7. Это гарантированно сработает. Итак, идите сюда, чтобы загрузить python 3.6.7.

LSTM предсказывает одно и то же слово

Это могло произойти по нескольким причинам. Один из них заключался в том, что если один блокирует сообщение и пытается предсказать следующее слово, то следующее слово всегда будет вводным словом. Для нас причина, по которой это происходило, заключалась в том, что нам просто нужно было тренироваться дольше. 10 эпох недостаточно: около 250 эпох были точкой, в которой точность обучения больше не улучшалась. Обратите внимание, что это заняло более 10 часов обучения, поэтому вы не сможете понять, почему, если не тренируетесь достаточно долго! Эту ошибку было трудно выяснить, потому что наш инстинкт состоял в том, чтобы попытаться немного потренировать ее (1-2 эпохи) и посмотреть, будет ли она предсказывать то же самое. Кроме того, «тренироваться дольше» просто не казалось правильным, потому что в этом решении предполагается, что модель, которая не была обучена, должна просто предсказывать случайный мусор (а не одно и то же слово снова и снова), поскольку все веса инициализируются случайным образом.

Прогнозы модели не работают с Flask Python

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

Я не совсем понимаю, почему это происходит (и если вы знаете, дайте мне знать!), Но исправить это было, добавив в код следующее:

# import Tensorflow to the tensorflow graph, which fixed the bug
import tensorflow as tf
# store it into a variable
tf_graph = tf.get_default_graph()
# ... 
# more code ... 
def predict(inputs): 
    # before making a prediction, reset the graph as default
    with tf_graph.as_default(): 
        model.predict(inputs)

Эта проблема возникла при запуске кода с запущенным сервером Flask. В сети я обнаружил, что сервер обрабатывает вещи асинхронно, так что это как-то связано с этим.

Расширения к этому проекту

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

  • Использование встраивания Word2Vec Skip-Gram: это вложение гарантирует, что встраивание, которое мы используем, добавит некоторого смысла последовательностям, что не только ускорит обучение, но и, вероятно, улучшит показатели модели (особенно по классификатору).
  • Используйте одну и ту же модель для всех реакций: в настоящее время каждая реакция имеет свою собственную модель. Однако мы могли бы легко использовать одну модель, которая делает прогнозы для всех из них. Это могло бы иметь больше шансов уловить обратную зависимость, наблюдаемую выше (что наличие большего количества реакций одного типа приводит к меньшему количеству всех остальных реакций).
  • Используйте какую-либо форму переноса обучения на текст: это было бы полезно, чтобы иметь возможность принимать текст, преобразовывать его в какой-либо полезный формат и использовать этот формат в качестве входных данных для наших моделей. Встраивание Word2Vec, описанное выше, может быть формой передачи обучения (например, с использованием модели Google Word2Vec).
  • Прогнозирование доли признаний вместо количества признаний: это потенциально может дать лучшие результаты, поскольку сокращает пространство для выборки. Это также заменяет вопрос "сколько реакций я получу?" на «как люди отреагируют на это признание?»
  • Поэкспериментируйте с вариациями архитектур модели. Иногда другая архитектура может дать лучшие результаты в проверочном наборе. Возможно, наши модели были слишком сложными, поскольку они переоснащали данные и не работали так же хорошо на проверочном наборе.
  • Сбор дополнительных данных: На самом деле чрезвычайно важен для всего.
  • Поэкспериментируйте с лучшими методами очистки данных
  • Использование LSTM для модели классификатора
  • Больше работать над пониманием того, что делает признание исповеди или нарушает его.

Что теперь? Анализ настроений

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

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

Google сделал нечто подобное с Perspective API, на который, я думаю, стоит обратить внимание.

Твои предложения

Есть ли у вас предложения добавить в этот список или доработать проект? Пожалуйста, поделитесь в комментариях и спасибо, что прочитали это!

Огромное спасибо

Работа над этим проектом помогла мне узнать много нового о машинном обучении, серверах, Flask и Heroku, чего я раньше не знал, и я хочу поблагодарить наших инструкторов Натали Лао и Хэла Абельсона за то, что они подарили мне этот замечательный опыт.

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

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

___________________________________________________________________

Сноски

¹ На странице может быть больше признаний, чем то, что я дал здесь. Это потому, что каждому признанию присваивается идентификатор, а на странице признания публикуются как «#CONFESSION_ID CONFESSION_TEXT». Может быть, счетчик id перезапустился или что-то в этом роде, но общее количество признаний не перезапустится. Вот почему MIT Summer Confession предоставил больше данных, чем самый большой идентификатор признания.

«Вы спросите, а почему бы не взять все подпоследовательности? Например, если у нас есть последовательность [1, 2, 3, 1], почему бы не взять все подпоследовательности длиной не менее двух, а именно: [1, 2], [1, 2, 3], [1, 2, 3, 1], [2, 3], [2, 3, 1], [3, 1]. Причина, по которой мы не стали бы этого делать, заключается в следующем: Сколько подпоследовательностей получается из последовательности длиной n? Решение - n choose 2, что оказывается n * (n — 1) / 2. Так что, если бы в наших примерах было где-то между 20-80 словами в среднем, это было бы как минимум 10 * 19 * 4555 = 865,450 и 40 * 79 * 4555 = 14,393,800 примеров для обучения. Это не такая уж большая проблема, пока вы не примете во внимание последовательность максимальной длины, которая может быть довольно большой, поэтому каждый примерный вектор будет таким же большим. Если бы эта максимальная последовательность была 80 (а в нашем случае она намного больше), то у нас было бы много действительно больших векторов, каждый из которых увеличивался бы в 300 раз через слой встраивания (размер 300 в случае LSTM), который просто много памяти для python. Мы действительно попробовали это, и python отказался от нас из-за использования слишком большого количества памяти.