Почему характеристики так важны?

машинное обучение

Автор: Винко Коджоман

Перевод: Лао Ци

Я работаю над соревнованием по машинному обучению Quora Q&A на Kaggle уже месяц, и я заметил тему, которая неоднократно обсуждалась, и хотел бы поговорить о ней сейчас.Кажется, существует непреодолимая граница для машинного обучения моделей, хотя есть методы, которые обычно дают очень хорошие результаты, но из-за особенностей данных верхний предел не может быть превышен. Итак, я хочу подчеркнуть, что функции очень важны.

Примечание. В марте 2020 г. в Electronic Industry Press была опубликована статья «Подготовка данных и проектирование функций». В книге есть специальные главы, объясняющие, как выполнять выбор функций, включая метод выбора функций на основе важности функций, представленный в этой статье.

исследование данных

Ниже я буду использовать набор вопросов и ответов Quora, в котором всего 404 290 вопросов и ответов, из которых 37% вопросов семантически идентичны («дубликаты»), и наша цель — найти их.

Примечание. Проект этой статьи и другой связанный проект: Идентификация повторяющихся вопросов включены в «Случай машинного обучения», который также заполняется с использованием данных Quora Q&A.

Для начала необходимо загрузить и изучить набор данных:

# Load the dataset
train = pd.read_csv('train.csv', dtype={'question1': str, 'question2': str})
print('Training dataset row number:', len(train))  # 404290
print('Duplicate question pairs ratio: %.2f' % train.is_duplicate.mean())  # 0.37

Примеры повторяющихся и неповторяющихся пар вопросов показаны ниже.

Вопрос 1 вопрос 2 это лишнее
What is the step by step guide to invest in share market in india? What is the step by step guide to invest in share market? 0
How can I be a good geologist? What should I do to be a great geologist? 1
How can I increase the speed of my internet connection while using a VPN? How can Internet speed be increased by hacking through DNS? 0
How do I read and find my YouTube comments? How do I read and find my YouTube comments? 1

Используйте облака слов для представления результатов исследования данных, показывая, какие слова встречаются чаще всего. Облако слов создано на основе слов в вопросе и ответе, и, как вы можете видеть, популярные слова такие, как вы и ожидали (например, «лучший способ», «похудеть», «разница», «заработать деньги»). ", и т.д.).

Этот результат облака слов см. в разделе «Выявление повторяющихся проблем» в случаях машинного обучения.

Теперь у нас есть некоторое представление о том, как выглядит набор данных.

разработка функций

Я создал 24 функции, некоторые из которых показаны ниже. Весь код написан на Python с помощью библиотек машинного обучения (pandas, sklearn, numpy).

Код этой статьи был включен в общедоступный онлайн-курс «Случаи машинного обучения», обратите внимание на общедоступную учетную запись этой статьи и ответьте: имя + номер мобильного телефона + «кейс», вы можете подать заявку на участие в этом курсе.

  • q1_word_num: количество слов в вопросе 1
  • q2_length: количество символов в вопросе 2
  • word_share: соотношение общих слов между вопросами
  • same_first_word: 1, если первое слово двух вопросов одинаковое, иначе 0
def word_share(row):
    q1_words = set(word_tokenize(row['question1']))
    q2_words = set(word_tokenize(row['question2']))
           
    return len(q1_words.intersection(q2_words)) / (len(q1_words.union(q2_words)))

def same_first_word(row):
    q1_words = word_tokenize(row['question1'])
    q2_words = word_tokenize(row['question2'])
        
    return float(q1_words[0].lower() == q2_words[0].lower())

# A sample of the features
train['word_share'] = train.apply(word_share, axis=1)
train['q1_word_num'] = train.question1.apply(lambda x: len(word_tokenize(x)))
train['q2_word_num'] = train.question2.apply(lambda x: len(word_tokenize(x)))
train['word_num_difference'] = abs(train.q1_word_num - train.q2_word_num)
train['q1_length'] = train.question1.apply(lambda x: len(x))
train['q2_length'] = train.question2.apply(lambda x: len(x))
train['length_difference'] = abs(train.q1_length - train.q2_length)
train['q1_has_fullstop'] = train.question1.apply(lambda x: int('.' in x))
train['q2_has_fullstop'] = train.question2.apply(lambda x: int('.' in x))
train['q1_has_math_expression'] = train.question1.apply(lambda x: int('[math]' in x))
train['q2_has_math_expression'] = train.question2.apply(lambda x: int('[math]' in x)) 
train['same_first_word'] = train.apply(same_first_word, axis=1)

Производительность модели

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

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

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

logloss = \frac{1}{N} \displaystyle\sum_{i=1}^{N} \displaystyle\sum_{j=1}^{M} y_{i,j} * log(p_{i,j})

Чтобы протестировать все функции модели, мы используем модель классификации случайного леса, которая представляет собой мощный «стандартный» ансамблевый классификатор. Никаких оптимизаций гиперпараметров — они могут остаться прежними, потому что мы тестируем производительность модели на разных наборах функций. Простая модель дает показатель логарифмических потерь 0,62923, что на момент написания этой статьи занимает 1371-е место из 1692 команд. Теперь давайте посмотрим, может ли выбор функций помочь нам уменьшить потери журнала.

model = RandomForestClassifier(50, n_jobs=8)
model.fit(X_train, y_train)

predictions_proba = model.predict_proba(X_test)
predictions = model.predict(X_test)

log_loss_score = log_loss(y_test, predictions_proba)
acc = accuracy_score(y_test, predictions)
f1 = f1_score(y_test, predictions)

print('Log loss: %.5f' % log_loss_score)  # 0.62923
print('Acc: %.5f' % acc)  # 0.70952
print('F1: %.5f' % f1)  # 0.59173

Важность функций

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

model = XGBClassifier(n_estimators=500)
model.fit(X, y)
    
feature_importance = model.feature_importances_
    
plt.figure(figsize=(16, 6))
plt.yscale('log', nonposy='clip')

plt.bar(range(len(feature_importance)), feature_importance, align='center')
plt.xticks(range(len(feature_importance)), features, rotation='vertical')
plt.title('Feature importance')
plt.ylabel('Importance')
plt.xlabel('Features')
plt.show()

Как показано ниже, мы видим, что некоторые функции вообще бесполезны, в то время как некоторые функции (например, «word_share») сильно влияют на производительность. Мы можем добиться уменьшения размерности, создав подмножества функций на основе их важности.

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

def extract_pruned_features(feature_importances, min_score=0.05):
    column_slice = feature_importances[feature_importances['weights'] > min_score]
    return column_slice.index.values

pruned_featurse = extract_pruned_features(feature_importances, min_score=0.01)
X_train_reduced = X_train[pruned_featurse]
X_test_reduced = X_test[pruned_featurse]

def fit_and_print_metrics(X_train, y_train, X_test, y_test, model):
    model.fit(X_train, y_train)
    predictions_proba = model.predict_proba(X_test)
    
    log_loss_score = log_loss(y_test, predictions_proba)
    print('Log loss: %.5f' % log_loss_score)

Производительность модели на основе анализа важности признаков

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

model = RandomForestClassifier(50, n_jobs=8)
# LogLoss 0.59251
fit_and_print_metrics(X_train_reduced, y_train, X_test_reduced, y_test, model) 
    
# LogLoss 0.63376
fit_and_print_metrics(X_train, y_train, X_test, y_test, model)

Присмотревшись к показателю важности функции (построение логарифмических потерь классификатора для подмножества усеченных функций), мы можем еще больше уменьшить потери. В данном конкретном случае случайные леса лучше всего работают только с одной функцией! Использовать только функции"word_share", чтобы получить 0,5544 балла в оценке logloss.

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

в заключении

Как я показал, анализ важности признаков может улучшить производительность модели. Хотя некоторые модели, такие как XGBoost, выбирают функции за нас, все же важно понимать влияние определенной функции на производительность модели, поскольку это дает нам больший контроль над выполняемой задачей. Теорема «нет бесплатного обеда» (нет проблемы «наилучшего для всех») говорит нам, что, хотя XGBoost обычно работает лучше, чем другие модели, нам все же нужно судить, действительно ли это лучшее решение. Получение подмножества важных функций с помощью XGBoost позволяет нам повысить производительность модели, передавая это подмножество функций в модель без выбора функций. Использование выбора функций на основе их важности может значительно улучшить производительность модели.

Оригинальная ссылка:данные какие сейчас.com/feature-imp…

Обратите внимание на публичный аккаунт WeChat: Lao Qi Classroom. Читайте подробные статьи, получайте превосходные навыки и наслаждайтесь блестящей жизнью.