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

Что такое ДистилБЕРТ?

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

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

Что такое модели гауссовой смеси (GMM)?

Модели гауссовой смеси (GMM) — это алгоритм кластеризации, который используется для группировки точек данных в кластеры на основе их сходства. Алгоритм основан на предположении, что точки данных в кластере нормально распределены, и алгоритм пытается найти параметры, определяющие эти распределения.

Объединение DistilBERT и GMM для кластеризации заголовков

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

Чтобы продемонстрировать этот процесс, мы будем использовать набор названий средних статей из двух изданий Towards Data Science, UX Collective и The Startup.

Запуск DistilBERT для извлечения внедренных заголовков

import torch
import numpy as np
from transformers import AutoTokenizer, AutoModel

model_name = 'distilbert-base-cased'
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

title_embeddings = []
for title in titles:
    encoding = tokenizer.encode_plus(
        title,
        add_special_tokens=True,
        max_length=128,
        pad_to_max_length=True,
        return_attention_mask=True,
        return_tensors='pt'
    )
    with torch.no_grad():
        embedding = model(encoding['input_ids'], encoding['attention_mask'])[0][:, 0, :]
        title_embeddings.append(embedding.numpy())
title_embeddings = np.array(title_embeddings).squeeze()

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

Кластеризация заголовков

from sklearn.mixture import GaussianMixture
clusters = GaussianMixture(n_components=3).fit_predict(title_embeddings)

Этот код Python использует алгоритм Gaussian Mixture Model (GMM) для кластеризации вложений, сгенерированных DistilBERT. Сначала в коде указывается количество кластеров, которые необходимо сгенерировать с помощью алгоритма GMM. Затем он подгоняет алгоритм GMM к вложениям заголовков, создавая кластерные назначения для каждого заголовка. Эти назначения добавляются в список, который можно использовать для различных задач обработки естественного языка, таких как группировка похожих заголовков статей.

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

title_clusters = []
for i in range(len(np.unique(clusters))):
    cluster_titles = []
    for j, title in enumerate(titles):
        if clusters[j] == i:
            cluster_titles.append(title)
    title_clusters.append(cluster_titles)

Полученные результаты

Чтобы получить представление о качестве кластеризации, мы можем проверить первые 5 заголовков в каждом кластере:

for idx, cluster in enumerate(title_clusters):
    print(f'Cluster {idx}:')
    print('\n'.join(np.random.choice(cluster, 5)))
    print()

Это вернет:

Cluster 0: [Seems to be related to Towards Data Science topics]
Visualized Linear Algebra to Get Started with Machine Learning: Part 2
Hacking Causal Inference: Synthetic Control with ML approaches
Performance Estimation Techniques for Machine Learning Models
Claymorphism in user interfaces
How I Address Direct Questions on My Competitors as a 1-Man Consultant

Cluster 1: [Seems to be related to UX Collection topics]
Screen time: the next plastic?
Google wants you to test LaMDA; how UX research can help it outperform
The Vignelli Canon: A design classic from the last of the modernists
Standing at the crossroads of authenticity and career advancement
Product design is going down a weird path, but we can still save it

Cluster 2: [Seems to be related to The Startup topics]
I Tried Substack for a Month, You Won’t Believe What Happened
What I’m Doing as the Recession Gets Worse (To Avoid Going Broke)
Your Results Will Only Change When You Do
5 New Side Hustles You Didn’t Even Know Existed
4 Easy Tips To Make the Most Out of LinkedIn as a Newbie Writer

Для более эстетичного обобщения каждого кластера мы можем использовать облака слов:

def show_word_cloud(cluster):
    words = [word.lower() for title in cluster for word in title.split() if "'" not in word and '’' not in word and len(word)>1]
    text = " ".join(words)
    wordcloud = WordCloud(width = 800, height = 800, 
                    background_color ='white', 
                    stopwords = STOPWORDS, 
                    min_font_size = 10).generate(text)

    plt.figure(figsize = (2, 2), facecolor = None) 
    plt.imshow(wordcloud) 
    plt.axis("off") 
    plt.tight_layout(pad = 0) 

    plt.show()

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

Можете ли вы сделать предположение и соединить каждый кластер с соответствующей публикацией? ;)

Хотите больше кластеров?

Хотите посмотреть, как изменится качество при использовании большего количества кластеров? Посмотрите этот GIF, который демонстрирует кластеризацию с 10 кластерами.

Повышение уровня кодирования

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

  • 👏 Хлопайте за историю и подписывайтесь на автора 👉
  • 📰 Смотрите больше контента в публикации Level Up Coding
  • 💰 Бесплатный курс собеседования по программированию ⇒ Просмотреть курс
  • 🔔 Подписывайтесь на нас: Twitter | ЛинкедИн | "Новостная рассылка"

🚀👉 Присоединяйтесь к коллективу талантов Level Up и найдите прекрасную работу