Я пытаюсь обучить текстовый классификатор на наборе учебных текстов (сообщения Reddit) с двумя эксклюзивными классами (1 и 0), касающимися функции авторов сообщений, а не самих сообщений .
Классы несбалансированы: примерно 75:25, что означает, что 75% авторов имеют значение "0", а 25% - "1".
Весь набор данных состоит из 3 столбцов: первый представляет автора поста, второй субреддит, к которому принадлежит пост, и третий фактический пост.
Данные
Набор данных выглядит следующим образом:
In [1]: train_data_full.head(5)
Out[1]:
author subreddit body
0 author1 subreddit1 post1_1
1 author2 subreddit2 post2_1
2 author3 subreddit2 post3_1
3 author2 subreddit3 post2_2
4 author5 subreddit4 post5_1
Где postI_J - это J-й пост I-го автора. Обратите внимание, что в этом наборе данных один и тот же автор может появляться более одного раза, если он / он опубликовал более одного раза.
В отдельном наборе данных у меня есть класс, к которому принадлежит каждый автор.
Первым делом я сгруппировал по автору:
def proc_subs(l):
s = set(l)
return " ".join([st.lower() for st in s])
train_data_full_agg = train_data_full.groupby(["author"], as_index = False).agg({'subreddit': proc_subs, "body": " ".join})
train_data_full_agg.head(5)
Out[2]:
author subreddit body
author1 subreddit1 subreddit2 post1_1 post1_2
author2 subreddit3 subreddit2 subreddit3 post2_1 post2_2 post2_3
author3 subreddit1 subreddit5 post3_1 post3_2
author4 subreddit7 post4_1
author5 subreddit1 subreddit2 post5_1 post5_2
В общей сложности 5000 авторов, 4000 для обучения и 1000 для проверки (roc_au c Гол). А вот код spaCy, который я использую (train_texts
- это подмножество train_data_full_agg.body.tolist()
, которое я использую для обучения, а test_texts
- то, которое я использую для проверки).
# Before this line of code there are others (imports and data loading mostly) which i think are irrelevant
train_data = list(zip(train_texts, train_labels))
nlp = spacy.blank("en")
if 'textcat' not in nlp.pipe_names:
textcat = nlp.create_pipe("textcat", config={"exclusive_classes": True, "architecture": "ensemble"})
nlp.add_pipe(textcat, last = True)
else:
textcat = nlp.get_pipe('textcat')
textcat.add_label("1")
textcat.add_label("0")
def evaluate_roc(nlp,textcat):
docs = [nlp.tokenizer(tex) for tex in test_texts]
scores , a = textcat.predict(docs)
y_pred = [b[0] for b in scores]
roc = roc_auc_score(test_labels, y_pred)
return roc
dec = decaying(0.6 , 0.2, 1e-4)
pipe_exceptions = ['textcat']
other_pipes = [pipe for pipe in nlp.pipe_names if pipe not in pipe_exceptions]
with nlp.disable_pipes(*other_pipes):
optimizer = nlp.begin_training()
for epoch in range(10):
random.shuffle(train_data)
batches = minibatch(train_data, size = compounding(4., 32., 1.001) )
for batch in batches:
texts1, labels = zip(*batch)
nlp.update(texts1, labels, sgd=optimizer, losses=losses, drop = next(dec))
with textcat.model.use_params(optimizer.averages):
rocs.append(evaluate_roc(nlp, textcat))
Проблема
Я получаю низкую производительность (измеряется RO C в тестовом наборе данных, на котором у меня нет меток), также по сравнению с более простыми алгоритмами, которые можно написать с помощью scikit learn (например, tfidf, bow, embeddings word) et c)
Попытки
Я пытался добиться большей производительности с помощью следующих процедур:
- Различные предварительные обработки / лемматизация текстов: лучшая кажется, удаляет все знаки препинания, числа, стоп-слова, из словарных слов, а затем лемматизирует все оставшиеся слова
- Испытанные архитектуры textcat: ансамбль, лук (также с параметрами
ngram_size
и attr
): кажется наилучшее чтобы быть ансамблем, с документация spaCy . - Попытка включить информацию о subreddit: я сделал это, обучив отдельную текстовую кошку на тех же столбцах 4000 авторов
subreddit
е. пункт 5. чтобы прочитать, как используется информация, поступающая с этого шага). - Пытался включить информацию о встраиваниях слов: используя векторы документов из
en_core_web_lg-2.2.5
модели spaCy, я на тех же 4000 агрегированных постах обучил многослойный персептрон scikit (см. Пункт 5., чтобы прочитать, как информация исходя из этого шага используется). - Затем, чтобы смешать информацию, поступающую из подразделов, постов и векторов документов, я обучил регрессии c логистики на 1000 предсказаний трех моделей (я также пытался сбалансировать классы на этом последнем шаге, используя adasyn
Используя эту регрессию logisti c, я получаю RO C = 0,89 по тестовому набору данных. Если я удалю любой из этих шагов и использую промежуточную модель, RO C понижает.
Я также попробовал следующие шаги, которые снова просто понизили RO C:
- Используйте предварительно обученные модели, такие как Bert. Код I используется аналогично этому
- Пытался сбалансировать классы с самого начала, используя меньший тренировочный набор.
- Пытался оставить пунктуацию и поставить
sentencizer
в начало nlp
конвейера
Дополнительная информация (в основном из комментариев)
Q: Что такое RO C базовой линии такие модели, как Multinomial Naive Bayes или SVM?
У меня есть легкий доступ к РПЦ, оцениваемым только по текстам (без субреддитов или векторов). SVM, настроенный так:
svm= svm.SVC(C=1.0, kernel='poly', degree=2, gamma='scale', coef0=0.0, shrinking=True, probability=True, tol=0.001, cache_size=200, class_weight=None, max_iter=-1)
даст ro c (с использованием Bow CountVectorizer) = 0,53 (то же самое с ядром rbf, но rbf + class_weight = None или «сбалансированный» дает 0,63 (то же самое без ограничение на cache_size)). Во всяком случае, XGBregressor с параметрами, установленными с gridsearch, даст ro c = 0,88. Тот же XGB, но также с подсчетами CountVectorizer и векторами scikit Doc2Ve c (в сочетании с lr, как указано выше) дает около 93. Код ансамбля, который вы видите выше, только для текстов, дает около 83. С subreddts и векторами (обработанными как выше) дает 89
Q: Вы пробовали не объединять?
Если я не объединяю, Производительность (только для не связанных текстов, поэтому опять нет векторов / подредактов) аналогична случаю, в котором я объединяю, но я бы тогда не знал, как объединить несколько предсказаний для одного автора в одно предсказание. Потому что помните, что у меня есть больше комментариев от каждого автора, и я должен предсказать двоичную особенность в отношении авторов.
Вопросы
- Есть ли у вас какие-либо предложения в частности, о коде spaCy, который я использую (например, любой другой способ использовать субредакты и / или информацию о векторах документов)?
- Как я могу улучшить общую модель?
Любое предложение высоко ценится.
Пожалуйста, будьте как можно точнее с точки зрения кода / объяснений / ссылок, поскольку я новичок в НЛП.