Logistic Regression: классификатор имён на Python

Дмитрий Филатов
На моём сайте уже как-то была статья о том, как научить машину классифицировать составные части русских имён. Но, полагаю, она выглядит неполно без примера классификатора на Python (который в ней, к слову, вскользь упоминается).

Делать будем то же самое: классифицировать слова и фразы. И, если всмотреться, то окажется, что и программный код-то тот же самый, только написан на другом языке. Одно важное отличие: колонки в вашем датасете должны быть озаглавлены. И, для разнообразия, будем использовать другой символ-разделитель колонок. А ещё, попробуем помимо частей имён классифицировать другие объекты. Например, даты и географические координаты. Итак, структура нашего датасет будет вот такой:

X@y
Маск@text:surname
Илон@text:name
Ривович@text:patronymic
30 июля 2022 17:17@datetime:text
30 июля 2022@date:text
30.07.2022 17:17@datetime:digital
30.07.2022@date:digital
55.030414, 82.924501@coordinates:dd
55°01'49.5"N 82°55'28.2"E@coordinates:dms

Здесь в самой первой строке - заголовки столбцов ( X и y), разделённые заданным разделителем (@), а далее на каждой строчке - образец текста, разделитель, категория. Категорий на сей раз больше (text, datetime, date, coordinates) и у каждой есть своя подкатегория (surname, name, patronymic и т.д.; загадочные подкатегории dd и dms у координат - это, как вы уже догадались, нотации "decimal degrees" и "degrees, minutes, seconds").

Небольшое лирическое отступление. Где взять данные? Да везде! Я, например, даты и географические координаты вытягивал скриптом на Python из собственного цифрового архива, содержащего 40+ тысяч фотографий. Если хотите повторить этот подвиг - читайте про piexif. Ну, а набор данных по частям имён у меня остался ещё со времён первой статьи.

Обучающий код прост до безобразия.

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.linear_model import LogisticRegression
import pickle

dataset = pd.read_csv('dataset.txt', sep='@', encoding='utf-8')

X = dataset['X']
y = dataset['y']

X_train, X_test, y_train, y_test = train_test_split(X, y)

pipe = Pipeline([('vectorizer', CountVectorizer()),
('transformer', TfidfTransformer()),
('classificator', LogisticRegression())])

pipe.fit(X_train, y_train)

print(pipe.score(X_test, y_test))

with open('model.pkl', 'wb') as file:
pickle.dump(pipe, file)

Как видите, всё то же самое: создаём Pipeline и с его помощью пропускаем образцы текста последовательно через CountVectorizer, TfidfTransformer и LogisticRegression. В конце сохраняем полученную модель в файл. Чтобы воспользоваться моделью, нужно просто восстановить её из файла:

import pickle

with open('model.pkl', 'rb') as file:
pickle_model = pickle.load(file)

А теперь можно что-нибудь классифицировать.

print(pickle_model.predict(['54.574332, 83.354304']), '54.574332, 83.354304')
print(pickle_model.predict(['25.07.2022']), '25.07.2022')
print(pickle_model.predict(['18 мая 2020 18:43']), '18 мая 2020 18:43')
print(pickle_model.predict(['''54°34'27.6"N 83°21'15.5"E''']), '''54°34'27.6"N 83°21'15.5"E''')
print(pickle_model.predict(['Миклухо-Маклай']), 'Миклухо-Маклай')

Выведет:

['coordinates:dd'] 54.574332, 83.354304
['date:digital'] 25.07.2022
['datetime:text'] 18 мая 2020 18:43
['coordinates:dms'] 54°34'27.6"N 83°21'15.5"E
['text:surname'] Миклухо-Маклай

Ничего сложного. Однако, стоит помнить, что качество предсказаний модели напрямую зависит от качества тренировочного набора данных, и если ваша модель выдаёт нелепые предсказания - в первую очередь, следует пересмотреть состав датасета и переобучить модель. Ну и, разумеется, всегда полезно выбрать параметры, отличные от стандартных, и посмотреть, что получится. У конвертера, трансформера и классификатора можно настроить много разных параметров.
2022-07-30