- vừa được xem lúc

[NLP] Cải thiện Elasticsearch trong bài toán semantic search sử dụng phương pháp Sentence Embeddings

0 0 684

Người đăng: Võ Văn Phúc

Theo Viblo Asia

Elasticsearch

Elasticsearch là gì ?

Elasticsearch là một công cụ tìm kiếm dựa trên phần mềm Lucene. Nó cung cấp một bộ máy tìm kiếm dạng phân tán, có đầy đủ công cụ với một giao diện web HTTP có hỗ trợ dữ liệu JSON. Elasticsearch được phát triển bằng Java và được phát hành dạng nguồn mở theo giấy phép Apache. Elasticsearch là một công cụ tìm kiếm phổ biến nhất, theo sau là Apache Solr, cũng dựa trên Lucene. (Theo wiki)

Hạn chế của Elasticsearch trong bài toán semantic search:

Do cơ chế đánh Inverted Index theo từng từ nên elasticsearch rất kém trong bài toán semantic search, vì với cách đánh index đó elasticsearch không thể hiểu hết được cả câu ( hay cả đoạn văn bản). Inverted Index elasticsearch Inverted Index elasticsearch

Sentence Embeddings:

Từ những hạn chế trên của elasticsearch việc chúng ta cần làm là tìm cách cho elasticsearch hiểu được toàn bộ câu.

Hiện nay với sự phát triển bùng nổ của các mô hình họ nhà transformers như Bert, RoBerta, GPT, .. thì việc hiểu ngôn ngữ tự nhiên trở nên đơn giản hơn. Trong bài này mình sẽ không đi vào phân tích từng mô hình này vì đã có rất nhiều bạn đã phân tích khá chi tiết.

Hiện nay có một số kỹ thuật sentence embedding phổ biến như InferSent, Universal Sentence Encoder, SBERT, SimCSE, ...

Trong bài viết mình sẽ hướng dẫn mọi người sử dụng mô hình SimeCSE_Vietnamese để cải thiện elasticsearch trong bài toán Semantic search.

SimeCSE_Vietnamese là pretrain model được mình training dựa trên kiến trúc SimCSE với encoding input mình sử dụng PhoBert mình đã tối lại một vài chỗ trong quá trình trainning để mô hình có thể hoạt động tốt nhất.

Mọi người có thể tham khảo chi tiết tại : https://github.com/vovanphuc/SimeCSE_Vietnamese

(Nếu mọi người có quan tâm đến bài toán thì mình sẽ tiếp tục viết 1 bài hướng dẫn tạo dữ liệu cũng như training cho mô hình SimCSE)

Áp dụng SimeCSE_Vietnamese vào Elasticsearch

Cài đặt Elasticsearch

Muốn sử dụng elastic search thì đầu tiên tất nhiên mọi người phải cài đặt elasticsearch rồi. :v Mọi người có thể vào trang chủ để cài đặt theo hướng dẫn. https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html

Dữ liệu sử dụng trong bài:

Trong bài ví dụ này mình sẽ sử dụng dữ liệu là 100k title của 100k bài báo mình đã crawl được.

Mọi người có thể tải tại đây !

Sử dụng SimCSE_Vietnamese:

Mình sẽ hướng dẫn các bạn sử dụng SimCSE_Vietnamese để embeddings các câu trước khi lưu vào elasticsearch.

Thư viện chúng ta sẽ sử dụng để load model SimCSE là sentence-transformers vì nó khá đơn giản và dễ dùng.

Đầu tiên chúng ta cài đặt thư viện sentence-transformers:

pip install -U sentence-transformers

Sau đó cùng load model thôi

from sentence_transformers import SentenceTransformer model_embedding = SentenceTransformer('VoVanPhuc/sup-SimCSE-VietNamese-phobert-base') def embed_text(batch_text): batch_embedding = model_embedding.encode(batch_text) return [vector.tolist() for vector in batch_embedding]

Quá trình tải model sẽ mất vài phút.

Sử dụng python để đánh index trong elasticsearch:

Mình sẽ đánh index các câu và các vector embedding sau khi chúng qua hàm embed_text đã được viết ở trên, mỗi lần mình sẽ đánh 1 batch cho nhanh.

Trước khi đánh index cho các câu mình sẽ sử dụng thêm thư viện pyvi để tokenize các câu.

from elasticsearch import Elasticsearch
from elasticsearch.helpers import bulk
from pyvi.ViTokenizer import tokenize
import pandas as pd index_name = "demo_simcse"
path_index = "config/index.json"
path_data = "data/data_title.csv"
batch_size = 128
client = Elasticsearch() def index_batch(docs): requests = [] titles = [tokenize(doc["title"]) for doc in docs] title_vectors = embed_text(titles) for i, doc in enumerate(docs): request = doc request["_op_type"] = "index" request["_index"] = index_name request["title_vector"] = title_vectors[i] requests.append(request) bulk(client, requests) print(f"Creating the {index_name} index.")
client.indices.delete(index=index_name, ignore=[404])
with open(path_index) as index_file: source = index_file.read().strip() client.indices.create(index=index_name, body=source) docs = []
count = 0
df = pd.read_csv(path_data).fillna(' ')
for index, row in df.iterrows(): count += 1 item = { 'id': row['id'], 'title': row['title'] } docs.append(item) if count % batch_size == 0: index_batch(docs) docs = [] print("Indexed {} documents.".format(count))
if docs: index_batch(docs) print("Indexed {} documents.".format(count)) client.indices.refresh(index=index_name)
print("Done indexing.") 

Query với embedding vector trong elasticsearch:

Elasticsearch có hỗ trợ sẵn một vài công thức để tính similarity giữa các vector như l1norm, l2norm, cosineSimilarity, dotProduct, .. Trong bài này chúng ta sẽ sử dụng cosineSimilarity.

Chúng ta chỉ cần cho câu muốn tìm kiếm qua hàm embed_text và sử dụng câu query sau:

{ "script_score": { "query": { "match_all": {} }, "script": { "source": "cosineSimilarity(params.query_vector, 'title_vector') + 1.0", "params": {"query_vector": query_vector} } }
}

Vậy là xong. !!!!!!!

Mình sử dụng thêm streamlit để demo cũng như so sánh kết quả khi search bằng elasticsearch bình thường (BM25) và cách search theo độ tương đồng giữa các vector embedding (SimCSE). Các bạn cùng xem kết quả nhé.!!!!

Đây là kết quả khi mình sử dụng elasticsearch bình thường.

Còn đây là kết quả khi mình sử dụng SimCSE_Vietnamese.

Như mọi người có thể thấy thì kết quả được cải thiện rất nhiều !!!!

Kết luận

Toàn bộ source mình để tại đây: https://github.com/vovanphuc/elastic_simCSE

Nếu mọi người có gặp vấn đề trong khi triển khai thì có thể để lại comment bên dưới. ! ( Đây là bài viết đầu tiên của mình nên còn hơi vụng về mong mọi người góp ý !! )

Tham khảo:

  1. https://github.com/VinAIResearch/PhoBERT
  2. https://github.com/princeton-nlp/SimCSE
  3. https://www.elastic.co/blog/text-similarity-search-with-vectors-in-elasticsearch

Bình luận

Bài viết tương tự

- vừa được xem lúc

Hành trình AI của một sinh viên tồi

Mình ngồi gõ những dòng này vào lúc 2h sáng (chính xác là 2h 2 phút), quả là một đêm khó ngủ. Có lẽ vì lúc chiều đã uống cốc nâu đá mà giờ mắt mình tỉnh như sáo, cũng có thể là vì những trăn trở về lý thuyết chồng chất ánh xạ mình đọc ban sáng khiến không tài nào chợp mắt được hoặc cũng có thể do mì

0 0 131

- vừa được xem lúc

[Deep Learning] Key Information Extraction from document using Graph Convolution Network - Bài toán trích rút thông tin từ hóa đơn với Graph Convolution Network

Các nội dung sẽ được đề cập trong bài blog lần này. . Tổng quan về GNN, GCN. Bài toán Key Information Extraction, trích rút thông tin trong văn bản từ ảnh.

0 0 198

- vừa được xem lúc

Tìm hiểu về YOLO trong bài toán real-time object detection

1.Yolo là gì. . Họ các mô hình RCNN ( Region-Based Convolutional Neural Networks) để giải quyết các bài toán về định vị và nhận diện vật thể.

0 0 269

- vừa được xem lúc

Encoding categorical features in Machine learning

Khi tiếp cận với một bài toán machine learning, khả năng cao là chúng ta sẽ phải đối mặt với dữ liệu dạng phân loại (categorical data). Khác với các dữ liệu dạng số, máy tính sẽ không thể hiểu và làm việc trực tiếp với categorical variable.

0 0 243

- vừa được xem lúc

TF Lite with Android Mobile

Như các bạn đã biết việc đưa ứng dụng đến với người sử dụng thực tế là một thành công lớn trong Machine Learning.Việc làm AI nó không chỉ dừng lại ở mức nghiên cứu, tìm ra giải pháp, chứng minh một giải pháp mới,... mà quan trọng là đưa được những nghiên cứu đó vào ứng dụng thực tế, được sử dụng để

0 0 54

- vừa được xem lúc

Xây dựng hệ thống Real-time Multi-person Tracking với YOLOv3 và DeepSORT

Trong bài này chúng ta sẽ xây dựng một hệ thống sử dụng YOLOv3 kết hợp với DeepSORT để tracking được các đối tượng trên camera, YOLO là một thuật toán deep learning ra đời vào tháng 5 năm 2016 và nó nhanh chóng trở nên phổ biến vì nó quá nhanh so với thuật toán deep learning trước đó, sử dụng YOLO t

0 0 302