Читать нас в Telegram
Иллюстрация: Ксения Здоровец

Установка библиотеки koNLPy

Библиотека koNLPy предлагает пользователям пять классов для токенизации текстов на корейском языке: Kkma, Hannanum, Komoran, Mecab и Twitter. Они отличаются по своему функционалу. Вы можете выбрать тот, который больше соответствует вашим задачам. Чтобы начать с ними работать, устанавливаем саму библиотеку konlpy и импортируем все нужные нам классы.

!pip install konlpy
from konlpy.tag import Kkma, Hannanum, Komoran, Mecab, Twitter

Далее создаём экземпляры нужных классов и сохраняем результаты в соответствующие переменные:

twitter = Twitter()
mecab = Mecab()
kkma = Kkma()
hannanum = Hannanum()
komoran = Komoran()

Базовый морфологический анализ

Каждый класс содержит в себе несколько атрибутов. Рассмотрим сначала те, которые являются общими для всех классов, — это .morphs, .nouns и .pos. В результате применения этих атрибутов к строке с корейским текстом мы получаем соответственно список морфем, имён существительных и пар вида морфема, часть речи. Части речи обозначены буквами: NN (существительное), VV (глагол), SF (знак пунктуации) и т. д.

Атрибуты .morphs, .nouns и .pos работают для всех классов одинаково.  Для примера рассмотрим класс kkma:

>>>kkma.morphs(u'음식이 좀 상한 것 같아요.') #список морфем
['음식', '이', '좀', '상하', 'ㄴ', '것', '같', '아요', '.']

>>>kkma.nouns(u'음식이 좀 상한 것 같아요.') #список из имён существительных
['음식', '것']

>>>kkma.pos(u'음식이 좀 상한 것 같아요.') #список вида: морфема, часть речи
[('음식', 'NNG'),
 ('이', 'JKS'),
 ('좀', 'MAG'),
 ('상하', 'VV'),
 ('ㄴ', 'ETD'),
 ('것', 'NNB'),
 ('같', 'VA'),
 ('아요', 'EFN'),
 ('.', 'SF')]

Расшифровка частеречных тегов из примера выше:

NNG — простое существительное

JKS — частица

MAG — наречие

VV — глагол

ETD — показатель атрибутива

NNB — служебное имя

VA — прилагательное

EFN — индикативное окончание SF — знак пунктуации

Класс Hannanum

Теперь рассмотрим методы, которые доступны в отдельных классах. Так, в классе Hannanum можно вызвать атрибут .analyse, которое возвращает большой вложенный список. Этот список устроен следующим образом: для каждого токена возвращается список из всех возможных морфологических разборов. Причём каждый такой разбор тоже представляет собой список из пар вида морфема, часть речи.

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

  1. 노는 no-nɨn (весло) — как существительное с показателем топика — 는;
  2. 노는 no-nɨn (играющий) — как форма причастия настоящего времени -는 глагола 놀다 nolda (играть) .
>>>hannanum.analyze(u'노는')
[[[('노', 'ncn'), ('는', 'jxc')], [('놀', 'paa'), ('는', 'etm')], [('놀', 'pvg'), ('는', 'etm')]]]

Однако, в нашем примере, мы получили три разбора вместо двух: один разбор для существительного и два для глагола. Почему так произошло? Причиной являются особенности самого тегсета, который используется в Hannanum. Полный набор соответствий тегов приведен в таблице к документации библиотеки koNLPy. Согласно таблице, в класс глагола (предиката) P входят как собственно глаголы (PVG), так и прилагательные (PAA).

Класс Kkma

Атрибут .sentences из класса Kkma разбивает введённый текст по предложениям и возвращает его списком.

>>>kkma.sentences(u'그래도 계속 공부합니다. 재밌으니까!')
['그래도 계속 공부합니다.', '재밌으니까!']

Класс Twitter

Класс Twitter предлагает атрибут .phrases. В документации библиотеки koNLPy функция этого метода заключается в извлечении фраз, однако эксплицитного пояснения, что разработчики понимают под этой фразой, нет. В презентации для конференции по созданной библиотеке этому атрибуту отводится один слайд, где написано, что атрибут определяет собственно прилагательные, существительные, сочинительные группы 친구들과 어머니 (друзья и мама) и сочетания прилагательного вместе с существительным 재미있는 드라마 (интересная дорама).

Исследовав этот атрибут, можем сказать, что он также определяет и сочетания существительных 한국 음식 (корейская еда) / досл. (корея еда), поэтому из примера (1) ниже метод выделит фразу 올해 한국 досл. (этот год Корея). Однако, этот атрибут также считает фразой и данное сочетание из примера (1): 저의 어머니 (моя мама). Эта фраза не очень подходят под объяснение выше, в чём причина? Ответ опять кроется в особенностях того, как этот атрибут токенизирует и определяет часть речи. Дело в том, что токенизатор разбивает 저의 = 저 + 의 и считает местоимение (я/сам) при этом существительным. После такой токенизации получается, что рядом стоят два существительных, которые отлично подходят под объяснение.

Эту особенность важно учитывать, поскольку существительными этот атрибут считает и, например, такие наречия как 항상 (всегда), 어제 (вчера). Из-за токенизации также может вернуть как фразу существительное 산책 (прогулка) из составного глагола 산책하다 (гулять), как в примере (2). Причём, важно отметить, в рамках этого атрибута применяется своего рода нормализация, так как отбрасываются такие показатели, как топик (는), некоторые падежи (에), соединительные окончания (과), как в примерах (1) и (2):

#1 моя мама приедет в Корею в этом году
>>>twitter.phrases(u'저의 어머니는 올해 한국에 올 것입니다')
['저의 어머니', '올해', '올해 한국', '어머니', '한국']
#2 вместе с друзьями сходил в парк
>>>twitter.phrases(u'친구들과 함께 공원에서 산책하고 왔어요.')
['친구들', '공원', '산책']

Класс Mecab

Класс Mecab требует отдельной установки дополнительных зависимостей и не работает на Windows 7. Изначально был создан для японского языка, но затем был доработан и для корейского. Не имеет дополнительных интересных методов, помимо вышеописанных базовых, поэтому не будет приведён в сводной таблице ниже.

from konlpy.tag import Mecab
>>> mecab = Mecab()
>>> print(mecab.morphs(u'영등포구청역에 있는 맛집 좀 알려주세요.'))
['영등포구', '청역', '에', '있', '는', '맛집', '좀', '알려', '주', '세요', '.']
>>> print(mecab.nouns(u'우리나라에는 무릎 치료를 잘하는 정형외과가 없는가!'))
['우리', '나라', '무릎', '치료', '정형외과']
>>> print(mecab.pos(u'자연주의 쇼핑몰은 어떤 곳인가?'))
[('자연', 'NNG'), ('주', 'NNG'), ('의', 'JKG'), ('쇼핑몰', 'NNG'), ('은', 'JX'), ('어떤', 'MM'), ('곳', 'NNG'), ('인가', 'VCP+EF'), ('?', 'SF')]

Сводная таблица методов

Различия в поведении между различными методами токенизации таковы:

Элемент корейскогоkomoranhannanumkkmatwitter
Составные существительные: 곱슬머리, 도착역, 화장품Обычно предлагает оба варианта разбора, но иногда и только вместе/отдельноБывает и вместе, и отдельно, но чаще сохраняет единым существительнымБывает и вместе, и отдельно, но чаще сохраняет единым существительнымРазбивает на два слова и оставляет как одно примерно в равных пропорциях
Прилагательные на -하다 в разных формах (간단하게,불편한, 피곤하다)Корень + 하다 + грамм. морф.Корень + 하다 + грамм. морф.Корень + 하다 + грамм. морф.Единая лексема, часть речи определяется по функции формы
Бенефактив (보여줘, 보내줘요, 깨워주다 )Всегда отделяет 주다Всегда отделяет 주다Иногда отделяет 주다, иногда — нетНикогда не отделяет 주다, размечает как один глагол
Глаголы, образованные как noun + 하다Обычно разделяет существительное и 하다Обычно разделяет существительное и 하다Обычно разделяет существительное и 하다Обычно разделяет существительное и 하다
Официально-вежливый стиль (합쇼체)
Настоящее времяОтделяет как окончание -ㅂ니다/습니다Отделяет как окончание -ㅂ니다/습니다Отделяет как окончание -ㅂ니다/습니다Ничего не отделяет
Прошедшее времяОтделяет -었/았 + 습니다Отделяет -었/았+ 습니다 кроме случаев, когда форма второй основы совпадает с первой (가다/일어나다). В случае последнего вообще может не включить в разбор -었/았Отделяет -었/았+ 습니다 кроме случаев, когда форма второй основы совпадает с первой (가다/일어나다). В случае последнего дефолтно отделяет -었Ничего не отделяет
Будущее времяОтделяет показатель причастия будущего времени -(으)ㄹ и разбивает 것입니다 = 것 + 이 + ㅂ니다Отделяет показатель причастия будущего времени -(으)ㄹ и разбивает 것입니다 = 것 + 이 + ㅂ니다Отделяет показатель причастия будущего времени -(으)ㄹ и разбивает 것입니다 = 것 + 이 + ㅂ니다Не отделяет показатель причастия будущего времени -(으)ㄹ, но разбивает 것입니다 = 것 + 입니다
Повелительное наклонениеРазбивает на -(으)시 + ㅂ시오Отделяет целиком -(으)십시오Разбивает на -(으)시 + ㅂ시오Ничего не отделяет
Разговорно-вежливый стиль (해요체)
Настоящее времяОтделяет как окончание вместе с соединительной гласной -어/아요Предлагает варианты разбора, при которых может как разбить 어/아요 на -어/아 + 요, так и не разбивать и оставить единым окончаниемОтделяет как окончание вместе с соединительной гласной -어/아요Ничего не отделяет
Прошедшее времяОтделяет -었/았 + 어요Отделяет -었/았 + 어요 кроме случаев, когда форма второй основы совпадает с первой (가다/일어나다). В случае последнего вообще может не включить в разбор -었/았Отделяет -었/았 + 어요 кроме случаев, когда форма второй основы совпадает с первой (가다/일어나다). В случае последнего дефолтно отделяет -었Ничего не отделяет
Будущее времяОтделяет показатель причастия будущего времени -(으)ㄹ и разбивает 거에요 = 거 + 에요Отделяет показатель причастия будущего времени -(으)ㄹ и либо разбивает 거에요 = 거 + 에요, либо никак не разбиваетОтделяет показатель причастия будущего времени -(으)ㄹ и разбивает 거에요 = 거 + 에 + 요Не отделяет показатель причастия будущего времени -(으)ㄹ, но разбивает 거에요 = 거 + 에요
Разговорный стиль (해체 или 반말)
Настоящее времяОтделяет как окончание -어/아Отделяет как окончание -어/아Отделяет как окончание -어/아Ничего не отделяет
Прошедшее времяОтделяет -었/았 + 어Отделяет -었/았 + 어 кроме случаев, когда форма второй основы совпадает с первой (가다/일어나다). В случае последнего вообще может не включить в разбор -었/았 и 어Отделяет -었/았 + 어 кроме случаев, когда форма второй основы совпадает с первой (가다/일어나다). В случае последнего дефолтно отделяет -었Ничего не отделяет
Будущее времяОтделяет показатель причастия будущего времени -(으)ㄹ и разбивает 거야 = 거 + 야Отделяет показатель причастия будущего времени -(으)ㄹ и разбивает 거야 = 거 + 시 + 야Отделяет показатель причастия будущего времени -(으)ㄹ и неверно разбивает 거야 = на глагольную основу 그 + 어야Ничего не отделяет
Книжный стиль (해라체)
Настоящее времяОтделяет как окончание -ㄴ다/는다Разбивает 는다 на 는 + 다

В формах на -ㄴ다 ничего не отделяет
Отделяет как окончание -ㄴ다/는다

Отделяет как окончание -ㄴ다, но может при этом ошибаться с основой глагола
Ничего не отделяет
Прошедшее времяОтделяет -었/았 + 다Отделяет -었/았 + 다 кроме случаев, когда форма второй основы совпадает с первой (가다/일어나다). В случае последнего вообще может не включить в разбор -었/았Отделяет -었/았 + 다 кроме случаев, когда форма второй основы совпадает с первой (가다/일어나다). В случае последнего дефолтно отделяет -었Ничего не отделяет
Будущее времяОтделяет показатель причастия будущего времени -(으)ㄹ и разбивает 것이다 = 거 + 시 + 다Отделяет показатель причастия будущего времени -(으)ㄹ и разбивает 것이다 = 거 + 시 + 다Отделяет показатель причастия будущего времени -(으)ㄹ и разбивает 것이다 = 거 + 시 + 다Не отделяет показатель причастия будущего времени -(으)ㄹ, но разбивает 거에요 = 것 + 이다
Повелительное наклонениеОтделяет вместе с соединительной гласной -어/아라Отделяет -어/아라, но в случае, когда вторая основа совпадает с первой (가다/일어나다) может выделитьОтделяет вместе с соединительной гласной -어/아라Ничего не отделяет
Пригласительное наклонениеОтделяет -자Отделяет -자Отделяет -자Ничего не отделяет
Гоноративные глаголы (глаголы вежливости)
1) 잡수시다
2) 주무시다
3) 계시다
4) 드시다
1), 2), 3) — отделяет только 다 как окончание

4) — отделяет гонорифик 시 и верно определяет основу 
2), 3) — отделяет только 다 как окончание

1), 4) — отделяет как окончание целиком 시다 и верно определяет основу 
2), 3) — отделяет только 다 как окончание

1), 4) — отделяет 시 и 다 и неверно определяет основу 드
Ничего не отделяет и относит 3) 계시다 к классу прилагательного
ㅋㅋ (корейское “пхпхпх”), ㅜㅜ (плачущий смайл)существительноеNAEMOKoreanParticle
ПадежиНе всегда распознаёт именительный (집이), не разделяет составные падежи, не распознаёт 하고 как падежНе разделяет составные падежи (께서는, 에게서), распознает 하고 как падежРазделяет некоторые составные падежи (께서는, 에게서), не распознает 하고 как падежНе разделяет составные падежи (께서는, 에게서), распознаёт 하고 как падеж
Уважительный суффикс -님- (부장님)Отделяет от корня и помечает как отдельный суффиксНе отделяет от корняОтделяет от корня и отдельный суффиксНе отделяет от корня
가는데(‘가’, ‘VV’), (‘는데’, ‘EC’)(가’, ‘P’), (‘ㄴ데’, ‘E’)(‘갈’, ‘VV’), (‘는데’, ‘ECD’)(가’, ‘P’), (‘ㄴ데’, ‘E’),
누가(‘누구’, ‘NP’), (‘가’, ‘JKS’)(‘누구’, ‘N’), (‘가’, ‘J’)(‘누’, ‘NNG’), (‘가’, ‘JKS’)(‘누구’, ‘N’), (‘가’, ‘J’)

Все анализаторы различают морфемы причастий прошедшего и настоящего времени и топик, а также морфемы причастий будущего времени и винительный падеж. Все отглагольные падежи (대해서) распознаются как глагольные формы.

Источник: KoNLPy [Электронный ресурс]. URL: https://konlpy.org/en/v0.4.4/api/konlpy.tag/ (дата обращения 30.03.2024).