Алгоритм ближайшего соответствия для строк / предложений не работает?


Я написал программу, которая принимает вопрос от пользователя. Затем он сопоставляет этот вопрос со списком предопределенных вопросов и возвращает ответ. Он должен быть точным и совпадать только с вопросами, которые близки к (нечеткие совпадения) или точно то, что ввел пользователь.

Мой SSSCE:

Http://ideone.com/JTcF73

Код:

#include <iostream>
#include <cstdint>
#include <algorithm>
#include <numeric>
#include <functional>

int min_index(const std::vector<int>& list)
{
    int index = 0;
    int smallest = list[0];

    for (size_t i = 0; i < list.size(); ++i) {
        if (list[i] < smallest) {
            smallest = list[i];
            index = i;
        }
    }
    return index;
}

std::uint32_t LevenshteinDistance(const std::string &First, const std::string &Second)
{
    const std::size_t FirstLength = First.size();
    const std::size_t SecondLength = Second.size();

    std::vector<std::uint32_t> Current(SecondLength + 1);
    std::vector<std::uint32_t> Previous(SecondLength + 1);

    std::size_t I = 0;
    std::generate(Previous.begin(), Previous.end(), [&] {return I++; });

    for (I = 0; I < FirstLength; ++I)
    {
        Current[0] = I + 1;

        for (std::size_t J = 0; J < SecondLength; ++J)
        {
            auto Cost = First[I] == Second[J] ? 0 : 1;
            Current[J + 1] = std::min(std::min(Current[J] + 1, Previous[J + 1] + 1), Previous[J] + Cost);
        }

        Current.swap(Previous);
    }
    return Previous[SecondLength];
}

std::vector<std::string> questions = 
{
    "What is the most popular program at GBC?",
    "How much is the tuition at GBC?",
    "Do I have to pay my fees before I can register?",
    "What are my fee payment options?",
    "How do I know when I'm allowed to register?",
    "How do I add and/or drop courses from my timetable?",
    "What do I do if I can't find my PASSWORD?",
    "How do I withdraw from a program?",
    "What are the college policies?",
    "How much math do I need to know?",
    "What is the program code for computer programming?",
    "What is stu-view?",
    "What is the college best known for?",
    "How easy is it to find work after program completion?",
    "What if I plan to continue my education after?"
};

std::vector<std::string> answers =
{
    "Fashion",
    "3000 a semester",
    "Yes you have to pay the fees before registering",
    "You may pay online on your student account through the student portal",
    "You may register two weeks or more before the start of the program",
    "You may drop courses from online through the student portal",
    "You can call ... and an agent will assist you",
    "You may withdraw using the student portal online",
    "They are located at the following link...",
    "It depends on the program you are entering",
    "T127 is the code for computer science",
    "Stu-View is a student portal to manage student account and view marks.",
    "The cafeteria food",
    "Depends on the field of work and timing",
    "You may do so within three years after program completion"
};

int main()
{
    std::string user_question = "program";

    std::vector<int> distances = std::vector<int>(questions.size(), 0);

    for (size_t I = 0; I < questions.size(); ++I)
    {
        int dist = LevenshteinDistance(user_question, questions[I]);
        distances[I] = dist;
    }

    std::cout<<"Distance:      "<<distances[min_index(distances)]<<"n";
    std::cout<<"User-Question: "<<user_question<<"n";
    std::cout<<"Question-Key:  "<<questions[min_index(distances)]<<"n";
    std::cout<<"Answer-Value:  "<<answers[min_index(distances)]<<"n";

    return 0;
}
Таким образом, в приведенном выше примере пользователь вводит "program".. Предполагается найти наиболее близкое совпадение из списка вопросов и верните соответствующий ответ..

Однако он печатает:

Distance:      17
User-Question: program
Question-Key:  What is stu-view?
Answer-Value:  Stu-View is a student portal to manage student account and view marks.

Он должен был бы иметь намного лучшие результаты или точность, но его, кажется, не волнует, есть ли в предложении ключевые слова, введенные пользователем :S он работает для небольших случаев, но для большой базы данных или выше, где есть более 5 предложений, он имеет трудное время.. Особенно с небольшими ключевыми словами; l

Что я делаю не так? Есть идеи, как я могу исправить это и сделать его более точным? Я попробовал HammingDistance, такой же результат..

1 3

1 ответ:

И "program", и "What is stu-view?" довольно короткие по сравнению с другими строками. Легче преобразовать "program" в "What is stu-view?", чем преобразовать "program" в "What is the most popular program at GBC?", несмотря на то, что слово "program" является общим.

Что я делаю не так?

Я не думаю, что ты делаешь что-то неправильно. Если вы не удовлетворены результатом, это означает, что ваш текущий формализм (минимизация расстояния Левенштейна) не тот, который вы хотите.

Вы можете перейти к более локальным решениям: например Маркируя строки, вычислите попарно Левенштейновское расстояние между словами, затем объедините результаты (среднее, sup inf...)

Лучшие решения потребовали бы выполнения некоторой библиографии (вероятно, тема бесконтрольного машинного обучения)