2025. 1. 23. 17:39ㆍ자연어 처리/자연어 처리
1. 자연어
* 자연어는 인간이 일상적으로 의사소통에 사용하는 언어로, 말과 글을 통해 표현되는 언어를 말합니다.
* 자연어는 문법, 어휘, 맥락, 뉘앙스 등 복잡한 요소들로 이루어져 있어 규칙적인 구조와 함께 다양한 변형이 가능합니다.
* 컴퓨터 과학에서는 이러한 자연어를 이해하고 처리하기 위해 자연어 처리(NLP, Natural Language Processing) 기술이 사용되며, 이를 통해 텍스트 분석, 번역, 음성 인식, 챗봇과 같은 다양한 응용이 가능합니다.
* 자연어는 인간의 사고와 문화적 배경을 반영하므로, 이를 다루는 기술은 인문학적 이해와 기술적 접근이 결합되어야 합니다.
2. 자연어 처리
* 자연어 처리는(Natural Language Processing, NLP) 컴퓨터가 인간의 언어를 이해하고 처리하며 생성할 수 있도록 돕는 인공지능 기술 분야입니다.
* 이를 통해 텍스트나 음성 데이터를 분석하고, 번역, 요약, 감정 분석, 질의응답, 음성인식 등 다양한 작업을 수행할 수 있습니다.
* 자연어 처리는 언어학, 컴퓨터 과학, 인공지능의 융합으로 이루어지며, 형태소 분석, 구문 분석, 의미 분석 등 여러 단계를 포함합니다.
* 최근에는 딥러닝 기술과 대규모 언어 모델의 발전으로 자연어 처리 성능이 크게 향상되어 챗봇, 검색 엔진, 추천 시스템과 같은 실생활 응용에서 널리 사용되고 있습니다.
3. 한국어 자연어 처리
* 한국어의 고유한 언어적 특성과 구조적인 복잡성 때문에 한국어 자연어 처리가 영어보다 어렵습니다.
3-1. 교착어의 특성:
* 한국어는 어미와 접사가 붙는 교착어로, 하나의 단어에 여러 문법적 정보가 포함됩니다.
* 예를 들어, "가다"라는 기본 동사에 "갔습니다", "가겠다", "가더라"처럼 다양한 어미가 붙어 형태가 복잡하게 변화합니다. 이는 형태소 분석을 어렵게 만듭니다.
3-2. 어순의 유연성:
* 한국어는 주어-목적어-동사(SOV) 구조를 기본으로 하지만, 어순이 비교적 자유로워 맥락에 따라 문장이 달라질 수 있습니다. 이는 문장의 구문 분석을 어렵게 합니다.
* 나는 운동을 했어. 체육관에서
* 나는 체육관에서 운동을 했어
* 체육관에서 나는 운동을 했어
* 나는 운동을 체육관에서 했어
3-3. 단어 경계가 모호함:
* 영어는 공백으로 단어를 구분하지만, 한국어는 조사와 어미가 붙어 단어 경계가 명확하지 않은 경우가 많아 단어를 분리하는 작업(형태소 분석)이 까다롭습니다.
* 한국어는 띄어쓰기를 하지 않아도 쉽게 읽을 수 있습니다.
* 제가이렇게띄어쓰기를전혀하지않고글을썼다고하더라도글을쉽게이해할수있습니다.
3-4. 높임말과 다양한 표현 방식:
* 한국어에는 다양한 높임말과 경어체가 있어, 같은 의미를 여러 방식으로 표현할 수 있습니다.
* 예를 들어, "먹다"는 "드시다", "잡수시다" 등으로 변화하며, 이러한 다양성을 처리하기 위해 추가적인 맥락 분석이 필요합니다.
3-5. 어휘적 중의성:
* 한국어는 같은 발음이나 형태를 가진 단어가 여러 의미를 가지는 경우가 많아, 문맥에 따른 의미 해석이 어렵습니다.
* 예를 들어, "배"는 '사람의 배', '배(船)', '배(梨)' 등 다양한 의미를 가집니다.
4. 토큰화
* 토큰화(Tokenization)는 텍스트 데이터를 분석하거나 처리하기 위해 문장을 의미 있는 단위로 나누는 과정입니다.
* 이 단위는 단어, 어절, 형태소, 또는 문자 단위일 수 있으며, 자연어 처리(NLP)의 기초 단계로 매우 중요한 역할을 합니다.
* 예를 들어, 영어에서는 공백이나 구두점을 기준으로 단어를 나누는 것이 일반적이지만, 한국어나 일본어처럼 공백이 명확하지 않은 언어에서는 형태소 분석기를 사용하여 어절이나 형태소 단위로 나누는 작업이 필요합니다.
4-1. 문장 토큰화
* 문장 토큰화는 텍스트를 문장 단위로 나누는 과정입니다.
* 일반적으로 마침표(.), 물음표(?), 느낌표(!)와 같은 문장 부호를 기준으로 문장을 구분합니다.
* 예를 들어, "안녕하세요. 오늘 날씨가 좋네요!"라는 문장은 "안녕하세요."와 "오늘 날씨가 좋네요!"로 나눌 수 있습니다.
* 하지만 약어(예: "Dr.", "Mr.")나 숫자(예: "3.14")처럼 마침표를 포함하지만 문장 경계가 아닌 경우를 처리해야 하므로 복잡한 규칙이나 모델이 필요합니다.
* 문장 토큰화는 문서 요약, 감정 분석, 번역 등의 작업에서 중요한 역할을 합니다. (한국어에서의 문장 토크나이저로 'KSS'를 추천)
* 링크 주소 : https://github.com/hyunwoongko/kss
예시 1)
sentence = 'Yonsei University is a private research university in Seoul, South Korea. Yonsei University is deemed as one of the three most prestigious institutions in the country. It is particularly respected in the studies of medicine and business administration.'
# 주어진 문장(sentence)을 정의합니다.
# 이는 연세대학교와 관련된 정보를 포함하는 문자열입니다.
sentence.split('. ')
# 문자열을 '. ' (마침표와 공백) 기준으로 나눕니다.
# 이 함수는 문자열을 특정 기준으로 나누어 리스트 형태로 반환합니다.
# 결과적으로 문장이 개별적으로 리스트에 저장됩니다.
--->
['Yonsei University is a private research university in Seoul, South Korea',
'Yonsei University is deemed as one of the three most prestigious institutions in the country',
'It is particularly respected in the studies of medicine and business administration.']
예시 2)
import nltk
# nltk(Natural Language Toolkit) 라이브러리를 가져옵니다.
# nltk는 자연어 처리를 위한 다양한 기능과 데이터를 제공하는 라이브러리입니다.
nltk.download('punkt_tab')
# nltk의 'punkt_tab' 데이터를 다운로드합니다.
# 'punkt_tab'은 NLTK에서 문장이나 단어를 토큰화(나누기)할 때 사용하는 특정 데이터입니다.
# 'punkt'는 문장을 나누는 데 쓰이는 구두점 기반의 토크나이저(tokenizer)이며,
# 여기서 'punkt_tab'은 관련된 추가 데이터입니다.
--->
[nltk_data] Downloading package punkt_tab to /root/nltk_data...
[nltk_data] Unzipping tokenizers/punkt_tab.zip.
True
예시 3)
import nltk # NLTK(Natural Language Toolkit)는 자연어 처리 라이브러리입니다.
# from nltk.tokenize import sent_tokenize, punkt_tab
# 위 코드에서 sent_tokenize는 문장을 분리(토큰화)하는 함수입니다. punkt_tab은 내부적으로 사용되는 데이터입니다.
sentence = "His barber kept his word. But keeping such a huge secret to himself was driving him crazy. Finally, the barber went up a mountain and almost to the edge of a cliff. He dug a hole in the midst of some reeds. He looked about, to mae sure no one was near."
# 분석할 문장을 하나의 문자열로 정의합니다.
print(sent_tokenize(sentence))
# 문장을 토큰화하여 분리한 결과를 출력합니다.
sentence = "I am actively looking for Ph.D. students. and you are a Ph.D student."
# 또 다른 문장을 정의합니다.
print(sent_tokenize(sentence))
# 이 문장도 마찬가지로 문장을 토큰화하여 분리한 결과를 출력합니다.
--->
['His barber kept his word.', 'But keeping such a huge secret to himself was driving him crazy.', 'Finally, the barber went up a mountain and almost to the edge of a cliff.', 'He dug a hole in the midst of some reeds.', 'He looked about, to mae sure no one was near.']
['I am actively looking for Ph.D. students.', 'and you are a Ph.D student.']
예시 4)
!pip install kss #kss 설치
예시 5)
import kss # kss(Korean Sentence Splitter)는 한국어 문장을 자연스럽게 분리해주는 라이브러리입니다.
text = '딥 러닝 자연어 처리가 재미있기는 합니다. 그런데 문제는 영어보다 한국어로 할 때 너무 어려워요. 이제 해보면 알걸요?'
# 분석할 한국어 문장을 정의합니다.
print(kss.split_sentences(text))
# kss.split_sentences() 함수를 사용하여 문장을 분리하고, 그 결과를 출력합니다.
--->
['딥 러닝 자연어 처리가 재미있기는 합니다.', '그런데 문제는 영어보다 한국어로 할 때 너무 어려워요.', '이제 해보면 알걸요?']
4-2. 단어 토큰화
* 단어 토큰화는 문장을 단어 또는 어절 단위로 나누는 과정입니다.
* 영어와 같이 공백이 단어 경계를 나타내는 언어에서는 비교적 간단히 처리할 수 있지만, 한국어나 일본어처럼 단어 간 경계가 명확하지 않은 언어에서는 형태소 분석기를 사용해야 합니다.
* 예를 들어, "나는 학교에 간다"를 단어 토큰화하면 ["나", "는", "학교", "에", "간다"]와 같이 나눌 수 있습니다.
* 또한, "preprocessing" 같은 단어를 다룰 때 서브워드 토큰화를 사용해 "pre", "process", "ing"로 나누기도 합니다.
* 단어 토큰화는 텍스트를 수치화하거나 분석하기 위한 기초 단계로 사용됩니다.
예시 1)
# NTLK는 영어 자연어 처리를 위한 패키지
# 영어로 토큰화를 할 때는 일반적으로 NLTK라는 패키지를 사용
import nltk
nltk.download('punkt')
nltk.download('punkt_tab') # 확장 데이터
print(nltk.data.path) #nltk 설치 경로 폴더
### Punkt Tokenizer
* Punkt Tokenizer는 문장 토큰화(Sentence Tokenization)와 단어 토큰화(Word Tokenization)를 수행하는 데 사용됩니다.
* 이 모델은 언어 독립적인 방식으로 설계되었으며, 구두점과 텍스트 패턴을 기반으로 문장을 구분하거나 단어를 추출합니다.
예시 1)
from nltk.tokenize import word_tokenize # NLTK에서 제공하는 단어 토큰화 함수입니다.
sentence = "Don't be fooled by the dark sounding name, Mr. Jone's Orphanage is as cheery as cheery goes for a pastry shop."
# 분석할 문장을 정의합니다.
print(word_tokenize(sentence))
# word_tokenize 함수를 사용하여 문장을 단어 단위로 분리하고 결과를 출력합니다.
-->
['Do', "n't", 'be', 'fooled', 'by', 'the', 'dark', 'sounding', 'name', ',', 'Mr.', 'Jone', "'s", 'Orphanage', 'is', 'as', 'cheery', 'as', 'cheery', 'goes', 'for', 'a', 'pastry', 'shop', '.']
예시 2)
from nltk.tokenize import WordPunctTokenizer # 단어와 구두점을 분리해주는 토크나이저입니다.
sentence = "Don't be fooled by the dark sounding name, Mr. Jone's Orphanage is as cheery as cheery goes for a pastry shop."
# 분석할 문장을 정의합니다.
print(WordPunctTokenizer().tokenize(sentence))
# WordPunctTokenizer를 사용하여 문장을 단어와 구두점으로 분리한 결과를 출력합니다.
--->
['Don', "'", 't', 'be', 'fooled', 'by', 'the', 'dark', 'sounding', 'name', ',', 'Mr', '.', 'Jone', "'", 's', 'Orphanage', 'is', 'as', 'cheery', 'as', 'cheery', 'goes', 'for', 'a', 'pastry', 'shop', '.']
※ 토큰화 알고리즘
* 영어 토큰화 알고리즘은 축약형과 소유격 규칙을 반영하여 더 나은 텍스트 분석을 위해 설계되었습니다.
* 이를 통해 구문 분석이나 텍스트 처리의 정확성을 높일 수 있습니다.
* 영어의 축약형과 소유격은 문법적으로 의미가 달라서, 이를 명확히 분리하면 자연어 처리(NLP) 작업에 유리합니다.
* 토큰화 알고리즘마다 각자 규칙이 다르기 때문에 사용하고자 하는 목적에 따라 토크나이저를 선택하는 것이 중요합니다.
예시 1)
from nltk.tokenize import word_tokenize # 단어 토큰화를 위한 함수입니다.
sentence = "A Dog Run back corner near spare bedrooms!!!!"
# 분석할 문장을 정의합니다.
print(word_tokenize(sentence))
# word_tokenize를 사용하여 문장을 단어 단위로 분리한 결과를 출력합니다.
print(sentence.split())
# Python의 기본 문자열 split() 메서드를 사용하여 공백을 기준으로 단어를 분리한 결과를 출력합니다.
--->
['A', 'Dog', 'Run', 'back', 'corner', 'near', 'spare', 'bedrooms', '!', '!', '!', '!']
['A', 'Dog', 'Run', 'back', 'corner', 'near', 'spare', 'bedrooms!!!!']
예시 2)
from nltk.tokenize import word_tokenize # 단어 토큰화를 위한 함수입니다.
sentence = "A Dog Run back corner near spare bedrooms... bedrooms!!"
# 분석할 문장을 정의합니다.
print(word_tokenize(sentence))
# word_tokenize를 사용하여 문장을 단어와 기호로 분리한 결과를 출력합니다.
print(sentence.split())
# Python의 기본 split() 메서드를 사용하여 공백 기준으로 단어를 분리한 결과를 출력합니다.
--->
['A', 'Dog', 'Run', 'back', 'corner', 'near', 'spare', 'bedrooms', '...', 'bedrooms', '!', '!']
['A', 'Dog', 'Run', 'back', 'corner', 'near', 'spare', 'bedrooms...', 'bedrooms!!']
예시 3)
if 'bedroom' == 'bedrooms...':
print('이 둘은 같습니다.')
else:
print('이 둘은 다릅니다.')
-->
이 둘은 다릅니다.
예시 4)
'bedrooms...' == 'bedrooms!!'
-->
False
5. 형태소 분석기
* 교착어인 한국어의 특성으로 인해 한국어는 토크나이저로 형태소 분석기를 사용하는 것이 보편적입니다.
* Mecab :
빠르고 정확하며 대규모 데이터 처리에 적합하지만, Windows 설치가 복잡함.
* Kkma :
세밀한 분석과 구문 분석에 유리하지만 속도가 느리고 결과가 복잡함.
* Hannanum :
구문 및 통계 분석을 지원하나 처리 속도가 느리고 오류 가능성이 있음.
* Komoran :
안정적이고 빠르며 사전 확장이 쉬우나 복잡한 문장에서 정확도가 떨어질 수 있음.
* Open Korean Text :
SNS와 비표준 언어 처리에 강하며 빠르지만, 문어체 분석 정확도는 낮음.
* Konlpy :
다양한 분석기를 통합 제공하며 Python 친화적이나 분석기 성능 차이가 있음.
* Khaiii :
Kakao에서 개발한 형태소 분석기로 딥러닝 기반 기술을 사용하여 높은 정확도를 제공. 하지만 속도는 전통적인 분석기보다 느릴 수 있음.
* Soynlp :
사전 없이 비지도 학습 방식으로 토큰화를 수행하며, 신조어 및 형태소 경계 추출에 강점. 그러나 대량 데이터 처리 시 속도가 느릴 수 있음.
예시 1)
kor_text = "사과의 놀라운 효능이라는 글을 봤어. 그래서 오늘 사과를 먹으려고 했는데 사과가 썩어서 슈퍼에 가서 사과랑 오렌지 사왔어"
# 분석할 한국어 텍스트입니다. "사과"라는 단어가 여러 번 등장하며, 조사(의, 를, 가, 랑)가 붙어 있어 각각 다른 단어로 처리될 수 있습니다.
print(kor_text.split())
# split() 메서드는 공백(스페이스)을 기준으로 문자열을 분리합니다.
-->
['사과의', '놀라운', '효능이라는', '글을', '봤어.', '그래서', '오늘', '사과를', '먹으려고', '했는데', '사과가', '썩어서', '슈퍼에', '가서', '사과랑', '오렌지', '사왔어']
예시 2)
'사과' == '사과의'
-->
False
예시 3)
# 영어에 NLTK가 있다면, 한국어에는 형태소 분석기 패키지인 KoNLPy(코엔엘파이)가 있음
# KoNLPy에 다양한 형태소 분석기가 존재
# Mecab 형태소 분석기는 별도 설치를 해주어야 함
!pip install konlpy
예시 4)
# Colab에 Mecab 설치
# 설치 후 [런타임] - [세션 다시 시작 및 모두 실행]을 해야 함
!git clone https://github.com/SOMJANG/Mecab-ko-for-Google-Colab.git
%cd Mecab-ko-for-Google-Colab
!bash install_mecab-ko_on_colab_light_220429.sh
예시 5)
import nltk
nltk.download('punkt')
nltk.download('punkt_tab') # 확장 데이터
print(nltk.data.path) #nltk 설치 경로 폴더
예시 6)
from konlpy.tag import * # KoNLPy 라이브러리에서 다양한 형태소 분석기 모듈을 가져옵니다.
hannanum = Hannanum() # 한나눔 형태소 분석기
kkma = Kkma() # 꼬꼬마 형태소 분석기
komoran = Komoran() # 코모란 형태소 분석기
okt = Okt() # 이전에는 Twitter로 알려졌던 Okt 형태소 분석기
mecab = Mecab() # MeCab 형태소 분석기 (Linux/MacOS에서 주로 사용, Windows에서는 추가 설치 필요)
예시 7)
# nouns : 명사 추출
# morphs : 최소 단위로 문장을 쪼갬
# pos : 형태소로 나누고 각 품사 정보를 태깅
print(okt.nouns("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
print(okt.morphs("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
print(okt.pos("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
#--->
#['코딩', '당신', '연휴', '여행']
#['열심히', '코딩', '한', '당신', ',', '연휴', '에는', '여행', '을', '가봐요']
#[('열심히', 'Adverb'), ('코딩', 'Noun'), ('한', 'Josa'), ('당신', 'Noun'), (',', 'Punctuation'), ('연휴', 'Noun'), ('에는', 'Josa'), ('여행', 'Noun'), ('을', 'Josa'), ('가봐요', 'Verb')]
print(kkma.nouns("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
print(kkma.morphs("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
print(kkma.pos("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
#--->
# ['코딩', '당신', '연휴', '여행']
# ['열심히', '코딩', '하', 'ㄴ', '당신', ',', '연휴', '에', '는', '여행', '을', '가보', '아요']
# [('열심히', 'MAG'), ('코딩', 'NNG'), ('하', 'XSV'), ('ㄴ', 'ETD'), ('당신', 'NP'), (',', 'SP'), ('연휴', 'NNG'), ('에', 'JKM'), ('는', 'JX'), ('여행', 'NNG'), ('을', 'JKO'), ('가보', 'VV'), ('아요', 'EFN')]
print(komoran.nouns("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
print(komoran.morphs("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
print(komoran.pos("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
# -->
# ['코', '당신', '연휴', '여행']
# ['열심히', '코', '딩', '하', 'ㄴ', '당신', ',', '연휴', '에', '는', '여행', '을', '가', '아', '보', '아요']
# [('열심히', 'MAG'), ('코', 'NNG'), ('딩', 'MAG'), ('하', 'XSV'), ('ㄴ', 'ETM'), ('당신', 'NNP'), (',', 'SP'), ('연휴', 'NNG'), ('에', 'JKB'), ('는', 'JX'), ('여행', 'NNG'), ('을', 'JKO'), ('가', 'VV'), ('아', 'EC'), ('보', 'VX'), ('아요', 'EC')
print(hannanum.nouns("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
print(hannanum.morphs("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
print(hannanum.pos("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
# -->
# ['코딩', '당신', '연휴', '여행']
# ['열심히', '코딩', '하', 'ㄴ', '당신', ',', '연휴', '에는', '여행', '을', '가', '아', '보', '아']
# [('열심히', 'M'), ('코딩', 'N'), ('하', 'X'), ('ㄴ', 'E'), ('당신', 'N'), (',', 'S'), ('연휴', 'N'), ('에는', 'J'), ('여행', 'N'), ('을', 'J'), ('가', 'P'), ('아', 'E'), ('보', 'P'), ('아', 'E')]
print(mecab.nouns("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
print(mecab.morphs("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
print(mecab.pos("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
# -->
# ['코딩', '당신', '연휴', '여행']
# ['열심히', '코딩', '한', '당신', ',', '연휴', '에', '는', '여행', '을', '가', '봐요']
# [('열심히', 'MAG'), ('코딩', 'NNG'), ('한', 'XSA+ETM'), ('당신', 'NP'), (',', 'SC'), ('연휴', 'NNG'), ('에', 'JKB'), ('는', 'JX'), ('여행', 'NNG'), ('을', 'JKO'), ('가', 'VV'), ('봐요', 'EC+VX+EC')]
'자연어 처리 > 자연어 처리' 카테고리의 다른 글
3. 벡터화 (0) | 2025.02.03 |
---|---|
2.IMDB Dataset를 활용한 데이터 전처리 (0) | 2025.01.24 |