Перекомпилируйте ElasticSearch для обработки поиска изображений и семантического сопоставления текста.

NLP Идентификация изображения

написать впереди

ElasticSearch7 начал добавлять два типа данных, Dense Vector и Sparse Vector, которые считаютсяпоиск изображенийа такжеСемантическое сопоставление текстаподдерживается.

Но я обнаружил, что его размер в документе (версия elasticsearch 7.5) очень низкий и может поддерживать только до 1024 размеров. Хотя это измерение подходит для общего текстового семантического сопоставления, его далеко недостаточно для поиска изображений.

Глядя на размеры признаков изображения, в настоящее время обучаемых нейронной сетью, я нахожу здесь случай распознавания лиц:keras-vggface

В его исходном коде представлены три модели: VGG16, RESNET50 и SENET50.

Можно видеть, что размерность вектора признаков, выводимого моделью VGG16, составляет 2622 измерения, что намного превышает 1024.

Выходное измерение моделей RESNET50 и SENET50 составляет 8631, что намного больше, чем 1024 измерения.

Цель этой статьи — увеличить размерность плотного вектора Я погуглил решение и обнаружил, что брат уже задавал этот вопрос:Increase Elasticsearch maximum dimensions for sparse vectors

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

Изменить исходный код

Глядя на файл конфигурации, вы можете видеть, что ES уже однажды увеличила самое большое измерение с 500 до 1024.

Скачать с гитхаба здесьes7.5.1После исходного кода найдите его командой grepDenseVectorFieldMapperэтот класс.

Здесь я впервые скачал исходный код ветки master и обнаружил, что максимальная размерность на самом деле 2048.

Поиск PR ES показал, что он действительно был добавлен снова.

Не всегда кажется, что этого достаточно.

Открой тему и увидишь, что этот парень сказал, что 1024 мало.Ну, 2048 на самом деле мало.На этот раз я поменяю его на 4096 для вас.

Просто изменить число в исходном коде здесь нечего сказать.

Скомпилируйте исходный код

Затем скомпилируйте исходный код, пользователи Linux или Mac могут войти в каталог elasticsearch и выполнить следующую команду.

./gradlew assemble

Если это окна, используйте этот gradlew.bat.

gradlew.bat assemble

Поработав некоторое время, я обнаружил, что было сообщено об ошибке, и было обнаружено, что требуется JDK11 или выше.

Но после моей компиляции я обнаружил, что 11 версия не годится, она должна быть 12, да и JDK13 тоже не годится. А на официальном сайте оракла нету jdk12, тогда переходи на следующийopenjdk-12Хорошо.

После завершения установки перекомпилировать.При компиляции обнаруживается, что здесь также скомпилирована версия docker.Это на самом деле не нужно, и даже если docker установлен, то версия неверная, а указанная версия должна быть установлена. Здесь вы не можете скомпилировать докер, добавив комментарии к вещам, связанным с gradle, в settings.gradle.

Наконец он скомпилирован, в документе написано, что скомпилированный файл находится вbuild/distributionДалее я обнаружил, что такого вообще нет.После долгих поисков скомпилированный вывод находится вdistribution\archivesПод содержанием

В основном установочный пакет для Mac, Linux и Windows. Здесь я загружаю скомпилированный результат в облако Baidu.

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

Ссылка на сайт:disk.baidu.com/is/1K CTS UCL5…Код извлечения: 4l0i

контрольная работа

Затем проверьте, достигает ли плотный вектор 4096 измерений. Здесь я использую python3 для тестирования.

Запустить службу ЕС

Здесь сначала запустите службу ES и запустите каталог bin в соответствии с разными версиями.elasticsearchфайл.

Я окна здесь, дважды щелкните напрямуюelasticsearch.batВот и все.

Вы можете видеть, что es уже работает на порту 9200.

Установить библиотеку

Затем установите библиотеку python, которую можно установить с помощью pip здесь.

pip3 install elasticsearch==7.1.0

создать индекс

Затем создайте плотный индекс.Здесь мы используем векторное измерение из 4000 измерений, а затем случайным образом генерируем 10 000 векторов и строим индексы.

from elasticsearch import Elasticsearch
import random


def get_num():
    return random.randrange(0, 1000) / 100


es = Elasticsearch()
index_mappings = {
  "mappings": {
      "properties": {
        "my_vector":    {
            "type": "dense_vector",
            "dims": 4000,
        },
      }
    },
}

if es.indices.exists(index='test_index') is not True:
    print("create test_index")
    es.indices.create(index='test_index', body=index_mappings)

for i in range(10000):
    data = {
        "id": i,
        "my_vector": [get_num() for k in range(4000)],
    }
    print(data)
    res = es.index(index="test_index", id=i, body=data)
    print(res)

Побегав, я обнаружил, что скорость неплохая, очень быстрая.

поисковый тест

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

from elasticsearch import Elasticsearch
import random

query_vector = [random.randrange(0, 1000) / 100 for i in range(4000)]
script_query = {
    "script_score": {
        "query": {"match_all": {}},
        "script": {
            "source": "cosineSimilarity(params.query_vector, doc['my_vector']) + 1.0",
            "params": {"query_vector": query_vector}
        }
    }
}
es = Elasticsearch()
searched = es.search("test_index", body={
    "size": 100,
    "query": script_query,
}, timeout=None)

for hit in searched["hits"]["hits"]:
    print(hit["_id"], hit["_score"])

После запуска обнаруживается, что скорость очень высокая, в основном она исчисляется секундами.

Анализ исходного кода части поиска ИНС

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

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

Поскольку я никогда раньше не видел исходный код ElasticSearch, мне потребовалось много времени, чтобы найти различные PR и проблемы, и я нашел коммит для отправки этой новой функции:GitHub.com/эластик/голодный…

Вот читаю давно, там очень критичное замечание следующего содержания:

Этот блок говорит о том, что каждый плотный вектор кодируется как двоичное значение документа, а затем занимает в 4 раза больше размера измерения. Затем снова посмотрите на код:

Проверьте эту логику

На самом деле здесь нужно закодировать значение в четыре значения, а затем инвертировать индекс.

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

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

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

Тем не менее, после поиска google все еще есть некоторые плагины, которые реализовали некоторые функции поиска ANN на ES.

Попытка поиска изображения

Эвристический метод не обязательно плох, потому что приведенный выше алгоритм действительно можно рассматривать как приближение, и он очень быстр. Здесь я попробую приложение предыдущего поиска давки:GitHub.com/yourado/MM FI…

Здесь я воссоздал ветку какelasticsearch(Код ниже весь в нем):

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

Давайте снова протестируем веб-сторону, которая точно такая же, как и в предыдущей статье.

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

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

О семантическом сопоставлении текста

Для семантического сопоставления текста здесь не так много введения.Подобно поиску изображений, генерируется плотный вектор.Разница в том, что одно изображение, а другое текст. Существует множество решений для обработки естественного языка, таких как традиционные LDA, SVD, Word2Vec с использованием нейронных сетей, Doc2Vec и последняя версия Bert.

Что касается Берта, я видел здесь проект с открытым исходным кодом:GitHub.com/Hi RonThree/Не голоден…, его можно считать самым передовым методом в настоящее время, и вы можете взглянуть на него, если вам интересно.