1. Что такое многоуровневая классификация?
  2. В чем разница между Multilabel и Multiclass?
  3. Как решить проблему с несколькими метками (примеры)?
  4. Заключение

Введение

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

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

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

– Прогностическое моделирование классификации
– Двоичная классификация
– Многоклассовая классификация
– Несбалансированная классификация
– Многоуровневая классификация

В этой статье, прежде всего, мы дадим вам интуитивно понятное объяснение того, что влечет за собой классификация с несколькими метками, а также разницу между Multilabel и Multiclass и проиллюстрируем подход нейронных сетей к решению проблемы, связанной с набором данных Stack Overflow. Вы можете получить этот набор данных с несколькими метками с помощью этой команды: !gsutil cp ‘gs://ml-design-patterns/so_data.csv’.

1. Что такое многоуровневая классификация?

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

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

2. В чем разница между многоуровневой и многоклассовой проблемой?

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

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

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

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

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

3. Как решить проблему Multilabel?

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

Например, если наша модель классифицирует три изображения (кошки, собаки или обезьяны). вывод softmax может выглядеть так для данного изображения [0,80, 0,12, 0,08]. Этот результат означает, что наша модель имеет 80%-й шанс предсказать кошек, 12%-й шанс, что это собака и 8%-й шанс, что это обезьяна. Это потому, что каждое изображение может иметь только одну возможную метку в этом сценарии, мы можем взять argmax, который выбирает индекс с наибольшей вероятностью, чтобы определить прогнозируемый класс нашей модели. В накладном менее распространенном сценарии каждому обучающему примеру может быть присвоено более одной метки, что и касается Mutlilabel.

Когда мы имеем дело с классификацией текста с несколькими метками, мы строим модель, которая классифицирует данный текстовый ввод по разным категориям. Наш текстовый ввод может принадлежать нескольким категориям или меткам одновременно. Здесь мы используем в качестве примера набор данных «вопросы переполнения стека» и строим модель для предсказания тегов, связанных с конкретным вопросом.

Примером вопроса может быть «Как я могу построить DataFrame pandas?». Этот пример можно пометить как «Python», «pandas» и «visualization». Модель, которая идентифицирует комментарии ненависти в социальных сетях, представляет собой пример классификации текста с несколькими метками, и комментарии могут быть помечены как «вредные» и «непристойные».

Мы будем использовать исследовательский анализ данных (EDA) (pandas, numpy) для чтения нашего набора данных, выполнения математических вычислений и загрузки пакетов машинного обучения (sklearn, tensorflow).

import numpy as np
import pandas as pd
import tensorflow as tf

from tensorflow import keras
from tensorflow.keras import Model
from tensorflow.keras.layers import Dense, Embedding, Input, Flatten, Conv2D, MaxPooling2D

from sklearn.utils import shuffle
from sklearn.preprocessing import MultiLabelBinarizer
# we use pandas to load our dataset
data = pd.read_csv('so_data.csv', names=['tags', 'original_tags', 'text'], header=0)
# check the available columns in our dataset
data.head()

Вывод такой, как показано:

Мы удаляем столбец «original_tags» из набора данных и удаляем отсутствующие значения со строками кода ниже.

data = data.drop(columns=['original_tags'])
data = data.dropna()

data = shuffle(data, random_state=22)
data.head()

Вывод такой, как показано:

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

def tags_encoding(data):
  '''
  Converts between this intuitive format and the supported multilabel format
  @param dataset: All the dataset
  return classes, num_tags, tags_encoded
  '''
  tags_split = [tags.split(',') for tags in data['tags'].values]
  tag_encoder = MultiLabelBinarizer()
  tags_encoded = tag_encoder.fit_transform(tags_split)
  classes = tag_encoder.classes_
  num_tags = len(tags_encoded[0])

  return classes, num_tags, tags_encoded

И вы закончите с

Мы разделили набор данных на набор поездов и набор тестов, которые помогают нам оценить истинную производительность модели. Здесь случайная выборка используется для разделения данных на две части. 80 % набора данных используется в качестве обучающего набора, а 20 % — в качестве тестового.

def data_split(data):
  '''
  Split our dataset into train and test sets
  @param data: All the dataset
  return train_size, test_size: The size of train and test sets
  '''
  train_size = int(len(data) * 0.8)
  test_size = len(data) - train_size
  return train_size, test_size

Результат функции выше:

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

def tags_spliter(tags_encoded):
  '''
  Split our labels into train and test sets
  @param tags_encoded: All tags encoded by Multilabel encoder
  return train_tags, test_tags
  '''
  train_tags = tags_encoded[:data_split(data)[0]]
  test_tags = tags_encoded[data_split(data)[0]:]
    
  return train_tags, test_tags

Показан вывод закодированных тегов:

«data_questions», который является атрибутом данных «текст» (data[‘text’]), разделен на наборы train_qs и test_qs с помощью функции ниже.

def data_questions_spliter(data, train_size):
  '''
  Split our data text into train and test
  @param tags_encoded: All tags encoded by Multilabel encoder
  return train_qs, test_qs
  '''
  train_qs = data['text'].values[:train_size]
  test_qs = data['text'].values[train_size:]
    
  return train_qs, test_qs

Чтобы визуализировать результаты функции выше, попробуйте эту команду:

train_qs, test_qs = data_questions_spliter(data, 150559) # train_size=150559

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

from tensorflow.keras.preprocessing import text
import os

# Avoid gpu using
os.environ["CUDA_VISIBLE_DEVICES"]="-1" 

# This is a hyperparameter, you can try out different values for your dataset
VOCAB_SIZE=400  
tokenizer = text.Tokenizer(num_words=VOCAB_SIZE)
tokenizer.fit_on_texts(train_qs)

body_train = tokenizer.texts_to_matrix(train_qs)
body_test = tokenizer.texts_to_matrix(test_qs)

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

def build_model():
    classes, num_tags, _ = tags_encoding(data)
    train_tags, test_tags = tags_spliter(tags_encoded)

    # Note we're using sigmoid output with binary_crossentropy loss
    model = tf.keras.models.Sequential()
    model.add(tf.keras.layers.Dense(50, input_shape=(VOCAB_SIZE,), activation='relu'))
    model.add(tf.keras.layers.Dense(25, activation='relu'))
    model.add(tf.keras.layers.Dense(num_tags, activation='sigmoid'))

    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

    model.summary()

    # Train and evaluate the model
    model.fit(body_train, train_tags, epochs=3, batch_size=128, validation_split=0.1)
    print('Eval loss/accuracy:{}'.format(
    model.evaluate(body_test, test_tags, batch_size=128)))

    return model 

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

При анализе сигмоидальных результатов, в отличие от вывода softmax, мы не можем просто взять argmax выходного массива вероятностей. Нам нужно рассмотреть наши пороги для каждого класса. В этом случае мы скажем, что тег связан с вопросом, если наша модель уверена более чем на 80%.

Ниже мы напечатаем исходный вопрос вместе с предсказанными тегами нашей модели.

def predict_tags():
  # Get some test predictions
  predictions = model.predict(body_test[:3])
  for question_idx, probabilities in enumerate(predictions):
    print(test_qs[question_idx])
    for idx, tag_prob in enumerate(probabilities):
      if tag_prob > 0.8:
        print(classes[idx], round(tag_prob * 100, 2), '%')
        print('')

Вывод такой, как показано:

4. Вывод

Не все мультиклассовые классификаторы являются классификаторами с несколькими метками, и мы не должны предполагать это, если это явно не указано.

Надеюсь, это поможет в построении надежной обобщенной модели для классификации с несколькими метками.

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

В частности, вы узнали:

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

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

Надеюсь, вам понравилось это руководство. Спасибо за прочтение..!

Использованная литература: