Ціль цієї статті — продемонструвати, як комбінація технік може бути використана для отримання цінності з помірних наборів даних. Я представлю вигаданий набір даних і випадок використання та розгляну деякі методи машинного навчання, які можна застосувати для швидкого збагачення даних в осмислений спосіб, що може бути потужним у комерційному світі.
Уявіть, що ви — великий виробник одягу, який шукає способи реалізувати нову стратегію цифрового маркетингу. Ви хочете створити окремі кампанії для різних груп серед ваших клієнтів на основі спільних атрибутів. Простий спосіб досягти цього — це використання детерміністичних методів, таких як визначення правил, які б казали: «показати цю синю спідницю всім клієнтам, які люблять синій», однак ми хочемо піти далі та вирішити, що саме буде найкращим способом на основі більш складних методів. Ось як ми можемо досягти кращих результатів, використовуючи аналіз даних, семантичну обробку, несупервайзерне кластерування та деяку вигадливість із групуванням кольорів.
Оскільки це вигаданий приклад, мій перший крок — використати faker для створення уявних даних з іменами клієнтів та кількома супутніми атрибутами, такими як професія, місто, улюблений колір і титул.
# Імпортуємо всі необхідні бібліотеки
from faker import Faker #для генерації уявних даних
import pandas as pd #для маніпуляції з даними
import numpy as np #для числових операцій
from sentence_transformers import SentenceTransformer #для семантичної обробки тексту BERT
from sklearn.cluster import KMeans #для кластеризації
from sklearn.decomposition import PCA #для зменшення розмірності
import matplotlib.pyplot as plt #для побудови графіків
import webcolors #для перетворення назв кольорів у RGB
# створюємо уявний набір даних за допомогою faker
fake = Faker()
dataset_size = 10000
fake_names_lst = [fake.name() for _ in range(dataset_size)]
fake_color_lst = [fake.color_name() for _ in range(dataset_size)]
fake_job_lst = [fake.job() for _ in range(dataset_size)]
fake_city_lst = [fake.city() for _ in range(dataset_size)]
fake_suffix_lst = [fake.suffix() for _ in range(dataset_size)]
data_struct = {
'Name' : fake_names_lst,
'Color': fake_color_lst,
'Job' : fake_job_lst,
'City' : fake_city_lst,
'Suffix' : fake_suffix_lst
}
main_df = pd.DataFrame(data_struct)
Знімок екрана для демонстрації уявних даних, створених бібліотекою Faker
У реальному світі ми часто працюємо з даними високої розмірності. Простими словами, атрибут може мати багато окремих значень. В нашому уявному прикладі ми можемо побачити це в атрибуті «Job» або «Color», де є понад 100 різних значень. Оскільки ми не можемо створити понад 100 різних маркетингових кампаній для відповідних атрибутів, перший крок — розробити метод класифікації для створення кластерів із наявних даних.
Семантична обробка і K-means кластеризація
Один із способів зменшення розмірності нашого набору даних — це аналізувати значення наших атрибутів і групувати їх на основі семантичних концептів. Ми робимо це природно в мові, наприклад, об’єднуючи «CEO» і «CFO» в категорію керівників або «Frontend Engineer» і «QA» як інженерів. Те ж саме можна зробити з даними, створивши числове представлення слів у великих багатовимірних векторах, а потім порівнюючи відстані між ними. Чим ближчі вектори один до одного, тим схожіша семантика слів. Середнє або сума через речення також дозволяє робити те ж саме для більших обсягів тексту.
Процес знаходження числового представлення слова називається вбудовуваннями.
Word2Vec — це модель, що є частиною бібліотеки Gensim, яка дозволяє виконувати ці вбудовування, підтримуючи як натреновані, так і ненатреновані версії. Як несупервайзерна модель кластеризації машинного навчання (ML), Word2Vec може бути натренований виключно на ваших даних (це доцільно, якщо у вас є великий репозиторій текстових даних), де він визначатиме правильне представлення ваших слів у векторному просторі. Для випадків використання, коли ви працюєте з короткими або одиночними реченнями, краще використовувати попередньо натреновану версію, оскільки контекст важливий для ефективного створення точних векторів. Стикавшись із труднощами в ефективному використанні для моїх назв посад, я звернувся до використання BERT від hugging face для генерації вбудовувань. BERT натренований на більшому корпусі і, на відміну від Word2Vec, є багатим вбудовуванням, яке враховує контекст і навколишні слова. Також його набагато легше використовувати, оскільки не потрібні попередні кроки, такі як токенізація чи стандартизація — все це обробляється під капотом.
# Завантажуємо попередньо натреновану модель BERT з Sentence-Transformers
model = SentenceTransformer('all-MiniLM-L6-v2')
# Генеруємо вбудовування BERT для назв посад
job_titles = main_df['Job'].tolist()
embeddings = model.encode(job_titles)
BERT генерує великі вектори, як ми можемо побачити, вектори, які він створив для моїх назв посад, мають довжину 384 (це насправді mini-BERT, який має подібну продуктивність, але є меншим порівняно з оригінальним BERT розміром 768). Фактично, те, що відбувається під капотом, це те, що слова, які ви передаєте BERT, потім шукаються і передаються через шар трансформера (це гарне поглиблене керівництво по BERT)
Тут ми можемо побачити, що посада "Коректор" була перетворена на вектор розміром 384
Щоб підготувати і спростити наші дані для кластеризації, я використовую PCA, техніку зменшення розмірності, яка зменшує шум і фокусується на найважливіших ознаках.
# зменшуємо розмірність для кращої кластеризації
pca = PCA(n_components=50) # Зменшуємо до 50 вимірів
reduced_embeddings = pca.fit_transform(embeddings)
Тепер, коли наші назви посад вбудовані та зменшені до зручних 50 вимірів, ми можемо виконати кластеризацію. Для цього я вибрав K-means через його простоту та зрозумілість. Ця модель машинного навчання обчислює евклідову відстань між векторами, щоб визначити їхні кластери. Як вхідний параметр потрібно подати модель кількість кластерів, які ви хочете, щоб модель вивела. Це не є конкретною наукою, але можна визначити кількість, запустивши скрипт з різними розмірами кластерів і візуалізуючи результат, перевіряючи, чи задоволені ви згуртованістю груп. Як альтернатива можна використовувати метод ліктя або метод силуета для допомоги в цьому.
У моєму випадку я вибрав 8, оскільки мене задовольняє групування на цьому рівні, і це відповідає моєму теоретичному випадку використання, де команда цифрового маркетингу не хоче створювати більше 8 окремих кампаній.
# KMeans кластеризація
kmeans = KMeans(n_clusters=8, random_state=42)
main_df['Cluster'] = kmeans.fit_predict(reduced_embeddings)
# PCA для візуалізації
pca_2d = PCA(n_components=2)
embeddings_2d = pca_2d.fit_transform(reduced_embeddings)
# побудова графіку для кластерів
plt.figure(figsize=(10, 8))
plt.scatter(embeddings_2d[:, 0], embeddings_2d[:, 1], c=main_df['Cluster'], cmap='viridis')
plt.title('2D візуалізація кластерів назв посад')
plt.xlabel('PCA Компонент 1')
plt.ylabel('PCA Компонент 2')
plt.colorbar()
plt.show()
# перевірка кластерів
for i in range(8):
print(f"Кластер {i}:")
print(main_df[main_df['Cluster'] == i]['Job'].tolist())
print()
Кластери вбудовувань назв посад, використовуючи BERT від Hugging Face та K-Means
Порівнюючи когорти, результат досить вдалий, наприклад, Когорта 0: [‘Менеджер з виробництва’, ‘Сертифікований керуючий бухгалтер’, ‘Менеджер з обслуговування клієнтів’, ‘Менеджер розважального центру’, ‘Менеджер архіву’, ‘Менеджер конференц-центру’, ‘Менеджер тематичного парку’…], тоді як Когорта 2: [‘Вчитель початкової школи’, ‘Адміністратор освіти’, ‘Офіцер з підготовки та освіти в збройних силах’, ‘Лектор вищої освіти’, ‘Старша медсестра’, ‘Міжнародний працівник з надання допомоги/розвитку’ …]. Не погано! Тепер набір даних був розширений автоматичними когортами, визначеними за допомогою семантичної обробки та методів несупервайзерного навчання. Замість 639 окремих значень у моєму стовпці "Посада", я зібрав їх у 8 груп; набагато зручніше.
Виявилося, що складно працювати з кольорами
Використовуючи Faker, я зміг швидко створити умовні дані про кольори, які в моєму прикладі сьогодні я інтерпретую як улюблений колір умовних осіб у моєму наборі даних. Коли я це робив, я припустив, що зможу застосувати ту ж саму логіку, що й вище, до мого стовпця «Колір». Я помилився. Це призвело до погано згенерованих вбудовувань як з Word2Vec, так і з FastText та BERT, і навіть ще більш шокуючих кластерів. Причина цього в тому, що кольори є більш конкретними, ніж концептуальними, і попередньо натреновані моделі, такі як BERT, не мають контексту щодо кольорів. Тому, незважаючи на те, що створення атрибуту кольору зайняло кілька секунд, я створив проблему, намагаючись з’ясувати, який найкращий спосіб просто кластеризувати кольори без надмірних ручних зусиль. Це чудова демонстрація того, як важливо вибирати, які методи використовувати, і як один розмір не підходить для всіх.
Чудова річ у кольорах полягає в тому, що ми вже маємо певні вбудовування для них у вигляді RGB.
Щоб вирішити нашу проблему з кольорами, я просто взяв стовпець «Color» і використав бібліотеку для відображення рядкових значень кольорів на представлення в RGB.
# Перетворення назв кольорів у значення RGB
def name_to_rgb(color_name):
try:
# Перетворення назви кольору в RGB
return np.array(webcolors.name_to_rgb(color_name)) / 255.0 # Нормалізація значень RGB в діапазон [0, 1]
except ValueError:
return np.array([0, 0, 0]) # За замовчуванням чорний, якщо назва кольору некоректна
# Застосування функції RGB
main_df['rgb'] = main_df['Color'].apply(name_to_rgb)
Набір даних, збагачений стовпцем Cluster та представленням кольору в RGB
Тепер, коли ми маємо представлення RGB для кожного кольору в нашому наборі даних, ми можемо просто вручну визначити кластери для наших кольорів, використовуючи просту логіку, яким кольором є найдомінуючий, зменшуючи їх з 140 унікальних значень до 3.
# Функція для класифікації домінуючого кольору в RGB
def classify_dominant_color(rgb):
red, green, blue = rgb
if red >= green and red >= blue:
return 'Red'
elif green >= red and green >= blue:
return 'Green'
elif blue >= red and blue >= green:
return 'Blue'
# Застосування функції до стовпця
main_df['Color'] = main_df['rgb'].apply(classify_dominant_color)
Об'єднавши інформацію з кластеризації та обробки RGB, можна провести подальший аналіз, щоб зрозуміти сегментацію в кластерах та які атрибути має кожна когорта. Висновок: вищеописана логічна ланцюжок демонструє, як різні методи можна використовувати послідовно для збагачення даних та створення вартості для бізнесу, роблячи їх більш зручними для використання та допомагаючи у формуванні бізнес-стратегії, такій як створення стратегії цифрового маркетингу.
Перекладено з: Chain of Logic: Extracting value from data through the use of semantic processing, unsupervised clustering methods (& RGB processing)