Разработка алгоритма автоматической классификации комментариев на английском языке в соответствии с их токсичным тоном

Публикация - один из самых популярных форматов общения в социальной сети. Особенности векторного представления слов в двумерном пространстве. Архитектура рекуррентной нейронной сети. Модерация текста - инструмент борьбы с токсичностью в Интернете.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 02.09.2018
Размер файла 1,3 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

Размещено на http://www.allbest.ru

Размещено на http://www.allbest.ru

Введение

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

Исследование фокусируется на изучении вопросов, касающихся классификации токсических комментариев из социальных сетей методами машинного обучения. Все методы оцениваются по среднему значению ROC AUC по столбцам, используя набор комментариев из редакций Википедии на страницах обсуждений, предоставленных организаторами Toxic Comment Classification Challenge. Конкурс представлен на платформе Kaggle.

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

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

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

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

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

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

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

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

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

Постановка задачи.

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

Целью работы является разработка алгоритма автоматической классификации комментариев на английском языке в соответствии с их токсичным тоном.

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

Для достижения цели решены следующие задачи:

1. Предобработка текстовых данных на английском языке.

2. Разработка оптимального подхода представления текста.

3. Исследование существующих методов классификации текста.

4. Исследование архитектур нейронных сетей в задаче классификации тектов.

5. Разработка алгоритма классификации токсичных комментариев.

6. Разработка API.

7. Оценка решений с другими участниками конкурса путем представления прогнозов на платформе Kaggle.

Мерой качества алгоритма является усредненный по столбцам ROC AUC.

1. Обзор литературы

модерация рекуррентный нейронный двумерный

Выпускная квалификационная работа основана на современных исследованиях автоматической обработки естественного языка. Задача автоматического определения токсической полярности формулируется как задача многотемной (muli-label) классификации.

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

Например, предложения можно классифицировать в соответствии с их читабельностью, используя алгоритмы машинного обучения, такие как SVM, Random Forest и другие [1], чтобы сделать чтение более понятным, удобным и доступным. Кроме того, очень распространенный класс задач обработки естественного языка является категоризацией текстовой информации по полярности настроения. Проблема определения тональности изучается многими исследователями [12,13]. Доступность данных дает возможность проводить опросы общественного мнения по любому вопросу, то есть дает возможность оценивать удовлетворенность людей по интересующему вопросу, например, нравится ли людям только что вышедший в кинотеатр фильм или новое видео YouTube деятеля. Практическое применение этой задачи является очень широким: от мониторинга популярных событий (например, президентских дебатов, премии Оскара и т. д.) или отслеживания отношения к знаменитостям в соответствии с текстовыми комментариями подписчиков к извлечению торговых сигналов путем мониторинга твитов об открытых компаниях.

Однако, за негативными высказываниями скрывается много токсичности. Это приводит к тому, что многие люди избегают выражать свои мысли в Интернете и отказываются в поиске разных мнений из-за угрозы грубости, оскорблений и ненависти. В статье Ex Machina: Personal Attacks Seen at Scale [2] авторы пытаются разработать и проиллюстрировать методы машинного обучения и методы краудсорсинга для анализа грубых, жестоких и других личных атак. С помощью набора данных на страницах обсуждений в Википедии решаются открытые вопросы о характере онлайн персональных атак. Одна из проблем в исследовании негативного поведения людей в Интернете - это наличие множества разных форм токсичности, вследствие которой поднимается проблема отсутствия четкого и общего определения ее типа [7]. Так, в некоторых исследованиях представляют различные формы ненавистной речи [6,7], в то время как другие исследуют киберзапугивания [9,10] или онлайн-грубости [8] и преследования [3].

Текст из онлайн-сообщений скрывает множество личных атак, например, ненависть к личности, оскорбление или другую токсичность [14]. К сожалению, это распространенное явление в Интернете, и оно вызывает ряд проблем. Ранее Фонд Викимедиа обнаружил, что почти 55% тех людей, которые испытали киберзапугивание, больше не хотели испытать подобное. [2]. Более того, в 2014 году докладчики Pew Report подчеркивают тот факт, что более 73% взрослых пользователей видели издевательства в Интернете, а 39% испытали это на себе [14].

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

Автоматическое прогнозирование и идентификация токсичных комментариев в реальном времени имеют первостепенное значение, поскольку это поможет избежать угроз для пользователей Интернета. Попытки автоматической модерации контента были предприняты Jigsaw the Google, запустив службу под названием Perspective [15], которая использует методы машинного обучения для прогнозирования грубости, оскорблений и ненависти. Эта служба предоставляет API, который дает разработчикам доступ к использованию детектора токсичности в комментариях. Он работает на серверах Google и дает возможность фильтровать и идентифицировать токсичность в социальных сетях.

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

Основная цель выпускной квалификационной работы заключается в использовании набора данных, предоставленного организаторами соревнования, в попытке исследования в области интеллектуального анализа, обеспечивают ли рекуррентные нейронные сети с использованием векторного представления слов для кодирования текстов, какие-либо преимущества по сравнению с традиционными методами для классификации, которые использует представления текста в виде TF-IDF или Bag-of-Words (BoW).

2. Обзор данных

Материалом для данного исследования служит набор комментариев из редакций Википедии на страницах обсуждений, предоставленный организаторами Toxic Comment Classification Challenge, который представляет собой подготовленную таблицу комментариев, которые были размечены в соответствии с их токсичным тоном. Выделяются следующие типы токсичности:

· токсичность.

· сильная токсичность.

· непристойность.

· угроза.

· оскорбление.

· ненависть к личности.

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

· 159571 примеров для обучения модели.

· 153164 примеров для тестирования качества модели.

Рисунок 1. Случайные 15 примеров исходных тренировочных данных

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

Рисунок 2. Наиболее часто используемые слова в текстах, относящихся к типу identity_hate

По рисунку отчетливо видно, что наиболее часто используемые слова в текстах, которые относятся к классу identity_hate содержат оскорбления и расизм - «NIGGER» как обращение к расе темнокожих людей, что полностью соответствует типу identity_hate. Кроме того, видно, что пользователи пытаются обойти систему автоматической модерации, применяя различные видоизменения слов, например, «N133RS» и т.д. Это говорит о том, что нужно уделить этому внимание при выполнении предобработки данных.

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

Рисунок 3. Корреляция типов токсичности комментариев

По рисунку видно, что наиболее зависимыми типами токсичности являются obscene - insult, toxic - obscene, toxic - insult и то, что тип токсичности threat не имеет зависимости вообще ни с каким из типов.

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

Рисунок 4. Распределение наиболее популярных языков

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

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

Рисунок 5. Распределение комментариев по классам на тренировочных данных

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

Максимальное количество слов в комментарии среди всех комментариев составляет 1403, и 90 перцентиль имеет значение 156, что говорит о том, что 90% всех данных имеют количество слов в комментариях меньшее или равное 156.

Рисунок 6. Распределение слов в комментариях 90% данных для обученя

3. Предобработка текста

При решении задач, связанных с обработкой естественного языка, требуется предобработка входных текстовых данных для улучшения обобщающей способности будущей модели машинного обучения, поскольку необработанный текст содержит в себе лишнюю информацию (URL-адреса, символы табуляции, переноса строк и другие специальные символы такие как «\<>*&/» и другие), которая, по своей сути, является шумом, а также текст может содержать одинаковые по смыслу слова, но принимающие разные формы (например, отличаются окончания). И то, и другое может оказывать негативное влияние на результат.

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

· @I HATE Nl33ERS\n # ()*)$!

· "\nMore\nI can\'t make any real suggestions

· \nup, sit down.

· on wikioedia check it https://kpjl123812ujsdf.com

· H.e.l.l.o s.w.e.e.t.y

· w h a t a r e y o u d o i n g h e r e

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

1. Преобразование текста к нижнему регистру.

2. Удаление текстового шума (URL-адреса, символы табуляции, переноса строк, лишние пробелы, стоп-слова, цифры, символы пунктуации и прочие спец символы).

3. Использование техник стэмминга и лемматизации.

4. Преобразования вида «H E L L O M A N- > HELLO MAN».

5. Использование техник для автоматического исправления опечаток.

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

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

Рисунок 7. Реализованная универсальная функция предобработки текста

Ниже представлены аргументы функции и их краткое описание:

1. text - массив текстов, к которым необходимо применить предобработку текста.

2. lowercase - привести текст к нижнему регистру.

3. remove_urls - удалить URL адреса любого вида.

4. remove_numbers - удалить цифры.

5. use_transformation - использовать преобразование вида H.E.L.L.O M A N -> HELLO MAN.

6. use_jamspell - использовать автоматическое исправление опечаток.

7. use_correction - использовать преобразования вида N1e3r -> nigger и приведение мата к единому виду.

8. keep_only_letters - оставить только буквы (удалить остальные символы).

9. use_lemmatization - использовать лемматизацию.

10. use_stemming - использовать стемминг.

Приведение текста к нижнему регистру и удаление символов

Для приведения исходных текстовых данных к нижнему регистру используются стандартные средства языка Python. Для удаления символов используются регулярные выражения.

texts = [text.lower() for text in texts]

regex = re.compile(r'[0-9]')

texts = [regex.sub(r'',text) for text in texts]

regex = re.compile(r'[a-z\s()]', re.IGNORECASE)

texts = [regex.sub(r' ', text) for text in texts]

Удаление гиперссылок

Для удаления URL-адресов используются регулярные выражения. Выполнение гиперссылок происходит в 2 этапа - в первом проверяется наличие протокола, а во втором наличие URL-адреса.

regex = re.compile(r'https?:*/*/*', re.IGNORECASE)

texts = [regex.sub(r'', text) for text in texts]

regex = re.compile(r'(www.)?[a-z0-9]+\.[a-z]{2,4}', re.IGNORECASE)

texts = [regex.sub(r'', text) for text in texts]

Использование преобразований слов

Для выполнения данного преобразований используются регулярные выражения.

regex = re.compile(r'\b([a-z0-9])[.\s]\b', re.IGNORECASE)

texts = [regex.sub(r'\1', text) for text in texts]

regex = re.compile(r'f[\s]{3}(ing)*(in)*(n)*', re.IGNORECASE)

texts = [regex.sub(r' fuck ', text) for text in texts]

regex = re.compile(r'n(1|i)+g{0,}(e|3)+r{0,}s{0,}', re.IGNORECASE)

texts = [regex.sub(r' nigger ', text) for text in texts]

Использование автоматического исправления опечаток.

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

corrector = jamspell.TSpellCorrector()

corrector.LoadLangModel('jamspell-model/en.bin')

texts = [corrector.FixFragment(text) for text in texts]

Использование лемматизации и стемминга.

Для выполнения преобразований слов использовались решения библиотеки NLTK - пакет программ для обработки естественного языка. Перед началом преобразований необходимо поделить предложения на слова (токены), над, которыми, в дальнейшем будет выполнена операция преобразования. В качестве токенайзера использовался MosesTokenizer, для лемматизации - WordNetLemmatizer и для операции стемминга - SnowballStemmer.

tokenizer = MosesTokenizer()

lemmatizer = WordNetLemmatizer()

texts = [' '.join([lemmatizer.lemmatize(word, pos = 'v')

for word in tokenizer.tokenize(text)]) for text in texts]

stemmer = SnowballStemmer("english")

texts = [' '.join([stemmer.stem(word)

for word in tokenizer.tokenize(text)]) for text in texts]

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

there are dogs here on wikioedia check it https://kpjl123812ujsdf.com site for f*ckin n.1.g.g.3.3.r.s\nH.e.l.l.o s.w.e.e.t.y. How are you? w h a t a r e y o u d o i n g h e r e

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

Без использования стемминга и лемматизации:

preprocess(texts)

there are dogs here on wikipedia check it site for fuck nigger hello sweety how are you what are you doing here

1. С использованием лемматизации

preprocess(texts, use_lemmatization = True)

there be dog here on wikipedia check it site for fuck nigger hello sweety how be you what be you do here

2. С использованием стемминга

preprocess(texts, use_stemming = True)

there are dog here on wikipedia check it site for fuck nigger hello sweeti how are you what are you do here

Отчетливо видно, что текст стал чище. Были исправлены опечатки (wikiomedia -> wikipedia), преобразованы скрытые слова, содержащие мат и расизм, убраны точки, символы переноса строк, лишние пробелы и отступы между буквами, удалены ссылки и осуществлена операция лемматизации (are -> be) в первом случае и стемминга (sweety -> sweety) во втором.

4. Представление текста

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

1) Мешок слов (Bag of Words - BoW)

2) TF-IDF [5]

3) Word2vec, fastText, Glove[3,18,4]

Для традиционных моделей машинного обучения используются представления комментариев в виде мешка слов (BoW) и TF-IDF. Для представления текста в нейронных сетях используются предобученные векторы представления слов в пространстве.

Используемые в выпускной квалификационной работе предобученные векторы представления слов:

1. Crawl fastText

2. Twitter Glove

5. Аугментация данных

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

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

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

Ниже представлен пример аугментации данных:

Оригинал:

D'aww! He matches this background colour I'm seemingly stuck with. Thanks. (talk) 21:51, January 11, 2016 (UTC)

EN -> FR -> EN

D'aww! It corresponds to that background color with which I am apparently stuck. Thank you. (spoke) 21:51, January 11, 2016 (UTC)

EN -> DE -> EN

D'aww! It fits in with this background color, with which I seem to be stuck. Many Thanks. (Lecture) 21:51, 11 January 2016 (UTC)

EN -> ES -> EN

D'aww! He matches this background color that I'm apparently caught. Thank you. (speaks) 21:51, January 11, 2016 (UTC)

В приложении 3 представлен код для аугментации данных:

Рисунок 8. Параметры запуска кода для аугментации данных

Обязательным параметром является выбор языков для перевода, разделенных запятой. Также можно изменить путь к тренировочным данным, который по умолчанию - data/train.csv. Каждый аугментированный датасет будет сохранен в виде train_LANG.csv

Рисунок 9. Пример выполнения программы

6. Применение традиционных методов машинного обучения

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

Для построения моделей, комментарии были представлены в виде Bag of Words и TF-IDF последовательностей, так как это одни из самых эффективных способов представления слов в тексте. Первым делом из исходных текстов формируется словарь слов (токенов). Далее, формируется матрица признаков, в которой элементы представляет число вхождений слов из корпуса в случае представления BoW и оценки важности термина для какого-либо документа относительно всех остальных документов в случае TF-IDF. Были получены следующие результаты:

Рисунок 10. Результаты традиционных методов машинного обучения

Следующим шагом было использование не только представление слов в виде BoW и TF-IDF, но также посимвольное представление n-грамм с диапазоном от 2 до 6. Для этого сначала формируются признаки для слов, далее - для n-грамм символов, и последним этапом является их соединение в общую матрицу признаков.

Таким образом, удалось улучшить результаты:

Рисунок 11. Результаты традиционных методов машинного обучения

Как видно из рисунка выше, наилучший результат был достигнут при использовании модели логистической регрессии с одновременным использованием представления в виде TF-IDF последовательностей слов и посимвольного представления n-грамм символов - он составляет 0.9762 ROC AUC.

В приложении 4 представлен универсальный код для запуска всевозможных моделей, связанных с логистической регрессией и методом опорных векторов с представлениями в виде BoW и TF-IDF последовательностей слов и n-грамм символов. Приложенный код содержит следующие параметры для запуска:

Обязательными параметрами являются:

1. model - выбор модели (SVM - для метода опорных векторов и LOG - для Логистической регрессии)

2. vectorizer - выбор метода представления текста (BoW - для представления в виде мешка слов, TF_IDF - для представления в виде TF-IDF последовательностей)

Дополнительными параметрами являются:

· --train_data - путь к данным для обучения модели (по умолчанию - data/train.csv)

· --test_data - путь к данным для тестирования (по умолчанию - data/test.csv)

· --preprocess - использование предобработки текста (--lowercase --remove_urls --remove_numbers --use_transformation --use_correction, --use_jamspell, --keep_only_letters, --use_lemmatization, --use_stemming, --use_char_features)

· --word_features - максимальный размер словаря

· --char_features - максимальное количество униграмм

· --regularizer - использование l1 или l2 регуляризации

· --C - параметр регуляризации

· --folds - количество фолдов при выполнении кросс валидации

Рисунок 12. Параметры запуска кода

Рисунок 13. Пример исполнения кода

7. Применение нейронных сетей

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

Рисунок 14. Архитектура рекуррентной нейронной сети с одним входным нейронном, одним скрытым нейроном и одним выходным нейроном и ее развернутое по времени представление

Однако проблема рекуррентных нейронных сетей заключается в быстрой потере информации с течением времени. Нейронные сети с долгой краткосрочной памятью (long short term memory, LSTM) [16] пытаются решить эту проблему при помощи фильтров и клеток памяти. Каждый нейрон имеет ячейку памяти и три фильтра: ввод, вывод и забвение. Назначение этих фильтров - защита информации.

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

Рисунок 15. Архитектура долгой краткосрочной памяти, развернутая по времени

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

Рисунок 16. Исходные данные после обработки

В подходах, связанных с глубоким обучением, обычно используют векторное представление слов. Это специальное представление слов в n-мерном пространстве. Каждому слову соответствует вектор из n действительных чисел. Основной смысл такого представления заключается в том, что если слова похожи, то они располагаются рядом. [3]

Рисунок 17. Пример векторного представления слов в двумерном пространстве

Архитектура нейронной сети

· Первый слой: конкатенированные вектора представления слов fastText и Glove.

· Второй слой: двунаправленный LSTM с размером ядра 64.

· Третий слой: двунаправленный GRU [17] с размером ядра 32.

· Четвертый слой: полносвязный с 6 выходами

Рисунок 18. Архитектура рекуррентной нейронной сети

Параметры модели:

· Размер батча: 32

· Длина последовательности: 350

· Размер данных для валидации: 5% от данных для обучения

· Максимальное количество токенов - 250 000

· Максимальная длина последовательности - 350

· Размер ядра LSTM - 64

· Размер ядра GRU - 32

Таким образом удалось достигнуть результата - 0,9876 ROC AUC. В приложении 5 представлен код для обучения модели.

Рисунок 19. Параметры запуска кода

8. Разработка API

Для демонстрации работоспособности модели был создан Web сервис, позволяющий предсказывать наличие токсичности в тексте. API было реализовано при помощи микрофреймворка Flask на языке Python.

Рисунок 20. Главная страница созданного сервиса

Для определения токсичности комментария, необходимо выполнить запрос /toxic/?text=text. В качестве ответа на запрос будет возвращен JSON с классами токсичности и вероятностями. Например,

Рисунок 21. Пример работоспособности API с токсичными комментариями

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

Теперь необходимо проверить, как работает модель на текстах, которые не содержат токсичности в комментариях. Например, есть два текста - thanks и It is really good.

Рисунок 22. Пример работоспособности API с нетоксичными комментариями

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

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

Результаты.

Нейронные сети показывают лучшие результаты классификации токсичных комментариев. Двунаправленная рекуррентная нейронная сеть с долгой кратковременной памятью (LSTM, GRU) с предобученными векторами представления слов показала лучший результат ROC AUC - 0,9867, тогда как результат логистической регрессии - 0,9762 ROC AUC.

Рисунок 23. Итоговые результаты

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

Заключение

Целью выпускной квалификационной работы была разработка алгоритма автоматической классификации комментариев, которые пользователи публикуют в социальных сетях, на английском языке в соответствии с их токсичным тоном. Все методы машинного обучения оцениваются в сравнениях с другими участниками Toxic Comment Classification Challenge по усредненным по столбцам значениям ROC AUC.

Эксперименты показали, что лучшие результаты были получены с использованием двунаправленных рекуррентных моделей нейронных сетей с LSTM и GRU слоями. Итоговый результат - 0.9867 ROC AUC, что дало возможность оказаться на 709 месте среди 4551 команд (топ 16%) в Toxic Comment Classification Challenge, организованными Jigsaw и Google на платформе Kaggle.

Список литературы

1. Nikolay Karpov, Julia Baranova, and Fedor Vitugin. Single-sentence readability prediction in russian. In International Conference on Analysis of Images, Social Networks and Texts, pages 91-100. Springer, 2014.

2. Ellery Wulczyn, Nithum Thain, Lucas Dixon. Ex Machina: Personal Attacks Seen at Scale. In International World Wide Web Conference Committee (IW3C2), April 3-7, 2017.

3. Tomas Mikolov, Kai Chen, Greg Corrado, Jeffrey Dean. Efficient Estimation of Word Representations in Vector Space, Proceedings of Workshop at ICLR, 2013.

4. Pennington, Jeffrey, Richard Socher, and Christopher D. Manning. "Glove: Global Vectors for Word Representation." EMNLP. Vol. 14. 2014.

5. Ramos J. et al. Using TF-IDF to determine word relevance in document queries, Proceedings of the first instructional conference on machine learning. - 2003.

6. Gagliardone, D. Gal, T. Alves, and G. Martinez. Countering online hate speech. UNESCO Publishing, 2015.

7. Haji Mohammad Saleem, Kelly P Dillon, Susan Benesch, Derek Ruths. A Web of Hate: Tackling Hateful Speech in Online Social Spaces. Text Analytics for Cybersecurity and Online Safety (TA-COS), September, 2017.

8. J. Cheng, C. Danescu-Niculescu-Mizil, and J. Leskovec. Antisocial behavior in online discussion communities. In ICWSM, 2015.

9. D. Yin, Z. Xue, L. Hong, B. D. Davison, A. Kontostathis, and L. Edwards. Detection of harassment on web 2.0. In WWW, 2009.

10. N. E. Willard. Cyberbullying and cyberthreats: Responding to the challenge of online social aggression, threats, and distress. Research Press, 2007.

11. Xin Tong, Yang Feng, Jingyi Jessica Li. Neyman-Pearson (NP) classification algorithms and NP receiver operating characteristics (NP-ROC), 2016.

12. Svetlana Kiritchenko, Saif M Mohammad, and Mohammad Salameh. Semeval-2016 task 7: Determining sentiment intensity of english and arabic phrases. Proceedings of SemEval, pages 42-51, 2016.

13. Jeonghee Yi, Tetsuya Nasukawa, Razvan Bunescu, and Wayne Niblack (2003). Sentiment analyzer: Extracting sentiments about a given topic using natural language processing techniques. - In Proceedings of the Third IEEE International Conference on Data Mining. - p. 427-434.

14. Maeve Duggan. 2014. Online harassment. Pew Research Center.

15. Hossein Hosseini, Sreeram Kannan, Baosen Zhang, and Radha Poovendran. Deceiving Google's Perspective API Built for Detecting Toxic Comments, 2017.

16. Hochreiter S., Schmidhuber J. Long short-term memory. Neural computation 9, 1997. Issue 8. P. 1735 - 1780.

17. Junyoung Chung, Caglar Gulcehre, KyungHyun Cho, Yoshua Bengio. Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling, 2014.

18. Joulin, E. Grave, P. Bojanowski, T. Mikolov, Bag of Tricks for Efficient Text Classification, 2017

19. Тарасов Д.С. Глубокие рекурентные нейронные сети для аспектно-ориентированного анализа тональности отзывов пользователей на различных языках - 2014.

Приложение 1

import pandas as pd

import numpy as np

import seaborn as sns

import re

import tqdm

from wordcloud import WordCloud

from nltk.corpus import stopwords

from langdetect import detect

from matplotlib import pyplot as plt

from pylab import rcParams

rcParams['figure.figsize'] = 15, 8

train_data = pd.read_csv('data/train.csv')

test_data = pd.read_csv('data/test.csv')

train_data.sample(15)

text = str()

for i in train_data[train_data['identity_hate'] == 1]['comment_text']:

text += str(i)

regex = re.compile('\w+')

text = regex.sub(' ',text)

wc = WordCloud(background_color="white",

stopwords=stopwords.words('english'), width = 1920,height = 1080,)

wc.generate(text)

plt.figure()

plt.imshow(wc, interpolation="bilinear")

plt.axis("off")

plt.show()

train_data.iloc[:,2:].corr(method='pearson')

sns.heatmap(train_data.iloc[:,2:].corr(method='pearson'),cmap='Reds')

langs = []

for text in tqdm.tqdm_notebook(train_data['comment_text']):

try:

langs.append(detect(text))

except:

langs.append('error')

pd.DataFrame(pd.DataFrame(langs)[0].value_counts()).rename(columns = {0:'lang'}).head()

counts = []

for i in range(2,8):

counts.append(train_data.iloc[:,i].value_counts().loc[1])

counts.append(len(train_data[train_data.iloc[:,2:].eq([0,0,0,0,0,0]).all(1)]))

idx = list(train_data.columns[2:])

idx.append('clean')

tmp = pd.DataFrame(counts)

tmp.columns = ['counts']

tmp

sns.barplot(x = idx, y = 'counts', data = tmp)

np.percentile(lenghts,90)

sns.kdeplot(np.sort(lenghts)[:int(len(lenghts)*0.9)])

Приложение 2

import re

import jamspell

from nltk.stem import WordNetLemmatizer, SnowballStemmer

from nltk.tokenize.moses import MosesTokenizer

def preprocess(texts, lowercase = True, remove_urls = True, remove_numbers = True,

use_transformation = True, use_jamspell = True, use_correction = True,

keep_only_letters = True, use_lemmatization = False, use_stemming = False):

if lowercase: texts = [text.lower() for text in texts]

if remove_urls:

regex = re.compile(r'https?:*/*/*', re.IGNORECASE)

texts = [regex.sub(r'', text) for text in texts]

regex = re.compile(r'(www.)?[a-z0-9]+\.[a-z]{2,4}', re.IGNORECASE)

texts = [regex.sub(r'', text) for text in texts]

if use_transformation:

regex = re.compile(r'\b([a-z0-9])[.\s]\b', re.IGNORECASE)

texts = [regex.sub(r'\1', text) for text in texts]

if use_correction:

regex = re.compile(r'f[\s]{3}(ing)*(in)*(n)*', re.IGNORECASE)

texts = [regex.sub(r' fuck ', text) for text in texts]

regex = re.compile(r'n(1|i)+g{0,}(e|3)+r{0,}s{0,}', re.IGNORECASE)

texts = [regex.sub(r' nigger ', text) for text in texts]

if remove_numbers:

regex = re.compile(r'[0-9]')

texts = [regex.sub(r'',text) for text in texts]

if use_jamspell:

corrector = jamspell.TSpellCorrector()

corrector.LoadLangModel('jamspell-model/en.bin')

texts = [corrector.FixFragment(text) for text in texts]

regex = re.compile(r"[\"«»`'“”„“`'']+")

texts = [regex.sub(r'"', text) for text in texts]

regex = re.compile(r"[?---ЇЃ]-__-]+")

texts = [regex.sub(r'-', text) for text in texts]

regular = re.compile(r"\S{20,}")

texts = [regex.sub(" spam ", text) for text in texts]

if keep_only_letters:

regex = re.compile(r'[a-z\s()]', re.IGNORECASE)

texts = [regex.sub(r' ', text) for text in texts]

if use_lemmatization:

tokenizer = MosesTokenizer()

lemmatizer = WordNetLemmatizer()

texts = [' '.join([lemmatizer.lemmatize(word, pos = 'v') for word in tokenizer.tokenize(text)]) for text in texts]

if use_stemming:

tokenizer = MosesTokenizer()

stemmer = SnowballStemmer("english")

texts = [' '.join([stemmer.stem(word) for word in tokenizer.tokenize(text)]) for text in texts]

regex = re.compile(r'\s+')

texts = [regex.sub(' ', text) for text in texts]

return texts

Приложение 3

import pandas as pd

import argparse

import tqdm

from textblob import TextBlob

parser = argparse.ArgumentParser(add_help=True)

parser.add_argument('--train_data', type = str, default = "data/train.csv", help = "Path to train data")

parser.add_argument('langs', type = str, help = 'Separated by commas: fr,de,es')

args = parser.parse_args()

def do_translate(text, lang):

try:

text = TextBlob(text)

text = text.translate(to=lang)

text = text.translate(to="en")

return str(text)

except:

return None

print(args)

print('Loading data ...')

train_data = pd.read_csv(args.train_data)

langs = args.langs.split(',')

for lang in langs:

print('Translating to {}'.format(lang))

extended_data = pd.DataFrame()

for i in tqdm.tqdm(range(len(train_data))):

tmp = train_data.iloc[i,:].tolist()

tmp[1] = do_translate(tmp[1], lang)

extended_data = extended_data.append([tmp])

extended_data.columns = train_data.columns

extended_data.dropna(inplace = True)

extended_data.to_csv('train_' + lang + '.csv', index = None)

Приложение 3

import argparse

import pandas as pd

import numpy as np

from scipy.sparse import hstack

from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer

from sklearn.linear_model import LogisticRegression

from sklearn.svm import SVC

from sklearn.model_selection import cross_val_score

from nltk.tokenize.moses import MosesTokenizer

from utils.preprocess import preprocess

parser = argparse.ArgumentParser(add_help=True)

parser.add_argument('--train_data', type = str, default = "data/train.csv", help = "Path to train data")

parser.add_argument('--test_data', type = str, default = "data/test.csv", help = "Path to test data")

parser.add_argument('--preprocess', action = 'store_true', help = 'Use preprocessing')

parser.add_argument('--lowercase', action = 'store_true', help = "Convert to lowercase")

parser.add_argument('--remove_urls', action = 'store_true', help = "Remove urls")

parser.add_argument('--remove_numbers', action = 'store_true', help = "Remove numbers")

parser.add_argument('--use_transformation', action = 'store_true', help = "Use transformation like M.E.S S A.G.E -> MESSAGE")

parser.add_argument('--use_correction', action = 'store_true', help = "Use transformation like n1g33r -> nigger")

parser.add_argument('--use_jamspell', action = 'store_true', help = "Use JamSpell autocorrection")

parser.add_argument('--keep_only_letters', action = 'store_true', help = "Keep only A-Z a-z letters")

parser.add_argument('--use_lemmatization', action = 'store_true', help = "Use lemmatization")

parser.add_argument('--use_stemming', action = 'store_true', help = "Use stemming")

parser.add_argument('model', type = str, help = 'Model to use: SVM or LOG')

parser.add_argument('vectorizer', type = str, help = 'BoW or TF_IDF')

parser.add_argument('--use_char_features', action = 'store_true', help = 'Use additional char features')

parser.add_argument('--word_features', type = int, default = 10000, help = 'Max words features')

parser.add_argument('--char_features', type = int, default = 50000, help = 'Max char features')

parser.add_argument('--regularizer', type = str, default = 'l2', help = 'l1 or l2')

parser.add_argument('--C', type = float, default = 0.1, help = 'Penalty rate')

parser.add_argument('--folds', type = int, default = 3, help = 'Num of CV folds')

args = parser.parse_args()

print(args)

classes = ['toxic', 'severe_toxic', 'obscene', 'threat', 'insult', 'identity_hate']

print('Loading train data ...')

train_data = pd.read_csv(args.train_data).fillna(' ')

print('Loading test data ...')

test_data = pd.read_csv(args.test_data).fillna(' ')

train_texts = list(train_data['comment_text'])

test_texts = list(test_data['comment_text'])

if args.preprocess:

print('Preprocessing ...')

train_texts = preprocess(train_texts,

lowercase = args.lowercase,

remove_urls = args.remove_urls,

remove_numbers = args.remove_numbers,

use_transformation = args.use_transformation,

use_correction = args.use_correction,

use_jamspell = args.use_jamspell,

keep_only_letters = args.keep_only_letters,

use_lemmatization = args.use_lemmatization,

use_stemming = args.use_stemming)

test_texts = preprocess(test_texts,

lowercase = args.lowercase,

remove_urls = args.remove_urls,

remove_numbers = args.remove_numbers,

use_transformation = args.use_transformation,

use_correction = args.use_correction,

use_jamspell = args.use_jamspell,

keep_only_letters = args.keep_only_letters,

use_lemmatization = args.use_lemmatization,

use_stemming = args.use_stemming)

if args.vectorizer == 'TF_IDF':

word_vectorizer = TfidfVectorizer(

#tokenizer=MosesTokenizer().tokenize,

token_pattern=r'\w{1,}',

stop_words = 'english',

sublinear_tf=True,

max_features = args.word_features)

elif args.vectorizer == 'BoW':

word_vectorizer = CountVectorizer(

#tokenizer=MosesTokenizer().tokenize,

token_pattern=r'\w{1,}',

stop_words = 'english',

max_features = args.word_features)

print('Fitting word vectorizer ...')

word_vectorizer.fit(train_texts)

print('Transforming ...')

train_word_params = word_vectorizer.transform(train_texts)

test_word_params = word_vectorizer.transform(test_texts)

if args.use_char_features:

if args.vectorizer == 'TF_IDF':

char_vectorizer = TfidfVectorizer(

sublinear_tf=True,

analyzer='char',

stop_words='english',

ngram_range=(2, 6),

max_features=args.char_features)

elif args.vectorizer == 'BoW':

char_vectorizer = CountVectorizer(

analyzer='char',

stop_words='english',

ngram_range=(2, 6),

max_features=args.char_features)

print('Fitting char vectorizer ...')

char_vectorizer.fit(train_texts)

print('Transforming ...')

train_char_params = char_vectorizer.transform(train_texts)

test_char_params = char_vectorizer.transform(test_texts)

print('Stacking params ...')

X_train = hstack([train_word_params, train_char_params])

X_test = hstack([test_word_params, test_char_params])

else:

X_train = train_word_params

X_test = test_word_params

if args.model == 'LOG':

model = LogisticRegression(penalty = args.regularizer, C = args.C, solver = 'sag')

print('Logistic regression was selected')

elif args.model == 'SVM':

model = SVC(C = args.C)

print('Support vector machine was selected')

for class_name in classes:

y_train = train_data[class_name]

try:

print('CV score for {} class with {} folds is {}.'.format(class_name, args.folds,

np.mean(cross_val_score(model, X_train, y_train, cv=args.folds, scoring='roc_auc'))))

except:

pass

model.fit(X_train, y_train)

test_data[class_name] = model.predict_proba(X_test)[:,1]

test_data[['id', 'toxic', 'severe_toxic', 'obscene', 'threat', 'insult', 'identity_hate']].to_csv('submit.csv', index = None)

Приложение 4

import argparse

import pandas as pd

import numpy as np

from gensim import models

from keras.preprocessing.text import Tokenizer

from keras.preprocessing.sequence import pad_sequences

from keras.models import Model

from keras.layers import Input

from keras import regularizers

from keras.layers import GRU, LSTM, Bidirectional, Dense, Embedding, concatenate, CuDNNLSTM, CuDNNGRU

from sklearn.metrics import roc_auc_score

from utils.preprocess import preprocess

parser = argparse.ArgumentParser(add_help=True)

parser.add_argument('--preprocess', action = 'store_true', help = 'Use preprocessing')

parser.add_argument('--lowercase', action = 'store_true', help = "Convert to lowercase")

parser.add_argument('--remove_urls', action = 'store_true', help = "Remove urls")

parser.add_argument('--remove_numbers', action = 'store_true', help = "Remove numbers")

parser.add_argument('--use_transformation', action = 'store_true', help = "Use transformation like M.E.S S A.G.E -> MESSAGE")

parser.add_argument('--use_correction', action = 'store_true', help = "Use transformation like n1g33r -> nigger")

parser.add_argument('--use_jamspell', action = 'store_true', help = "Use JamSpell autocorrection")

parser.add_argument('--keep_only_letters', action = 'store_true', help = "Keep only A-Z a-z letters")

parser.add_argument('--use_lemmatization', action = 'store_true', help = "Use lemmatization")

parser.add_argument('--use_stemming', action = 'store_true', help = "Use stemming")

parser.add_argument('--valid_size', type = float, default = 0.05, help = 'Size of validation set')

parser.add_argument('--max_features', type = int, default = 250000, help = 'Max features')

parser.add_argument('--maxlen', type = int, default = 350, help = 'Max lenght of comment')

parser.add_argument('--fasttext', type = str, help = 'Path to fastText embeddings')

parser.add_argument('--glove', type = str, help = 'Path to Glove embeddings')

parser.add_argument('--lstm_size', type = int, default = 64, help = 'Size of LSTM')

parser.add_argument('--gru_size', type = int, default = 32, help = 'Size of GRU')

parser.add_argument('--recurrent_dropout', type = float, default = 0.25, help = 'Recurrent dropout value')

parser.add_argument('--dropout', type = int, default = 0.25, help = 'Dropout value')

parser.add_argument('--regularization', type = float, default = 1e-4, help = 'Regularization value')

parser.add_argument('--batch_size', type = int, default = 32, help = 'Batch size')

args = parser.parse_args()

print(args)

classes = ['toxic', 'severe_toxic', 'obscene', 'threat', 'insult', 'identity_hate']

print('Loading train data ...')

train_data = pd.read_csv('data/train.csv').append(

pd.read_csv('data/train_de.csv')).append(

pd.read_csv('data/train_fr.csv')).append(

pd.read_csv('data/train_es.csv')).fillna(' ')

train_data = train_data.sample(len(train_data))

print('Loading test data ...')

test_data = pd.read_csv('data/test.csv').fillna(' ')

if args.preprocess:

print('Preprocessing ...')

train_data['comment_text'] = preprocess(train_data['comment_text'],

lowercase = args.lowercase,

remove_urls = args.remove_urls,

remove_numbers = args.remove_numbers,

use_transformation = args.use_transformation,

use_correction = args.use_correction,

use_jamspell = args.use_jamspell,

keep_only_letters = args.keep_only_letters,

use_lemmatization = args.use_lemmatization,

use_stemming = args.use_stemming)

test_data['comment_text'] = preprocess(test_data['comment_text'],

lowercase = args.lowercase,

remove_urls = args.remove_urls,

remove_numbers = args.remove_numbers,

use_transformation = args.use_transformation,

use_correction = args.use_correction,

use_jamspell = args.use_jamspell,

keep_only_letters = args.keep_only_letters,

use_lemmatization = args.use_lemmatization,

use_stemming = args.use_stemming)

valid_data = train_data.iloc[-int(len(train_data)*args.valid_size):,:]

train_data = train_data.drop(valid_data.index)

max_features = args.max_features

maxlen = args.maxlen

print('Fitting tokenizer ...')

tokenizer = Tokenizer(max_features)

tokenizer.fit_on_texts(train_data['comment_text'])

print('Transforming into sequences ...')

X_train = tokenizer.texts_to_sequences(train_data['comment_text'])

X_train = pad_sequences(X_train, maxlen)

X_test = tokenizer.texts_to_sequences(test_data['comment_text'])

X_test = pad_sequences(X_test, maxlen)

X_valid = tokenizer.texts_to_sequences(valid_data['comment_text'])

X_valid = pad_sequences(X_valid, maxlen)

y_train = train_data.iloc[:,2:]

y_valid = valid_data.iloc[:,2:]

input = Input(shape=(maxlen,))

if args.fasttext:

print('Loading fastText embeddings ... ')

fasttext_embedding_dim = 300

fasttext_max_features = max_features

fasttext_embeddings = models.KeyedVectors.load_word2vec_format(args.fasttext)

keys = list(fasttext_embeddings.vocab.keys())

tmp = pd.DataFrame([ np.append(keys[i],fasttext_embeddings.syn0[i]) for i in range(0,len(keys))])

embeddings_index = {}

for i in range(0,len(tmp)):

values = np.array(tmp.iloc[i])

word = values[0]

coefs = np.asarray(values[1:], dtype='float32')

embeddings_index[word] = coefs

fasttext_embedding_matrix = np.zeros((fasttext_max_features, fasttext_embedding_dim))

for word, i in tokenizer.word_index.items():

if i >= fasttext_max_features:

continue

embedding_vector = embeddings_index.get(word)

if embedding_vector is not None:

fasttext_embedding_matrix[i] = embedding_vector

fasttext_embeddings = Embedding(input_dim = max_features, output_dim = 300,

embeddings_regularizer = regularizers.l2(1e-4),

trainable = False, weights = [fasttext_embedding_matrix])(input)

else:

fasttext_embeddings = Embedding(input_dim = max_features, output_dim = 300,

embeddings_regularizer = regularizers.l2(1e-4))(input)

if args.glove:

print('Loading glove embeddings ... ')

glove_embedding_dim = 200

glove_max_features = max_features

tmp = pd.read_csv(args.glove,header=None)

embeddings_index = {}

for i in range(0,len(tmp)):

values = np.array(tmp.iloc[i])

word = values[0]

coefs = np.asarray(values[1:], dtype='float32')

embeddings_index[word] = coefs

glove_embedding_matrix = np.zeros((glove_max_features, glove_embedding_dim))

for word, i in tokenizer.word_index.items():

if i >= glove_max_features:

continue

embedding_vector = embeddings_index.get(word)

if embedding_vector is not None:

glove_embedding_matrix[i] = embedding_vector

glove_embeddings = Embedding(input_dim = max_features, output_dim = 200,

embeddings_regularizer = regularizers.l2(args.regularization),

trainable = False, weights = [glove_embedding_matrix])(input)

else:

glove_embeddings = Embedding(input_dim = max_features, output_dim = 200,

embeddings_regularizer = regularizers.l2(args.regularization))(input)

concatenated_embeddings = concatenate([fasttext_embeddings, glove_embeddings])


Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.