[Data Mining, Natural Language Processing] Как сделать поиск по файлоболотам в 104 строки кода на python
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Продолжая тематику коротких полезных скриптов, хотелось бы познакомить читателей с возможностью построения поиска по контенту файлов и изображений в 104 строки. Это конечно не будет умопомрачительным по качеству решением — но вполне годным для простых нужд. Также в статье не будет ничего изобретаться — все пакеты open source.
И да — пустые строки в коде тоже считаются. Небольшая демонстрация работы приведена в конце статьи.
Нам понадобится python3, скачанный Tesseract пятой версии, и модель distiluse-base-multilingual-cased из пакета Sentence-Transformers. Кому уже понятно что дальше будет происходить — интересно не будет :)
А тем временем, всё что нам понадобится, будет выглядеть как
Первые 18 строк
SPL
import numpy as np
import os, sys, glob
os.environ['PATH'] += os.pathsep + os.path.join(os.getcwd(), 'Tesseract-OCR')
extensions = [
'.xlsx', '.docx', '.pptx',
'.pdf', '.txt', '.md', '.htm', 'html',
'.jpg', '.jpeg', '.png', '.gif'
]
import warnings; warnings.filterwarnings('ignore')
import torch, textract, pdfplumber
from cleantext import clean
from razdel import sentenize
from sklearn.neighbors import NearestNeighbors
from sentence_transformers import SentenceTransformer
embedder = SentenceTransformer('./distillUSE')
Понадобится как видим, прилично, и вроде всё готовое, но и без напильника не обойтись. В частности, textract (не от Amazon который платный), как-то плохо работает с русскими pdf, как выход использовать можно pdfplumber. Далее, разбиение текста на предложения — сложная задача, и с русским языком в её случае отлично справляется razdel.
Кто не слышал про scikit-learn — тому я завидую вкратце, алгоритм NearestNeighbors в нём запоминает вектора и выдает ближайшие. Вместо scikit-learn можно использовать faiss или annoy или например даже elasticsearch.
Главное на самом деле превратить текст (любого) файла в вектор, что и делают
следующие 36 строк кода
SPL
def processor(path, embedder):
try:
if path.lower().endswith('.pdf'):
with pdfplumber.open(path) as pfd:
if len(pdf.pages):
text = ' '.join([
page.extract_text() or '' for page in pdf.pages if page
])
elif path.lower().endswith('.md') or path.lower().endswith('.txt'):
with open(path, 'r', encoding='UTF-8') as fd:
text = fd.read()
else:
text = textract.process(path, language='rus+eng').decode('UTF-8')
if path.lower()[-4:] in ['.jpg', 'jpeg', '.gif', '.png']:
text = clean(
text,
fix_unicode=False, lang='ru', to_ascii=False, lower=False,
no_line_breaks=True
)
else:
text = clean(
text,
lang='ru', to_ascii=False, lower=False, no_line_breaks=True
)
sentences = list(map(lambda substring: substring.text, sentenize(text)))
except Exception as exception:
return None
if not len(sentences):
return None
return {
'filepath': [path] * len(sentences),
'sentences': sentences,
'vectors': [vector.astype(float).tolist() for vector in embedder.encode(
sentences
)]
}
Ну а далее остаётся дело техники — обойти все файлы, извлечь вектора и найти ближайший к запросу по косинусному расстоянию.
Оставшийся код
SPL
def indexer(files, embedder):
for file in files:
processed = processor(file, embedder)
if processed is not None:
yield processed
def counter(path):
if not os.path.exists(path):
return None
for file in glob.iglob(path + '/**', recursive=True):
extension = os.path.splitext(file)[1].lower()
if extension in extensions:
yield file
def search(engine, text, sentences, files):
indices = engine.kneighbors(
embedder.encode([text])[0].astype(float).reshape(1, -1),
return_distance=True
)
distance = indices[0][0][0]
position = indices[1][0][0]
print(
'Релевантность "%.3f' % (1 - distance / 2),
'Фраза: "%s", файл "%s"' % (sentences[position], files[position])
)
print('Поиск файлов "%s"' % sys.argv[1])
paths = list(counter(sys.argv[1]))
print('Индексация "%s"' % sys.argv[1])
db = list(indexer(paths, embedder))
sentences, files, vectors = [], [], []
for item in db:
sentences += item['sentences']
files += item['filepath']
vectors += item['vectors']
engine = NearestNeighbors(n_neighbors=1, metric='cosine').fit(
np.array(vectors).reshape(len(vectors), -1)
)
query = input('Что искать: ')
while query:
search(engine, query, sentences, files)
query = input('Что искать: ')
Запускать весь код можно так:
python3 app.py /path/to/your/files/
Вот как бы и всё с кодом.
А вот обещанная демонстрация.
Взял две новости с «лента.ру», и положил одну в gif-файл через небезызвестный paint, а вторую просто в текстовый.
Первый файл.gif
SPL
Второй файл.txt
SPL
Специалисты МЧС дали россиянам рекомендации, как снизить риск попадания в ДТП. Об этом сообщает РИА Новости.
Как отметили в ведомстве, большинство аварий происходит из-за беспечности и неправильного поведения на дороге. Поэтому, двигаясь по трассе, необходимо соблюдать предельную внимательность и использовать периферийное зрение, то есть смотреть в одну точку. Это позволяет видеть больше объектов по бокам. Важно внимательно следить за едущими рядом и сзади автомобилями, их скоростью.
Кроме того, необходимо всегда пристегиваться ремнями безопасности, а в дороге не есть и не пить, поскольку это отвлекает от дороги и может привести к аварии. Также следует не использовать лишний раз звуковой сигнал. Важно не провоцировать других водителей к агрессивному вождению.
В МЧС добавили, что чаще всего аварии происходят из-за управления автомобилем в нетрезвом виде и из-за превышения скорости.
Ранее доктор Александр Мясников, главврач ГКБ №71 имени Жадкевича в Москве, назвал людей, которые пользуются мобильными телефонами за рулем, преступниками и сравнил их с пьяными водителями. Он предложил штрафовать таких водителей на 10 тысяч рублей после того, как пользование мобильным телефоном зафиксировали камеры видеонаблюдения. За повторное нарушение — лишение прав.
А вот gif-анимация, как это работает. С GPU конечно всё работает бодрее.
Демонстрация, лучше кликнуть на картинку
SPL
Спасибо за ознакомление! Надеюсь всё же что этот метод кому-нибудь да будет полезен.
===========
Источник:
habr.com
===========
Похожие новости:
- [Data Mining, Big Data, Natural Language Processing] Парсим Википедию, фильтруя, для задач NLP в 44 строки кода
- [Data Mining, Анализ и проектирование систем, Машинное обучение] О котах и Process Mining
- [Big Data, Data Mining, Визуализация данных, Открытые данные] Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1
- [Машинное обучение, Программирование] Нейронки «с нуля», или Как мы делали помощника для наших диспетчеров техподдержки
- [Big Data, Data Mining, Информационная безопасность, Сотовая связь] «Вымпелком» выполнит дата-майнинг своих абонентов по заказу любого клиента
- [Big Data, Natural Language Processing, Искусственный интеллект, Машинное обучение] Наш опыт работы с DeepPavlov: голосовой помощник за 20 дней и приём 5000 звонков на горячей линии
- [Data Engineering, Data Mining, Matlab, Алгоритмы, Математика] Симуляционное моделирование механической системы средствами визуального программирования Scilab\Xcos
- [Data Mining, Машинное обучение, Исследования и прогнозы в IT] Портрет российского специалиста Data Science от MADE и hh.ru
- [Natural Language Processing, Искусственный интеллект, Машинное обучение] Искусственный интеллект в области юриспруденции. Статья 2
- [Data Mining, Python, Математика, Научно-популярное] Цепи Маркова и Пайтон — разбираемся в теории и собираем генератор текстов
Теги для поиска: #_data_mining, #_natural_language_processing, #_ktoto_chitaet_tegi__no_zachem (кто-то читает теги - но зачем), #_ktoto_chitaet_tegi (кто-то читает теги), #_data_mining, #_natural_language_processing
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 23-Ноя 02:35
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Продолжая тематику коротких полезных скриптов, хотелось бы познакомить читателей с возможностью построения поиска по контенту файлов и изображений в 104 строки. Это конечно не будет умопомрачительным по качеству решением — но вполне годным для простых нужд. Также в статье не будет ничего изобретаться — все пакеты open source. И да — пустые строки в коде тоже считаются. Небольшая демонстрация работы приведена в конце статьи. Нам понадобится python3, скачанный Tesseract пятой версии, и модель distiluse-base-multilingual-cased из пакета Sentence-Transformers. Кому уже понятно что дальше будет происходить — интересно не будет :) А тем временем, всё что нам понадобится, будет выглядеть как Первые 18 строкSPLimport numpy as np
import os, sys, glob os.environ['PATH'] += os.pathsep + os.path.join(os.getcwd(), 'Tesseract-OCR') extensions = [ '.xlsx', '.docx', '.pptx', '.pdf', '.txt', '.md', '.htm', 'html', '.jpg', '.jpeg', '.png', '.gif' ] import warnings; warnings.filterwarnings('ignore') import torch, textract, pdfplumber from cleantext import clean from razdel import sentenize from sklearn.neighbors import NearestNeighbors from sentence_transformers import SentenceTransformer embedder = SentenceTransformer('./distillUSE') Понадобится как видим, прилично, и вроде всё готовое, но и без напильника не обойтись. В частности, textract (не от Amazon который платный), как-то плохо работает с русскими pdf, как выход использовать можно pdfplumber. Далее, разбиение текста на предложения — сложная задача, и с русским языком в её случае отлично справляется razdel. Кто не слышал про scikit-learn — тому я завидую вкратце, алгоритм NearestNeighbors в нём запоминает вектора и выдает ближайшие. Вместо scikit-learn можно использовать faiss или annoy или например даже elasticsearch. Главное на самом деле превратить текст (любого) файла в вектор, что и делают следующие 36 строк кодаSPLdef processor(path, embedder):
try: if path.lower().endswith('.pdf'): with pdfplumber.open(path) as pfd: if len(pdf.pages): text = ' '.join([ page.extract_text() or '' for page in pdf.pages if page ]) elif path.lower().endswith('.md') or path.lower().endswith('.txt'): with open(path, 'r', encoding='UTF-8') as fd: text = fd.read() else: text = textract.process(path, language='rus+eng').decode('UTF-8') if path.lower()[-4:] in ['.jpg', 'jpeg', '.gif', '.png']: text = clean( text, fix_unicode=False, lang='ru', to_ascii=False, lower=False, no_line_breaks=True ) else: text = clean( text, lang='ru', to_ascii=False, lower=False, no_line_breaks=True ) sentences = list(map(lambda substring: substring.text, sentenize(text))) except Exception as exception: return None if not len(sentences): return None return { 'filepath': [path] * len(sentences), 'sentences': sentences, 'vectors': [vector.astype(float).tolist() for vector in embedder.encode( sentences )] } Ну а далее остаётся дело техники — обойти все файлы, извлечь вектора и найти ближайший к запросу по косинусному расстоянию. Оставшийся кодSPLdef indexer(files, embedder):
for file in files: processed = processor(file, embedder) if processed is not None: yield processed def counter(path): if not os.path.exists(path): return None for file in glob.iglob(path + '/**', recursive=True): extension = os.path.splitext(file)[1].lower() if extension in extensions: yield file def search(engine, text, sentences, files): indices = engine.kneighbors( embedder.encode([text])[0].astype(float).reshape(1, -1), return_distance=True ) distance = indices[0][0][0] position = indices[1][0][0] print( 'Релевантность "%.3f' % (1 - distance / 2), 'Фраза: "%s", файл "%s"' % (sentences[position], files[position]) ) print('Поиск файлов "%s"' % sys.argv[1]) paths = list(counter(sys.argv[1])) print('Индексация "%s"' % sys.argv[1]) db = list(indexer(paths, embedder)) sentences, files, vectors = [], [], [] for item in db: sentences += item['sentences'] files += item['filepath'] vectors += item['vectors'] engine = NearestNeighbors(n_neighbors=1, metric='cosine').fit( np.array(vectors).reshape(len(vectors), -1) ) query = input('Что искать: ') while query: search(engine, query, sentences, files) query = input('Что искать: ') Запускать весь код можно так: python3 app.py /path/to/your/files/
Вот как бы и всё с кодом. А вот обещанная демонстрация. Взял две новости с «лента.ру», и положил одну в gif-файл через небезызвестный paint, а вторую просто в текстовый. Первый файл.gifSPLВторой файл.txtSPLСпециалисты МЧС дали россиянам рекомендации, как снизить риск попадания в ДТП. Об этом сообщает РИА Новости.
Как отметили в ведомстве, большинство аварий происходит из-за беспечности и неправильного поведения на дороге. Поэтому, двигаясь по трассе, необходимо соблюдать предельную внимательность и использовать периферийное зрение, то есть смотреть в одну точку. Это позволяет видеть больше объектов по бокам. Важно внимательно следить за едущими рядом и сзади автомобилями, их скоростью. Кроме того, необходимо всегда пристегиваться ремнями безопасности, а в дороге не есть и не пить, поскольку это отвлекает от дороги и может привести к аварии. Также следует не использовать лишний раз звуковой сигнал. Важно не провоцировать других водителей к агрессивному вождению. В МЧС добавили, что чаще всего аварии происходят из-за управления автомобилем в нетрезвом виде и из-за превышения скорости. Ранее доктор Александр Мясников, главврач ГКБ №71 имени Жадкевича в Москве, назвал людей, которые пользуются мобильными телефонами за рулем, преступниками и сравнил их с пьяными водителями. Он предложил штрафовать таких водителей на 10 тысяч рублей после того, как пользование мобильным телефоном зафиксировали камеры видеонаблюдения. За повторное нарушение — лишение прав. А вот gif-анимация, как это работает. С GPU конечно всё работает бодрее. Демонстрация, лучше кликнуть на картинкуSPLСпасибо за ознакомление! Надеюсь всё же что этот метод кому-нибудь да будет полезен. =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 23-Ноя 02:35
Часовой пояс: UTC + 5