Введение

Извлечение адресов из необработанных данных — ценный инструмент для предприятий и организаций, которым требуется обрабатывать большие объемы письменных данных, таких как счета-фактуры или сообщения клиентов. Система автоматического извлечения адресов — это инструмент, который автоматически извлекает и идентифицирует адреса из неструктурированного текста. Он идентифицирует и извлекает соответствующую информацию, такую ​​как названия улиц, названия городов и почтовые индексы. Извлеченные адреса затем можно использовать для различных задач, таких как геокодирование, проверка адресов и анализ данных. Система может быть обучена работе с различными форматами адресов и языками и может быть интегрирована в широкий спектр приложений. В этой статье мы планируем пройтись по различным методам извлечения адресов и пакетам Python.

Постановка задачи

Извлечение и разбор адреса из обычного текста. Учитываются следующие категории адресов.

Номер дома
Улица
Город
Штат
Почтовый индекс
Страна

Пример:
1. Адрес офиса DMC: 3146 Barter St BEAUMONT TAXAS 77707–3514 US.

Извлечение:
3146 — номер дома
Barter St BEAUMONT — название улицы
TAXAS — штат
77707–3514 — почтовый индекс
США — штат

Содержание

  • Постановка задачи
  • Подходы
    1. pyap
    2. usaddress
    3. nltk chunker
    4. flair (обучение с учителем)
    5. Simple Transformer (обучение с учителем)
  • Основные моменты
  • Заключение

подходы

Простой подход к извлечению адресов заключается в использовании системы, основанной на правилах, в которой набор предопределенных правил используется для идентификации и извлечения адресов. Одним из примеров системы, основанной на правилах, является использование регулярных выражений для сопоставления шаблонов адресов в тексте, таких как наличие определенных ключевых слов (например, «улица», «авеню» и т. д.) или использование чисел и сокращений в адресах. адрес.

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

Недавние достижения в области обработки естественного языка (NLP) включают использование методов глубокого обучения, таких как модели преобразования, предварительное обучение на больших наборах данных и перенос обучения для повышения производительности при выполнении различных задач NLP. Эти методы привели к значительному улучшению понимания естественного языка, машинного перевода и генерации текста. Кроме того, растет интерес к использованию НЛП для таких задач, как диалоговые системы, разговорный ИИ и понимание контекста текста в мультимодальном наборе.

Одним из ключевых преимуществ использования обработки естественного языка (NLP) для извлечения адресов является то, что она позволяет получать более точные и последовательные результаты, чем ручные методы. Это связано с тем, что алгоритмы машинного обучения могут обучаться и адаптироваться на основе данных, которые им предоставляются, со временем становясь более точными и эффективными.

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

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

1. Пяп

Pyap¹ — это библиотека обработки текста для парсеров адресов. В настоящее время он поддерживает адреса США, Канады и Великобритании. Pyap основан на регулярных выражениях, поэтому его выполнение выполняется быстрее.

!pip install pyap
import pyap
text = "44 West 22nd Street, New York NY 12345"
addresses = pyap.parse(text, country='US')
for address in addresses:
    # shows found address
    print(address)
    # shows address parts
    print(address.as_dict())
    # 44 West 22nd Street, New York NY 12345
    # {'full_address': '44 West 22nd Street, New York NY 12345', 'full_street': '44 West 22nd Street', 'street_number': '44', 'street_name': 'West 22nd', 'street_type': 'Street', 'route_id': None, 'post_direction': None, 'floor': None, 'building_id': None, 'occupancy': None, 'city': 'New York', 'region1': 'NY', 'postal_code': '12345', 'country_id': 'US', 'match_start': 0, 'match_end': 38}

Самое приятное то, что он анализирует полный адрес и предоставляет необходимые детализированные данные. Учтите это для выполнения базового извлечения.

Блокнот: пяп

Ограничение:

  • Pyap основан на регулярных выражениях, он может давать ложноположительные результаты.

2. адрес США

usaddress² — еще одна библиотека Python для извлечения адресов из неструктурированных данных. Он поддерживает только адреса США.

Он использует парсератор вероятностную модель для предсказания. В синтаксическом анализаторе доступны следующие метки.

  • AddressNumber — номер адреса
  • AddressNumberPrefix — модификатор перед номером адреса, например. «Миля», «#»
  • AddressNumberSuffix — модификатор после номера адреса, например, «B», «1/2».
  • BuildingName — название здания, например. «Финансовый центр Атланты»
  • CornerOf — слова, указывающие на то, что адрес находится в углу, например. «Перекресток», «угол»
  • IntersectionSeparator — соединение, соединяющее части перекрестка, например. 'и', '&'
  • LandmarkName — название ориентира, например. «Ригли Филд», «Юнион Стейшн»
  • NotAddress — неадресный компонент, не относящийся к получателю.
  • OccupancyType — тип занятости в здании, например. «Люкс», «Квартира», «Этаж»
  • OccupancyIdentifier — идентификатор занятости, часто число или буква.
  • PlaceName — город
  • Получатель — получатель без адреса, например имя человека/организации
  • StateName — состояние
  • StreetName – название улицы без указания типа и направления.
  • StreetNamePreDirectional — направление перед названием улицы, например. «Север», «С»
  • StreetNamePreModifier — модификатор перед названием улицы, который не является направлением, например. 'Старый'
  • StreetNamePreType — тип улицы, который стоит перед названием улицы, например «Маршрут», «Авеню»
  • StreetNamePostDirectional — направление после названия улицы, например. «Север», «С»
  • StreetNamePostModifier — модификатор к названию улицы, например. «Внешний»
  • StreetNamePostType — тип улицы, который следует после названия улицы, например «Авеню», «Рд»
  • SubaddressIdentifier — имя/идентификатор компонента подадреса.
  • SubaddressType — уровень детализации адреса, который не относится к жилому помещению в здании, например. «Здание», «Башня»
  • USPSBoxGroupID – идентификатор группы ящиков USPS, обычно число.
  • USPSBoxGroupType — название группы ящиков USPS, например. «РР»
  • USPSBoxID — идентификатор ящика USPS, обычно число.
  • USPSBoxType — поле USPS, например. «П.О. Коробка'
  • ZipCode – почтовый индекс.

Метод «Парсер» разделит вашу адресную строку на токены и пометит все токены.

import usaddress
text = "DMC office address is 3146 Barter St BEAUMONT TAXAS 77707-3514 US."
usaddress.parse(text)
# [('DMC', 'Recipient'),
#  ('office', 'Recipient'),
#  ('address', 'Recipient'),
#  ('is', 'Recipient'),
#  ('3146', 'AddressNumber'),
#  ('Barter', 'StreetName'),
#  ('St', 'StreetNamePostType'),
#  ('BEAUMONT', 'PlaceName'),
#  ('TAXAS', 'StateName'),
#  ('77707-3514', 'ZipCode'),
#  ('US.', 'CountryName')]

«тег» объединит последовательные компоненты и разделит запятые, а также вернет тип адреса (уличный адрес, перекресток, абонентский ящик или неоднозначный). Это может вызвать ошибку «RepeatedLabelError», если несколько областей адреса имеют одну и ту же метку и, следовательно, не могут быть объединены.

try:
    usaddress.tag(text)
except usaddress.RepeatedLabelError as e :
    print(e.parsed_string, e.original_string)
#(OrderedDict([('Recipient', 'DMC office address is'),
#              ('AddressNumber', '3146'),
#              ('StreetName', 'Barter'),
#             ('StreetNamePostType', 'St'),
#              ('PlaceName', 'BEAUMONT'),
#              ('StateName', 'TAXAS'),
#              ('ZipCode', '77707-3514'),
#              ('CountryName', 'US.')]),
# 'Street Address')

Чтобы отобразить последовательные метки, можно использовать следующий аргумент.

usaddress.tag(text, tag_mapping={
   'Recipient': 'recipient',
   'AddressNumber': 'home1',
   'AddressNumberPrefix': 'home1',
   'AddressNumberSuffix': 'home1',
   'StreetName': 'home1',
   'StreetNamePreDirectional': 'st1',
   'StreetNamePreModifier': 'st1',
   'StreetNamePreType': 'st1',
   'StreetNamePostDirectional': 'st1',
   'StreetNamePostModifier': 'st1',
   'StreetNamePostType': 'st1',
   'CornerOf': 'st1',
   'IntersectionSeparator': 'st1',
   'LandmarkName': 'st1',
   'USPSBoxGroupID': 'st1',
   'USPSBoxGroupType': 'st1',
   'USPSBoxID': 'st1',
   'USPSBoxType': 'st1',
   'BuildingName': 'st1',
   'OccupancyType': 'home1',
   'OccupancyIdentifier': 'home1',
   'SubaddressIdentifier': 'home1',
   'SubaddressType': 'home1',
   'PlaceName': 'city',
   'StateName': 'state',
   'ZipCode': 'zip_code',
})

usaddress предоставляет готовый к использованию функционал для извлечения, и в большинстве случаев он отлично работает.

Блокнот: usaddress

Ограничение:

  • Он поддерживает только адрес США
  • Вероятность прогноза недоступна для обработки неправильного прогноза
  • Нет последних обновлений в репозитории

3. НЛТК

Этот пакет использует метод фрагментации NLTK³ для анализа адреса. Он использует уже помеченные более 9000 предложений с тегами IOB. Он использует ClassifierBasedTagger, основанный на Наивном байесовском классификаторе.

Этот список был создан с использованием нескольких методов: Получение существующего набора данных веб-страниц с контактной информацией отелей/пиццерий; Генерация поддельного текста с поддельными адресами; Вставка случайных адресов в корпус nltk.corpus.treebank.

Что такое разбиение на фрагменты?
«Разбиение на фрагменты — это процесс извлечения фраз из уже проанализированного текста, т. е. получение именных или глагольных фраз из размеченных данных POS».

Что такое теги IOB?
Это нотация фрагментов для захвата всего токена. Эти теги могут обозначать внутреннюю часть, внешнюю часть и начало фрагмента. Здесь разрешены не только словосочетания с существительными, но и несколько различных типов словосочетаний-фрагментов.
B-NP: начало именного словосочетания
I-NP: описывает, что слово находится внутри текущего именного словосочетания (часть предыдущей работы).
O:конец предложения.

Пример:
«Mr. Бин был президентом США».
Теги POS:
Mr. NNP B-NP
Bean NNP I-NP
был VBD B-VP< br /> был VBN I-VP
президентом NN I-NP
IN B-PP
США NNP B-NP

В приведенном выше предложении г-н Бин обозначает одну группу существительных, нотации IOB помогают завершить

предварительно скомпилированный набор тегов данные

# Extract address from unstructured text

import pickle
import nltk
import string

from nltk import pos_tag
from nltk import word_tokenize
from nltk.chunk import ChunkParserI
from nltk.chunk import conlltags2tree, tree2conlltags
from nltk.tag import ClassifierBasedTagger
from nltk.tag.util import untag
from nltk.stem.snowball import SnowballStemmer

# IOB tag name for specifying address 
GPE_TAG = "GPE"

class AddressChunker(ChunkParserI):
    def __init__(self, train_sents, **kwargs):
        self.tagger = ClassifierBasedTagger(
            train=train_sents,
            feature_detector=self.features,
            **kwargs)

    def parse(self, tagged_sent):
        chunks = self.tagger.tag(tagged_sent)

        # Transform the result from [((w1, t1), iob1), ...]
        # to the preferred list of triplets format [(w1, t1, iob1), ...]
        iob_triplets = [(w, t, c) for ((w, t), c) in chunks]

        # Transform the list of triplets to nltk.Tree format
        return conlltags2tree(iob_triplets)
    
    def features(self, tokens, index, history):
        # for more details see: http://nlpforhackers.io/named-entity-extraction/ 
        
        """
        `tokens`  = a POS-tagged sentence [(w1, t1), ...]
        `index`   = the index of the token we want to extract features for
        `history` = the previous predicted IOB tags
        """

        # init the stemmer
        stemmer = SnowballStemmer('english')

        # Pad the sequence with placeholders
        tokens = [('[START2]', '[START2]'), ('[START1]', '[START1]')] + list(tokens) + [('[END1]', '[END1]'), ('[END2]', '[END2]')]
        history = ['[START2]', '[START1]'] + list(history)

        # shift the index with 2, to accommodate the padding
        index += 2

        word, pos = tokens[index]
        prevword, prevpos = tokens[index - 1]
        prevprevword, prevprevpos = tokens[index - 2]
        nextword, nextpos = tokens[index + 1]
        nextnextword, nextnextpos = tokens[index + 2]
        previob = history[index - 1]
        contains_dash = '-' in word
        contains_dot = '.' in word
        allascii = all([True for c in word if c in string.ascii_lowercase])

        allcaps = word == word.capitalize()
        capitalized = word[0] in string.ascii_uppercase

        prevallcaps = prevword == prevword.capitalize()
        prevcapitalized = prevword[0] in string.ascii_uppercase

        nextallcaps = prevword == prevword.capitalize()
        nextcapitalized = prevword[0] in string.ascii_uppercase

        f = {
            'word': word,
            'lemma': stemmer.stem(word),
            'pos': pos,
            'all-ascii': allascii,

            'next-word': nextword,
            'next-lemma': stemmer.stem(nextword),
            'next-pos': nextpos,

            'next-next-word': nextnextword,
            'nextnextpos': nextnextpos,

            'prev-word': prevword,
            'prev-lemma': stemmer.stem(prevword),
            'prev-pos': prevpos,

            'prev-prev-word': prevprevword,
            'prev-prev-pos': prevprevpos,

            'prev-iob': previob,

            'contains-dash': contains_dash,
            'contains-dot': contains_dot,

            'all-caps': allcaps,
            'capitalized': capitalized,

            'prev-all-caps': prevallcaps,
            'prev-capitalized': prevcapitalized,

            'next-all-caps': nextallcaps,
            'next-capitalized': nextcapitalized,
        }

        return f

def get_address_chunker(dataset_file_name):
    """
    returns AddressChunker instance with dataset_file_name as training samples
    `dataset_file_name` = file name of pickled list of CoNLL IOB format sentences
    """

    with open(dataset_file_name, 'rb') as fp:
        dataset = pickle.load(fp)
        print(len(dataset))
        chunker = AddressChunker(dataset)

    return chunker

def get_chuncker_accuracy(chunker, test_samples):
    """
    returns score of the chunker against the gold standard
    """
    score = chunker.evaluate([
        conlltags2tree([(w, t, iob) for (w, t), iob in iobs])
        for iobs in test_samples
        ])
    return score.accuracy()

def get_tagged_sentence(chunker, sentence):
    """
    returns IOB tagged tree of sentence
    """
    return chunker.parse(pos_tag(word_tokenize(sentence)))

def extract_address(chunker, sentence):
    """
    returns all addresses in sentence
    """
    def tree_filter(tree):
        return GPE_TAG == tree.label()

    tagged_tree = get_tagged_sentence(chunker, sentence)
    addresses = list()
    for subtree in tagged_tree.subtrees(filter=tree_filter):
        addresses.append(untag(subtree.leaves()))
    return addresses

print("Loading dataset...")
chunker = get_address_chunker('dataset/IOB_tagged_addresses.pkl')
# Copy your address here.
addresses = extract_address(chunker, "Hey man! Joe lives here: 44 West 22nd Street, New York, NY 12345. Can you contact him now? If you need any help, call me on 12345678")
print([" ".join(address) for address in addresses])

Модуль NLTK извлекает все возможные наборы полных адресов в тексте. В настоящее время он не анализирует адреса. Однако его можно использовать в качестве предшественника для моделей синтаксического анализатора адресов, таких как usaddress, для лучшего прогнозирования в целом.

Блокнот: nltk_chunker

Ограничение:

  • Работает только для американского адреса
  • Не анализирует текст адреса

4. Чутье

Flair⁵ — одна из мощных библиотек, разработанных Берлинским университетом им. Гумбольдта. Flair можно использовать для всех популярных задач НЛП, таких как классификация, распознавание именованных объектов, классификация нулевого выстрела и многие другие.

Для извлечения адреса мы рассмотрели уже аннотированный набор данных[4]. Набор данных содержит 200 аннотированных образцов адресов США в следующих категориях.

  • Название здания
  • Building_Number
  • Название улицы
  • Город, Штат
  • Почтовый индекс
  • Страна
  • Получатель

Мы планируем обучать модель с предварительно обученной моделью из библиотеки талантов.

  1. Установите библиотеку талантов
!pip install flair

2. Набор данных должен быть преобразован во входной формат Flair, т. е. в нотацию BIO.

import pandas as pd
import numpy as np
import pandas as pd
from flair.data import Corpus
from flair.datasets import ColumnCorpus
import re, math
columns = ['Building_Name', 'Building_Number', 'City', 'Recipient',
       'Street_Name', 'Zip_Code', 'State', 'Country']
count=0
labels = set()
def generate_data(file_name):
    data = pd.read_csv(file_name)
    def get_value(x):
        global count
        results = []
        address = x["Address"]
        previous = ""
        _temp = x.to_dict()
        for each in address.split():
            match = False
            for col in columns:
                if each.strip(" ,.-") in str(_temp[col]):
                    if previous == col:
                        results.append((count, each, "I-"+col))
                        labels.add("I-"+col)
                    else:
                        results.append((count, each, "B-"+col)) 
                        labels.add("B-"+col)
                    previous = col
                    match = True
                    break
            if not match:
                results.append((count, each, "O")) 
                labels.add("O")
                match = False
        results.append(("", "",""))
        count += 1
        return results
    values = data[:].apply(lambda x:get_value(x), axis=1)
    flat_list = [item for sublist in values for item in sublist]
    train_df = pd.DataFrame(flat_list, columns=["sentence_id", "words", "labels"])
    return train_df

3. Загрузите поезд и проверьте CSV-файл.

train_df = generate_data("us-train-dataset.csv")
test_df = generate_data("us-test-dataset.csv")
train_df[["words", "labels"]].tail(20)

4. Создайте текстовый файл, совместимый с чутьем ввода

train_df[["words", "labels"]].to_csv(r'train/train.txt', header=None, index=None, sep=' ')
test_df[["words", "labels"]].to_csv(r'train/test.txt', header=None, index=None, sep=' ')

5. Загрузите набор данных и инициализируйте вложения.

# define columns
columns = {0 : 'text', 1 : 'ner'}
# directory where the data resides
data_folder = 'train/'
# initializing the corpus
corpus: Corpus = ColumnCorpus(data_folder, columns,
                              train_file = 'train.txt',
                              test_file = 'test.txt',
                              dev_file = 'test.txt')
print(len(corpus.train))
# tag to predict
columns = {0: 'text', 1: 'ner'}
tag_type = columns[1]
# make tag dictionary from the corpus
tag_dictionary = corpus.make_label_dictionary("ner")
from flair.embeddings import FlairEmbeddings, TransformerWordEmbeddings
# init Flair embeddings
flair_forward_embedding = FlairEmbeddings('multi-forward')
flair_backward_embedding = FlairEmbeddings('multi-backward')
# init multilingual BERT
bert_embedding = TransformerWordEmbeddings('bert-base-multilingual-cased')
from flair.embeddings import StackedEmbeddings
# now create the StackedEmbedding object that combines all embeddings
embeddings = StackedEmbeddings(
    embeddings=[flair_forward_embedding, flair_backward_embedding, bert_embedding])

6. Обучите модель

from flair.datasets import CONLL_03
from flair.embeddings import WordEmbeddings, FlairEmbeddings, StackedEmbeddings
from flair.models import SequenceTagger
from flair.trainers import ModelTrainer
print(corpus)

# 2. what label do we want to predict?
label_type = 'ner'

# 3. make the label dictionary from the corpus
label_dict = corpus.make_label_dictionary(label_type=label_type)
print(label_dict)

# 4. initialize embedding stack with Flair and GloVe
embedding_types = [
    # WordEmbeddings('glove'),
    FlairEmbeddings('news-forward'),
    FlairEmbeddings('news-backward'),
]

embeddings = StackedEmbeddings(embeddings=embedding_types)

# 5. initialize sequence tagger
tagger = SequenceTagger(hidden_size=256,
                        embeddings=embeddings,
                        tag_dictionary=label_dict,
                        tag_type=label_type,
                        use_crf=True)

# 6. initialize trainer
trainer = ModelTrainer(tagger, corpus)

# 7. start training
trainer.train('resources/taggers/sota-ner-flair',
              learning_rate=0.1,
              mini_batch_size=32,
              max_epochs=50)

7. Прогнозирование невидимых данных.

from flair.data import Sentence
from flair.models import SequenceTagger
# load the trained model
model = SequenceTagger.load('/content/resources/taggers/sota-ner-flair/best-model.pt')
# create example sentence
sentence = Sentence('My address is 223 NW STATE STRE, DOVER, DE 19001, United States, Thank you for confirming.')
# predict the tags
model.predict(sentence)
# print(sentence.to_tagged_string())
print(sentence.labels)

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

Блокнот: Флер

Ограничение:

  • Для лучших результатов требуется больший набор данных
  • Время вывода немного выше для ЦП

5. Простой трансформатор

Простой трансформатор⁶ — это библиотека НЛП, оптимизированная для простоты использования. Он предоставляет все возможности преобразователя с очень минимальным количеством строк кода. Он обеспечивает поддержку всех стандартных задач NLP, таких как NER, классификация, ответ на вопрос и т. д.

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

  1. Установите пакет Transformer
!pip install simpletransformers

2. Преобразуйте входной набор данных в нотацию BOI. Simple Transformer требует данные в нотации IOB со столбцами "идентификатор_предложения", "слова" и "метки".

import pandas as pd
import re, math
import numpy as np
import pandas as pd
from scipy.special import softmax
from simpletransformers.ner import NERModel
import logging
logging.basicConfig(level=logging.INFO)
transformers_logger = logging.getLogger("transformers")
transformers_logger.setLevel(logging.WARNING)
columns = ['Building_Name', 'Building_Number', 'City', 'Recipient',
       'Street_Name', 'Zip_Code', 'State', 'Country']
count=0
labels = set()
def generate_data(file_name):
    data = pd.read_csv(file_name)
    def get_value(x):
        global count
        results = []
        address = x["Address"]
        previous = ""
        _temp = x.to_dict()
        for each in address.split():
            match = False
            for col in columns:
                if each.strip(" ,.-") in str(_temp[col]):
                    if previous == col:
                        results.append((count, each, "I-"+col))
                        labels.add("I-"+col)
                    else:
                        results.append((count, each, "B-"+col)) 
                        labels.add("B-"+col)
                    previous = col
                    match = True
                    break
            if not match:
                results.append((count, each, "O")) 
                labels.add("O")
                match = False
        # results.append(("", "",""))
        count += 1
        return results
    values = data[:].apply(lambda x:get_value(x), axis=1)
    flat_list = [item for sublist in values for item in sublist]
    train_df = pd.DataFrame(flat_list, columns=["sentence_id", "words", "labels"])
    return train_df
train_df = generate_data("us-train-dataset.csv")
test_df = generate_data("us-test-dataset.csv")
train_df.to_csv(r'pandas1.txt', header=None, index=None, sep=' ', mode='a')

3. Инициализируйте модель NER

arguments={"save_eval_checkpoints": False,
      "save_steps": -1,
      'overwrite_output_dir': True,
      "save_model_every_epoch": False,
      'reprocess_input_data': True, 
      "train_batch_size": 5,
      'num_train_epochs': 50,
      "max_seq_length": 256, 
      "gradient_accumulation_steps": 8,
      "learning_rate": 4e-5,
      "do_lower_case": False,
      "adam_epsilon" : 1e-8,
      "train_batch_size": 8,
      "eval_batch_size": 8,
      "fp16" : True
      }
model = NERModel(
    "bert",
    "distilbert-base-uncased",
    args=arguments,
    labels =  list(labels)
)

Мы строго настроили следующие параметры для большей точности.

  • do_lower_case: True: заглавные буквы помогают обеспечить лучший контекст
  • Learning_rate: 4e-5 : Стандартная скорость обучения
  • train_batch_size и evel_batch_size могут быть увеличены, если добавлено больше образцов

4. Запустите тренировочный цикл

# Train the model
model.train_model(train_df)
# Evaluate the model
result, model_outputs, predictions = model.eval_model(train_df)
print(result)
# {'eval_loss': 0.11480890100614892,
#  'precision': 0.9591054313099041,
#  'recall': 0.9578813018506701,
#  'f1_score': 0.9584929757343551}
# prediction on test dataset (unseen sample)
result, model_outputs, predictions = model.eval_model(test_df)
print(result)
#{'eval_loss': 0.7861490646998087,
# 'precision': 0.7011494252873564,
# 'recall': 0.7176470588235294,
# 'f1_score': 0.7093023255813954}

5. Прогноз на тестовом наборе данных

# Predictions on arbitrary text strings
sentences = ["I stay at HIGHWAY 11-E, RUSSELLVILLE, TN 00000, United States"]
predictions, raw_outputs = model.predict(sentences)
print(predictions)
[[{'I': 'O'},
{'stay': 'I-Street_Name'},
{'at': 'O'},
{'HIGHWAY': 'I-Street_Name'},
{'11-E,': 'I-Street_Name'},
{'RUSSELLVILLE,': 'B-City'},
{'TN': 'B-State'},
{'00000,': 'O'},
{'United': 'B-Country'},
{'States': 'I-Country'}]]

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

Блокнот: СТ

Ограничение:

  • Для лучших результатов требуется больший набор данных
  • Время вывода немного выше для ЦП

Основные моменты

  1. pyap и usaddress предоставляют готовые возможности синтаксического анализа.
  2. Usaddress работает хорошо большую часть времени, однако ему не хватает показателя достоверности для прогнозов.
  3. Модель Flair или преобразователя предложений обеспечивает хорошие возможности по следующим причинам:
     – Огромный контроль над ожидаемым извлечением.
     – Ее можно улучшить с помощью больших обучающих данных.

Заключение

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

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

Ссылка

  1. https://pypi.org/project/pyap
  2. https://pypi.org/project/usaddress/
  3. https://github.com/bagrii/address_extraction
  4. https://github.com/swapnil-saxena/address-parser/tree/main/corpus/dataset
  5. https://github.com/flairNLP/flair
  6. https://simpletransformers.ai/docs/ner-specifics/

Если вам понравилась эта статья, поддержите меня аплодисментами. связаться со мной в LinkedIn. Пожалуйста, найдите github repo.