Индонезия привлекает путешественников со всего мира своей яркой культурой, захватывающими дух пейзажами и дружелюбными местными жителями. Но планирование поездки может быть ошеломляющим. Вот почему мы создали Travelah: Your Ultimate Travel Buddy — индивидуальный способ познакомиться с туристическими достопримечательностями Индонезии. Попрощайтесь с общими руководствами и бесконечными исследованиями. Наше приложение предлагает индивидуальные рекомендации и иммерсивные культурные идеи. Пусть Travelah станет вашим пропуском к открытию чудес Индонезии. Приготовьтесь к незабываемому путешествию, как никакому другому.

Почему Travelah?

Прежде всего, почему мы создали Travelah? Вот почему…

  • Индонезия быстро становится одним из самых популярных туристических направлений в мире. Страна известна своей яркой культурой, захватывающими дух пейзажами и широким выбором направлений на выбор.
  • Тем не менее, с таким количеством мест, которые нужно посетить, и чем заняться, планирование поездки может быть ошеломляющим…
  • Путешественникам требуются часы поиска в Интернете, чтобы подготовиться к тому, что они хотят делать, какую еду попробовать и какое жилье им лучше всего подходит…

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

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

Мы вдохновились статьей Али, Н. (2020) и добавили еще один компонент, Систему рекомендаций, между NLU и NLG, чтобы сделать нашего чат-бота более мощным. Итак, основные компоненты нашего чат-бота:

  • Модель классификации намерений
  • Модель распознавания именованных объектов
  • Система рекомендаций (эта часть не будет объясняться в этой статье)

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

Классификация намерений и распознавание именованных объектов

Система рекомендаций

Теперь мы более подробно обсудим каждый компонент в этом разделе…

1. Модель классификации намерений

Представьте, что у вас есть чат-бот, который действительно может понять смысл наших слов. Модель Intent Classification является ключом к раскрытию этой возможности. Он использует передовые методы для точной интерпретации наших сообщений, делая ответы чат-бота более человечными и интуитивно понятными.

Для этого мы используем ALBERT для слоя встраивания слов, который помогает эффективно представлять значение слов. Кроме того, мы объединяем сверточные нейронные сети (CNN)иплотные слои для слоя классификатора. Эта мощная комбинация позволяет нашей модели фиксировать сложные шаблоны и отношения в тексте, повышая ее способность точно определять намерения. Рассмотрим подробнее архитектуру модели:

Вот реализация кода этой модели с использованием TensorFlow и Keras:

def build_smallBERT_CNN_classifier_model():
    text_input = tf.keras.layers.Input(shape=(), dtype=tf.string, name='text')
    preprocessing_layer = hub.KerasLayer(bert_preprocessor, name='preprocessing')
    encoder_inputs = preprocessing_layer(text_input)
    encoder = hub.KerasLayer(bert_encoder_model, trainable=True, name='BERT_encoder')
    outputs = encoder(encoder_inputs)
    net = sequence_output = outputs["sequence_output"]

    net = tf.keras.layers.Conv1D(32, 2, activation='relu')(net)
    net = tf.keras.layers.Conv1D(64, 2, activation='relu')(net)
    net = tf.keras.layers.MaxPooling1D(pool_size=2)(net)
    
    net = tf.keras.layers.GlobalMaxPool1D()(net)
    
    net = tf.keras.layers.Dense(512, activation="relu")(net)
    net = tf.keras.layers.Dropout(0.1)(net)
    
    net = tf.keras.layers.Dense(num_classes, activation="softmax", name='classifier')(net)
    
    return tf.keras.Model(text_input, net)

Построение и компиляция модели просты:

loss = tf.keras.losses.CategoricalCrossentropy(from_logits=False)
metrics = tf.metrics.CategoricalAccuracy()
epochs = 15
optimizer=tf.keras.optimizers.Adam(1e-5)

# build the model
classifier_smallBERT_model_cnn = build_smallBERT_CNN_classifier_model()

# compile the model
classifier_smallBERT_model_cnn.compile(optimizer=optimizer,
                         loss=loss,
                         metrics=metrics)

Необязательно: добавьте обратные вызовы:

class MyCallback(tf.keras.callbacks.Callback):
    def on_epoch_end(self, epoch, logs=None):
        if logs['val_categorical_accuracy'] >= 0.94:
            print("\nValidation accuracy reached 94%!")
            self.model.stop_training = True

Обучение модели:

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

callback = MyCallback()
history = classifier_smallBERT_model_cnn.fit(x=X_train, y=y_train_one_hot,
                                             validation_data=(X_val, y_val_one_hot),
                                             batch_size=32,
                                             epochs=epochs,
                                             callbacks=[callback])

Тестирование модели

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

intent_mapping = df.groupby('intent_encoding')['intent'].first().to_dict()

user_utterance = "what should i prepare before i go"
user_utterance = np.array([user_utterance])

# Make the prediction
predictions = loaded_model.predict(user_utterance)
predicted_intent_index = np.argmax(predictions)

# Map the predicted intent index to intent label and response
predicted_intent_label = intent_mapping[str(predicted_intent_index)]
predicted_response = df.loc[df['intent'] == predicted_intent_label, 'response'].iloc[0]

print("Predicted Intent:", predicted_intent_label)
print("VELA:", predicted_response)

Выход действительно хороший.

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

2. Распознавание именованных объектов (NER)

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

Мы используем модель SpaCy Custom NER, чтобы точно определить и классифицировать это.

Объекты, которые будут извлечены здесь:

  • Регион [REGION]
  • Настройки аттракционов [ATT_PREFERENCE]
  • Пищевые предпочтения [FOOD_PREFERENCE]
  • Предпочтительный отель [HOTEL_PREFERENCE]

Но как научить нашу модель не только запоминать примеры, но и развивать общее понимание невидимых данных? Давайте изучим процесс:

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

[('Where can I find International cuisine?', {'entities': [(17, 30, 'FOOD_PREFERENCE')]})]

Для этого мы используем функции offsetter и spacify_row:

def offsetter(lbl, doc, matchitem):
    one = len(str(doc[0:matchitem[1]]))
    subdoc = doc[matchitem[1]:matchitem[2]]
    two = one + len(str(subdoc))
    
    if one != 0:
        one += 1
        two += 1
    return (one, two, lbl)

def spacify_row(document, label, entity_keywords):
    matcher = PhraseMatcher(nlp.vocab)

    for i in entity_keywords:
        matcher.add(label, None, nlp(i))

    nlp_document = nlp(document)
    matches = matcher(nlp_document)
    
    entity_list = [offsetter(label, nlp_document, match) for match in matches]
    
    return (document, {'entities': entity_list})

Протестируйте функцию:

spacify_row('I love to eat seafood', 'FOOD_PREFERENCE', 
            entity_keywords = entity_phrases.get('FOOD_PREFERENCE'))

Выход:

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

att_result = [spacify_row(item, label='ATT_PREFERENCE', entity_keywords=entity_phrases.get('ATT_PREFERENCE')) for item in utterances]
attpref_train = [(i,j) for i,j in att_result if j['entities'] != []]

region_result = [spacify_row(item, label='REGION', entity_keywords=entity_phrases.get('REGION')) for item in utterances]
region_train = [(i,j) for i,j in region_result if j['entities'] != []]

food_result = [spacify_row(item, label='FOOD_PREFERENCE', entity_keywords=entity_phrases.get('FOOD_PREFERENCE')) for item in utterances]
food_train = [(i,j) for i,j in food_result if j['entities'] != []]

hotel_result = [spacify_row(item, label='HOTEL_PREFERENCES', entity_keywords=entity_phrases.get('HOTEL_PREFERENCES')) for item in utterances]
hotel_train = [(i,j) for i,j in hotel_result if j['entities'] != []]

combined_train = []
combined_train.extend(attpref_train)
combined_train.extend(region_train)
combined_train.extend(food_train)
combined_train.extend(hotel_train)

Обучите модель spaCy NER

Теперь пора приступить к тренировочному процессу:

  1. Инициализируйте файл конфигурации с помощью base_config.cfg.
  2. Выполните команду spacy train, указав выходной каталог и пути к наборам данных для обучения и разработки.

Но перед этим мы должны преобразовать наши данные в формат .spacy.

import pandas as pd
import os
from tqdm import tqdm
import spacy
from spacy.tokens import DocBin

def spacify_data(data):
    nlp = spacy.load("en_core_web_lg")
    db = DocBin()
    
    for text, annot in tqdm(data):
        doc = nlp.make_doc(text)
        ents = []
        existing_ents = []
        
        for start, end, label in annot["entities"]:
            span = doc.char_span(start, end, label=label, alignment_mode="contract")
            if span is None:
                print("Skipping entity")
            else:
                is_overlapping = any(
                    ent.start < span.end and ent.end > span.start
                    for ent in existing_ents
                )
                if not is_overlapping:
                    ents.append(span)
                    existing_ents.append(span)
        
        doc.ents = ents
        db.add(doc)
    
    return db
db = spacify_data(hotel_train_test)
db.to_disk("./hotel_test.spacy")

Обучение/Конфигурация модели

!python -m spacy init fill-config base_config.cfg config.cfg

!python -m spacy train config.cfg --output ./output --paths.train ./hotel_train.spacy --paths.dev ./hotel_test.spacy

Тестирование модели spaCy NER

Наконец, мы можем протестировать обученную модель spaCy NER, используя следующий код:

nlp1 = spacy.load(r"./output/model-best")
doc1 = nlp1("in sibetan, recommend me some art place and hotel with guest room and swimming pool and asian food or cafe in ubud")
spacy.displacy.render(doc1, style="ent", jupyter=True)

Убедитесь в силе NER, поскольку он точно идентифицирует и выделяет именованные объекты в тексте, позволяя вашему чат-боту давать индивидуальные рекомендации пользователям.

Внедряя распознавание именованных объектов (NER) в возможности нашего чат-бота, мы повышаем его способность понимать предпочтения пользователей и предоставлять персонализированный опыт.

Следующий шаг

Но подождите, это еще не все! Мы еще не закончили. Теперь, когда мы извлекли все объекты, пришло время перейти к следующему этапу: рекомендательная система. Оставайтесь с нами для нашей следующей статьи, где мы подробно рассмотрим эту захватывающую тему. Впереди еще много интересного, так что следите за обновлениями!

Спасибо!

Рекомендации