АВТОРЫ: НИЛП ПАТЕЛЬ, Шри Патель, Друванш Праджапати, Самарт Пури

ОБЗОР

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

Первый подход предполагает использование TfidfVectorizer для создания сводки. Этот подход включает в себя создание векторного представления каждого предложения в тексте, а затем ранжирование предложений на основе их релевантности. Чтобы реализовать этот подход, нам сначала нужно импортировать необходимые библиотеки и создать функцию суммирования, которая принимает фрагмент текста и возвращает сводку. Функция начинается с токенизации текста с помощью spacy, а затем создания объекта TfidfVectorizer. Затем TfidfVectorizer помещается в список предложений и используется для преобразования предложений в векторы. Затем векторы суммируются, и в качестве сводки выбираются первые N предложений, где N — количество предложений, которые мы хотим получить в сводке.

Второй подход включает использование косинусного расстояния nltk для создания сводки. Этот подход включает в себя измерение сходства между предложениями и выбор наиболее похожих предложений в качестве резюме. Чтобы реализовать этот подход, нам сначала нужно импортировать необходимые библиотеки и создать функцию generate_summary, которая принимает имя файла и возвращает сводку. Функция начинается с чтения файла и разметки предложений с использованием стоп-слов nltk. Затем создается матрица сходства путем сравнения каждого предложения с каждым другим предложением в тексте. Затем матрица преобразуется в график с помощью networkx, а алгоритм PageRank используется для ранжирования предложений в зависимости от их важности. Затем в качестве сводки выбираются лучшие N предложений.

Третий подход предполагает использование предварительно обученной языковой модели, такой как T5, для создания сводки. Модель T5 была обучена на большом наборе текстовых данных и способна генерировать человекоподобные сводки, предсказывая следующее слово в последовательности. Чтобы использовать этот подход, нам сначала нужно установить необходимые библиотеки и загрузить данные. Затем мы можем создать NewsSummaryDataset и NewsSummaryDataModule для обработки и загрузки данных. Далее мы можем определить нашу модель, создав модель T5ForConditionalGeneration и указав гиперпараметры. Наконец, мы можем обучить модель, определив оптимизатор AdamW и обратный вызов ModelCheckpoint для сохранения весов модели в каждую эпоху.

НАБОР ДАННЫХ

В этом проекте мы использовали только один набор данных и использовали его при обучении заголовка, а также модели сводки 3.



РЕЗЮМЕ НОВОСТЕЙ
Создание кратких описаний новостных статей.www.kaggle.com



МОДЕЛИ

› ГЛАВНАЯ МОДЕЛЬ

код модели поезда присутствует по данной ссылке:



код начинается с импорта необходимых библиотек и считывания данных из CSV-файла с помощью pandas. Данные состоят из заголовков и текста для каждой новостной статьи. Затем данные предварительно обрабатываются, чтобы иметь правильный формат для обучения модели T5, которая ожидает фрейм данных со столбцами "source_text" и " target_text”. Исходный текст — это текст, который необходимо обобщить, а целевой текст — это резюме.

Затем данные разделяются на обучающий набор и тестовый набор с помощью функции train_test_split из sci-kit-learn. Класс SimpleT5 импортируется из библиотеки simplet5, а модель T5 создается с помощью метода from_pretrained. Затем модель обучается на тренировочном наборе с использованием метода обучения. Параметр eval_df указывает набор тестов, который будет использоваться для оценки во время обучения. Параметры source_max_token_len и target_max_token_len указывают максимальную длину исходного текста и целевого текста соответственно. Параметр batch_size указывает количество выборок на одно обновление градиента, а параметр max_epochs указывает максимальное количество эпох для поезд для. Параметр use_gpu указывает, использовать ли графический процессор для обучения.

› ОБЗОР 3 МОДЕЛЬ

код модели поезда присутствует по данной ссылке:



В этом блоке кода мы устанавливаем несколько библиотек, которые необходимы для нашей задачи суммирования текста с использованием модели T5. Эти библиотеки включают transformers, pytorch-lightning, torchtext и torchvision.

Затем мы импортируем эти библиотеки, а также некоторые дополнительные библиотеки, такие как pandas, numpy и pyplot. Мы также установили некоторые настройки визуализации, используя seaborn и matplotlib.

Затем мы читаем файл CSV, содержащий текстовые данные, и создаем кадр данных pandas с текстовыми и сводными столбцами. Затем мы разделяем данные на обучающие и тестовые наборы с помощью train_test_split.

Мы определяем класс NewsSummaryDataset, который принимает фрейм данных и объект T5Tokenizer, а также некоторые необязательные параметры для максимальной длины токена. Этот класс позволяет нам получить доступ к данным в фрейме данных как к объекту набора данных, что будет полезно для обучения и оценки нашей модели.

Мы также определяем класс NewsSummaryDataModule, который наследуется от класса pytorch_lightning LightningDataModule. Этот класс отвечает за создание загрузчиков данных для наших обучающих и тестовых наборов данных, а также за указание некоторых необязательных гиперпараметров, таких как размер пакета и текст, а также суммарная максимальная длина токена.

Наконец, мы определяем класс NewsSummaryModel, который наследуется от класса LightningModule pytorch_lightning. Этот класс содержит логику для обучения и оценки нашей модели, а также для создания сводок из входного текста. Он содержит несколько ключевых методов, таких как configure_optimizers, training_step, validation_step. и test_step.

Определив эти классы и функции, мы теперь можем использовать NewsSummaryModel для обучения и оценки модели суммирования текста с использованием модели T5.

ИЗВЛЕКАТЕЛЬНОЕ РЕЗЮМЕ

› ОБЗОР 1

from sklearn.feature_extraction.text import TfidfVectorizer
from spacy.lang.en import English
import numpy as np

nlp = English()
nlp.add_pipe('sentencizer')



def summarizer(text, tokenizer=nlp, max_sent_in_summary=3):
    
    doc = nlp(text.replace("\n", ""))
    sentences = [sent.text.strip() for sent in doc.sents]
    
    sentence_organizer = {k:v for v,k in enumerate(sentences)}
    
    vectorizer = TfidfVectorizer(min_df=2,  max_features=None, 
                                        strip_accents='unicode', 
                                        analyzer='word',
                                        token_pattern=r'\w{1,}',
                                        ngram_range=(1, 3), 
                                        use_idf=1,smooth_idf=1,
                                        sublinear_tf=1,
                                        stop_words = 'english')
    
    vectorizer.fit(sentences)
    vectors = vectorizer.transform(sentences)
    scores = np.array(vectors.sum(axis=1)).ravel()
    N = max_sent_in_summary
    top_n_sentences = [sentences[ind] for ind in np.argsort(scores, axis=0)[::-1][:N]]
    
    top_n = [(sentence,sentence_organizer[sentence]) for sentence in top_n_sentences]
   
    top_n = sorted(top_n, key = lambda x: x[1])
    ordered_scored_sentences = [element[0] for element in top_n]
   
    summary = " ".join(ordered_scored_sentences)
    return summary

функция TfidfVectorizer из библиотеки scikit-learn импортируется и используется для векторизации списка предложений. TfidfVectorizer преобразует список предложений в матрицу числовых значений, представляющих важность каждого слова в каждом предложении.

Объект nlp из английского модуля библиотеки spaCy также импортируется и используется для добавления канала Sentencizer к объекту nlp. Sentencizer используется для разделения текста на отдельные предложения.

Функция суммирования принимает фрагмент текста и токенизатор, которым в данном случае является объект nlp с добавленным каналом Sentencizer. Функция также принимает параметр максимального количества предложений, которые должны быть включены в сводку.

Сначала текст проходит через объект nlp, чтобы разделить его на отдельные предложения, которые затем сохраняются в переменной sentences. Затем создается словарь sentence_organizer, который сопоставляет каждое предложение с соответствующим индексом в исходном списке предложений.

Затем TfidfVectorizer подгоняется к списку предложений и используется для преобразования предложений в векторы. Сумма каждого вектора вычисляется и сохраняется в переменной scores. Затем выбираются первые N предложений с наивысшими оценками и сохраняются в списке top_n_sentences.

Затем создается список top_n, который представляет собой список кортежей, содержащих каждое из первых N предложений и соответствующий ему индекс в исходном списке предложений. Затем список «top_n» сортируется на основе индексов предложений. Окончательное резюме создается путем объединения отсортированного списка предложений и возвращается в качестве вывода.

› ОБЗОР 2

import nltk    #Natural Language ToolKit 
nltk.download('stopwords')
from nltk.corpus import stopwords
from nltk.cluster.util import cosine_distance
import numpy as np
import networkx as nx

def read_article(file_name):
    with open(file_name) as f:
        a = " ".join(line.strip() for line in f)
    with open(file_name,"r+") as f:
        f.truncate(0)
        f.write(a)
    file = open(file_name,"r")
    filedata = file.readlines()
    #print(filedata)
    article = filedata[0].split(". ")
    sentances=[]
    for sentance in article:
        sentances.append(sentance.replace("[^a-zA-Z]","").split(" "))
    #sentances.pop()
    return sentances 

def sentance_similarity(sent1,sent2,stopwords=None):
    if stopwords is None:
        stopwords=[]
    sent1 = [w.lower() for w in sent1]
    sent2 = [w.lower() for w in sent2]
    all_words = list(set(sent1+sent2))

    vector1= [0] * len(all_words)
    vector2= [0] * len(all_words)
    for w in sent1:
        if w in stopwords:
            continue
        vector1[all_words.index(w)] += 1
    for w in sent2:
        if w in stopwords:
            continue
        vector2[all_words.index(w)] += 1
    return 1-cosine_distance(vector1,vector2)

def gen_sim_matrix(sentances,stop_words):
    similarity_matrix=np.zeros((len(sentances),len(sentances)))
    for idx1 in range(len(sentances)):
        for idx2 in range(len(sentances)):
            if idx1 == idx2:
                continue
            similarity_matrix[idx1][idx2]=sentance_similarity(sentances[idx1],sentances[idx2],stop_words)

    return similarity_matrix

def generate_summary(file_name,top_n=5):
    stop_words=stopwords.words('english')
    summarize_text=[]
    sentances = read_article(file_name)
    matrix=gen_sim_matrix(sentances,stop_words)
    graph=nx.from_numpy_array(matrix)
    scores = nx.pagerank(graph)
    ranked_sentance=sorted(((scores[i],s)for i,s in enumerate(sentances)),reverse=True)
    for i in range(top_n):
        summarize_text.append(" ".join(ranked_sentance[i][1]))
    text = ". ".join(summarize_text)

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

Код начинается с импорта необходимых библиотек, включая Natural Language Toolkit (nltk) и библиотеку networkx для работы с графами в Python. Также загружается и импортируется корпус стоп-слов из nltk, представляющий собой список общеупотребительных английских слов, которые часто удаляются из текстовых данных, поскольку они не имеют большого значения.

Функция read_article читает текстовый файл и разбивает его на отдельные предложения. Функция sentance_similarity вычисляет сходство между двумя предложениями на основе наличия общих слов, исключая стоп-слова. Функция gen_sim_matrix создает матрицу показателей сходства для всех пар предложений в тексте.

Функция generate_summary — это основная функция для создания сводки текста. Сначала он вызывает функцию gen_sim_matrix для создания матрицы показателей сходства, а затем преобразует эту матрицу в график с помощью networkx библиотека. Затем к графику применяется алгоритм PageRank для расчета оценки для каждого предложения. Затем выбираются лучшие N предложений, которые возвращаются в качестве сводки.

РЕЗЮМЕ

› ОБЗОР 3

from models.summary_model.model import SummaryModel,tokenizer

trained_model = SummaryModel.load_from_checkpoint("models\\summary_model\\best-checkpoint.ckpt")
trained_model.freeze()

def summarize(text):
  text_encoding = tokenizer(
  text,
  max_length=512,
  padding="max_length",
  truncation=True,
  return_attention_mask=True,
  add_special_tokens=True,
  return_tensors="pt"
)

  generated_ids = trained_model.model.generate(
    input_ids=text_encoding["input_ids"],
    attention_mask=text_encoding["attention_mask"],
    max_length=150,
    num_beams=2,
    repetition_penalty=2.5,
    length_penalty=1.0,
    early_stopping=True
  )

  preds = [
    tokenizer.decode(gen_id, skip_special_tokens=True, clean_up_tokenization_spaces=True)
    for gen_id in generated_ids
  ]

  return "".join(preds)

Этот код использует предварительно обученную сводную модель для создания сводки заданного фрагмента текста. Класс SummaryModel импортируется из модуля summary_model.model, а также функции токенизатора. Затем обученная_модель загружается из файла контрольной точки с помощью метода load_from_checkpoint и замораживается, чтобы предотвратить дальнейшее обучение.

Функция суммирования принимает фрагмент текста и кодирует его с помощью функции токенизатора. Затем закодированный текст передается методу generate модели, который генерирует сводку текста. Сгенерированная сводка возвращается в качестве вывода.

Метод generate имеет несколько параметров, которые можно настроить для управления поведением генерации сводки. Параметр max_length указывает максимальную длину генерируемой сводки, параметр num_beams управляет количеством лучей, используемых в алгоритм поиска луча, а параметры repetition_penalty и length_penalty управляют компромиссом между повторением и длиной в сгенерированное резюме.

› ЗАГОЛОВКИ

from simplet5 import SimpleT5

def generate_headline(text):

    model = SimpleT5()

    model.load_model("t5","models\\headline_model", use_gpu=False)

    headline = model.predict(text)[0]

    return headline

предварительно обученная модель T5 для создания заголовка для заданного фрагмента текста. Класс SimpleT5 импортирован из библиотеки simplet5, которая предоставляет простой интерфейс для использования модели T5.

Функция generate_headline принимает фрагмент текста и создает объект SimpleT5. Затем модель загружается из файла контрольной точки с помощью метода load_model, а графический процессор отключается для прогнозирования. Затем текст передается в метод предсказания модели, который генерирует заголовок для текста. Сгенерированный заголовок возвращается в качестве вывода.

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

PDF-TO-ТЕКСТ

Это одна из функций, с помощью которой пользователь также может загрузить свой PDF-файл, чтобы подвести итоги.

Первый шаг — установить библиотеку PyPDF2 с помощью pip. Вы можете сделать это, выполнив следующую команду:

pip install pypdf2

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

def pdf_to_text(file):

    pdffile = open(file,'rb')

    pdfReader = PyPDF2.PdfFileReader(pdffile)

    num = pdfReader.numPages

    for i in range(0,num):
        pageobj = pdfReader.getPage(i)
        resulttext = pageobj.extractText()
        newfile = open(r"content.txt", "w")
        newfile.writelines(resulttext)
    
    demo=open("content.txt","r")
    str1=demo.read()
    return str1

Давайте подробнее рассмотрим, что происходит в приведенном выше коде. Сначала мы открываем файл PDF в режиме только для чтения и создаем объект для чтения PDF. Затем мы получаем количество страниц в файле PDF и перебираем каждую страницу, чтобы извлечь текст. Открываем новый текстовый файл и пишем в него текст. Наконец, мы открываем текстовый файл, читаем содержимое и возвращаем его в виде строки.

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

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

ОСНОВНОЙ

import streamlit as st
from io import StringIO
from pdf_txt import pdf_to_text
from headline import generate_headline
from summarizer1 import summarizer
from summarizer2 import generate_summary
from summarizer3 import summarize
from pathlib import Path
import os

st.markdown("<h1 style='text-align: center;'>TEXT SUMMARIZER v2.0</h1>",
            unsafe_allow_html=True)


file = st.file_uploader("Please choose a file", type=['txt', 'pdf'])
st.markdown("<h5 style='text-align: center;'>OR</h5>", unsafe_allow_html=True)
text = st.text_area("Input Text For Summary (More than 200 words)", height=200)
col1,  col2, col3 = st.columns(3)
if col1.button('SUMMARIZE'):
    #try:

        if file is not None:
            if bool(text)== True:
                st.error("ERROR: YOU CAN'T ENTER BOTH")
                st.stop()
            else:
                if file.name[-3:] == "pdf":
                    path=Path("uploaded_pdfs/" + file.name)
                    path.write_bytes(file.getvalue())
                    text = pdf_to_text("uploaded_pdfs/" + file.name)

                else:
                    stringio = StringIO(file.getvalue().decode("utf-8"))
                    text=stringio.read()
    
        textfile = open("content.txt","w")
        textfile.write(text)
        textfile.close()
        headline=generate_headline(text)
        summary1=summarizer(text)
        summary2=generate_summary("content.txt")
        summary3=summarize(text)
        st.write("")
        st.subheader(headline)
        st.markdown("<h4> > Summary 1 : </h4>" ,  unsafe_allow_html=True)                                
        st.write(summary1)
        st.markdown("<h4> > Summary 2 : </h4>" ,  unsafe_allow_html=True)
        st.write(summary2)
        st.markdown("<h4> > Summary 3 : </h4>" ,  unsafe_allow_html=True)
        st.write(summary3)

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

Первая строка импортирует библиотеку Streamlit. Следующие четыре строки импортируют различные функции из других модулей: pdf_to_text для извлечения текста из файла PDF, generate_headline для создания заголовка для введенного текста, summarizer, generate_summary и summarize. для создания резюме введенного текста. Также импортируются библиотеки pathlib и os.

Приложение начинается с отображения заголовка и виджета загрузки файлов. Пользователь может либо ввести текстовый файл или файл PDF, либо ввести текст непосредственно в виджет текстовой области. Затем пользователь может нажать кнопку «СУММАРИЗИРОВАТЬ», чтобы сгенерировать сводку ввода.

Если пользователь вводит файл, код проверяет, является ли он PDF-файлом или нет. Если это файл PDF, код использует функцию pdf_to_text для извлечения текста из файла и сохранения его в переменной с именем text. Если это не PDF-файл, код считывает текст из файла и сохраняет его в text. Затем переменная text записывается в файл с именем 'content.txt'.

Затем код вызывает функции generate_headline, summarizer, generate_summary и summarize для создания трех сводок входного текста. Заголовок и резюме затем отображаются для пользователя.

ЗАКЛЮЧЕНИЕ

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

ПОЛНЫЙ ИСХОДНЫЙ КОД ПОСЕТИТЕ: →GitHub