В этой статье рассмотрим, как можно использовать глубокое обучение для оценки различных негативных окрасок текста, таких как угрозы, непристойности, оскорбления.
Данные
Набор данных был создан командой Conversation AI. Тексты взяты из комментариев к правкам на странице обсуждения Википедии. Исходные данные состоят 223 549 примеров с разметкой.
Нужно на основе текста сообщения (comment_text) предсказать тональность (колонки toxic, severe_toxic, obscene, threat, insult, identity_hate). Значение 1 показывает наличие негативной составляющей:
comment_text |
toxic |
severe_toxic |
obscene |
threat |
insult |
identity_hate |
"You should be fired, you're a moronic wimp who is too lazy to do research. It makes me sick that people like you exist in this world." |
1 |
0 |
0 |
0 |
1 |
0 |
"Oh, I didn't know, thanks." |
0 |
0 |
0 |
0 |
0 |
0 |
Модели
Глубокое обучение предлагает следующие модели для определения эмоциональной окраски текста:
сверточные нейронные сети (CNN, convolutional neural network): класс нейронных сетей, часто применяемых в обработке изображений, но также успешно используемых в обработке текстов. В случае сентимент-анализа текста, сверточные слои CNN могут использоваться для извлечения локальных признаков из текста, а последующие полносвязные слои для классификации и определения тональности;
рекуррентные нейронные сети (RNN, Recurrent neural network): класс нейронных сетей, способных моделировать последовательности данных. Сети с долгой краткосрочной памятью (LSTM, long short-term memory) и модель с управляемыми рекуррентными блоками (GRU, Gated Recurrent Unit) являются расширениями RNN, позволяющими более эффективно учитывать долгосрочные зависимости в тексте;
Transformer: модель способна эффективно моделировать зависимости между словами в тексте и учитывать их важность при принятии решения о тональности. Примером такой модели является BERT (Bidirectional Encoder Representations from Transformers).
В статье рассмотрим и сравним CNN, LSTM и GRU.
Обработка данных
Для удобства обработки, тексты должны быть разбиты на одинаковое количество блоков. Далее из них будет составлен словарь, в котором каждому фрагменту будет соответствовать некое число, и каждый комментарий будет преобразован в вектор с различными значениями. Следует понять, какое оптимальное количество блоков нам нужно (слишком маленькое уменьшит точность предсказаний, слишком большое — увеличит время и сложность вычислений). Посмотрим, из скольких слов состоят сообщения в тексте:
Как видно, в среднем тексты состоят из 68 слов, а также большая часть из них содержит менее 76 слов, но есть и тексты с 2834 словами.
При выборе количества блоков стоит взять такое число, которое покроет большую часть текстов. Рассмотрим график подсчета (count plot) для длины сообщений:
По графику видно, что большая часть текстов содержит примерно до 250-300 слов, также имеется некоторое количество около 500. Попробуем узнать, какую часть текстов покрывают сообщения, содержащие до 250 и до 500 слов.
250 слов покрывают 95,65% слов, а 500 — 98,63%. Но разница между ними незначительна, поэтому для того, чтобы не увеличивать количество вычислений в будущей нейронной сети, возьмём разбиение на 250 слов.
Посмотрим, что представляет себой сообщение, которое имеет более 1000 слов в своем составе
Большинство таких комментариев содержат или повторяющие слова, или множество побочных символов (например, знаки препинания или иероглифы). Все лишнее стоит убрать. Также для стандартизации текста все следует перевести к одному регистру. Функция, которую мы будем использовать для представления текста к одному виду:
def custom_standardization(sentence):
# приводим в нижний регистр
sample = tensorflow.strings.lower(sentence)
# убираем не словесные знаки (к словесным относятся буквы, цифры и т.д.)
sample = tensorflow.strings.regex_replace(sample, '\W', ' ')
# убираем цифры
sample = tensorflow.strings.regex_replace(sample, '\d', ' ')
# убираем знаки препинания
return tensorflow.strings.regex_replace(sample,
'[%s]'%re.escape(string.punctuation), '')
После всего мы можем составить слой векторизации, с помощью которого мы приведем сообщения к стандартному виду:
vectorize_layer = tensorflow.keras.layers.TextVectorization(
standardize=custom_standardization,
split='whitespace',
max_tokens=max_features,
output_mode='int',
output_sequence_length=sequence_length,
encoding='utf-8')
vectorize_layer.adapt(train['comment_text'])
Также разделим данные на тренировочную и тестовую выборки, предварительно преобразовав сообщения с помощью слоя векторизации.
X = train["comment_text"]
Y = train[train.columns[2:-1]]
X = np.array(vectorize_layer(X))
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2)
Построение моделей
Начнем с свёрточной нейронной сети:
embedding_dim = 9
cnn_model = Sequential()
# сначала ембединг
cnn_model.add(Embedding(max_features+1, embedding_dim))
cnn_model.add(Dropout(0.2))
# далее уменьшим размерность
cnn_model.add(GlobalAveragePooling1D())
cnn_model.add(Dropout(0.2))
cnn_model.add(Dense(16, activation='relu'))
# слой для вывода результата. сигмоида для того, чтобы попасть в рамки [0, 1]
# в остальных моделях последним слоем также будет сигмоида
cnn_model.add(Dense(6, activation='sigmoid'))
cnn_model.compile(loss='binary_crossentropy',
optimizer='Adam',
metrics=['accuracy'])
Посмотрим, сколько времени требуется на обучение, а также какая точность предсказаний:
Она работает достаточно быстро (обучение одной эпохи занимает 3-5 секунд), обладает высокой точностью.
Аналогично построим модель нейронной сети с долгой краткосрочной памятью (long short-term memory; LSTM) и оценим ее время работы и точность:
lstm_epochs = 5
lstm_model = Sequential()
lstm_model.add(Embedding(max_features+1, embedding_dim))
lstm_model.add(LSTM(16))
lstm_model.add(Dropout(0.2))
lstm_model.add(Dense(16, activation='relu'))
lstm_model.add(Dense(6, activation='sigmoid'))
lstm_model.compile(loss='binary_crossentropy',
optimizer='Adam',
metrics=['accuracy'])
Нейронная сеть с долгой краткосрочной памятью работает намного медленнее свёрточной нейронной сети, при этом не обладая сильным преимуществом по точности.
Наконец, построим и оценим модель с управляемыми рекуррентными блоками (gated recurrent units, GRU)
gru_epochs = 5
gru_model = Sequential()
gru_model.add(Embedding(max_features+1, embedding_dim))
gru_model.add(GRU(16))
gru_model.add(Dropout(0.2))
gru_model.add(Dense(16, activation='relu'))
gru_model.add(Dense(6, activation='sigmoid'))
gru_model.compile(loss='binary_crossentropy',
optimizer='Adam',
metrics=['accuracy'])
gru_model.summary()
Работает медленней, чем свёрточная нейронная сеть, но быстрее чем сеть с долгой краткосрочной памятью, не обладает серьезным преимуществом в точности.
Выводы: из всех трёх моделей наилучшим образом себя показала свёрточная нейронная сеть.
Nasreddin_Hodja
Это тупиковый путь. Да и вообще многие сообщества умерли по причине этих новых трендов в модерировании с СЖВ. В итоге контингент разбрёлся по личным блогам, соцсетям и огороженным чатам.
Мне нравится как это само собой организовалось в федеративных сетях без модерации, она там просто не нужна, т.к. кажды сам себе модератор, при этом никто не страдает из-за того что самодур с банхаммером забанил кого-то тебе интересного. А классические сообщества с кармой и модераторами пережиток прошлого.
Sarukazm
Включая Хабр.
/thread