NLP(Natural Language Processing)
# 판다스 라이브러리 불러오기
import pandas as pd
# konlpy 설치
!pip install konlpy
# 라이브러리 불러오기 (okt라는 형태소 분석기)
import konlpy
from konlpy.tag import Okt
tokenizer = Okt()
# 토큰화 (형태소 단위)
text = "함께 탐험하며 성장하는 AI 학교 AIFFEL"
tokenizer.morphs(text)
# 토큰화 (명사만 추출)
tokenizer.nouns(text)
# 토큰화 (품사 태깅)
tokenizer.pos(text)
- CountVectorizer
- 단어 빈도수 기반 : 문서에 나타난 단어의 빈도수에만 주목
각 문서에서 각 단어가 나타난 빈도를 단어의 인덱스에 매핑하여 행렬을 만듭니다- 가중치 부재 : 모든 단어에 동일한 가중치를 부여합니다.
빈도수만을 고려하므로 문서에서 자주 나타나는 단어들이 중요하다고 가정합니다.- 단어의 빈도수 행렬 생성 : 각 문서에서 단어의 빈도수를 행렬로 표현합니다.
- TfidfVectorizer
- 단어 빈도와 역문서 빈도(TF-IDF) 기반 : 단어의 빈도뿐만 아니라 역문서 빈도도 고려합니다. 역문서 빈도는 특정 단어가 전체 문서에서 얼마나 중요한지를 나타냅니다
- 가중치 부여 : TfidfVectorizer는 단어에 가중치를 부여하여 빈도뿐만 아니라 특정 단어의 문서 전체에서의 중요도도 반영합니다. 자주 나타나는 단어에는 낮은 가중치를, 특이한 단어에는 높은 가중치를 부여합니다.
- 단어의 빈도와 중요도를 고려한 행렬 생성 : 각 문서에서 단어의 빈도와 중요도(TF-IDF 가중치)를 고려하여 행렬을 생성합니다.
단어의 빈도만을 고려하므로, 단어의 중요성이나 문맥을 고려하지 않고 단순한 빈도에 기반한 모델을 사용할 때 적합합니다.
각 단어에 가중치를 부여하여 문맥을 고려한 모델을 사용하고자 할 때 적합합니다.
일반적으로는 TF-IDFVectorizer가 단어의 중요성을 더 잘 반영하는 경향이 있으며, 감정 분석과 같은 텍스트 분류 작업에서는 TF-IDFVectorizer가 더 선호되는 경우가 많습니다
TF가 감정분석에 더 유리하다..
각 문장에서 단어 출현 횟수를 카운팅하는 방법 (BOW, Bag Of Word)
# CountVectorizer
from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer()
# 단어 토큰화 (Okt)
words = tokenizer.morphs(text)
# 데이터 학습
vect.fit(words)
# 학습된 어휘
vect.get_feature_names_out()
# 단어 사전
vect.vocabulary_
# 단어 사전 크기
len(vect.vocabulary_)
# 인코딩(transform)
df_t = vect.transform(words)
# 인코딩된 데이터 Matrix
df_t.toarray()
# 어휘와 피처
import pandas as pd
pd.DataFrame(df_t.toarray(), columns=vect.get_feature_names_out())
# test
test = "AI 공부하며 함께 성장해요!"
# 단어 토큰화 (Okt(형태소분석기)를 tokenizer 안에 저장시켜놓았었음)
> # 라이브러리 불러오기 (okt라는 형태소 분석기)
import konlpy
from konlpy.tag import Okt
tokenizer = Okt()
words = tokenizer.morphs(test)
words
#
test_t = vect.transform(words)
test_t.toarray()
pd.DataFrame(test_t.toarray(), columns=vect.get_feature_names_out())
다른 문서보다 특정 문서에 자주 나타나는 단어에 높은 가중치를 주는 방법
TF-IDF(Term Frequency - Inverse Document Frequency)
#tf-idf
from sklearn.feature_extraction.text import TfidfVectorizer
# tf-idf
vect = TfidfVectorizer() # 변수에 선언
words = tokenizer.morphs(text) # 형태소 분석
vect.fit(words) # 데이터 학습
vect.vocabulary_
vect.transform(words).toarray()
konlpy: 한국어 처리를 위한 형태소 분석기
형태소: 의미를 가지는 요소로서는 더 이상 분석할 수 없는 가장 작은 말의 단위
다의어와 동형어: 특정 단어가 여러 의미를 가지거나 다른 단어와 비슷한 형태를 가지는 경우 감성분석이 어려워집니다.
문맥 파악의 어려움: 단어의 감정은 문맥에 따라 달라질 수 있습니다. 따라서 문맥을 파악하는 것이 중요합니다.
예를 들어, ‘아주 훌륭해요! 물건을 받는 데 5주 걸렸어요.’ 라는 문장에서는 앞뒤 상황을 완전히 이해한 상태에서 문장을 분석하지 않는 한, ‘훌륭’ 이라는 단어를 기준으로 이 평가를 긍정으로 분류하게 됩니다.
데이터의 불균형: 긍정적인 리뷰가 부정적인 리뷰보다 많은 경우나 그 반대의 경우에는 모델이 편향될 수 있습니다.
# 라이브러리 불러오기
import pandas as pd
# 데이터 불러오기
df = pd.read_csv("https://raw.githubusercontent.com/e9t/nsmc/master/ratings_train.txt", sep="\t")
<전처리를 위한 준비작업>
import konlpy
from konlpy.tag import Okt
from sklearn.feature_extraction.text import CountVectorizer
# 데이터 샘플
df.head()
# 데이터 크기
df.shape
# 몇 개가 있는지 타겟 확인 (0:부정, 1:긍정)
df['label'].value_counts()
# 결측치: (결과값에서) document 값이 결측지
df.isnull().sum()
# 결측치 삭제
print(df.shape)
df = df.dropna()
print(df.shape)
# 피처 엔지니어링 (문장의 길이를 보여줌)
df['len'] = df['document'].apply(len) # len 이라는 피처를 만듦. document 기반
df.head()
# 이제 위 결과에서 긍/부정 따로 시각화하여 보여주는 작업
# len 시각화 (label == 0)
import matplotlib.pyplot as plt
df[df.label==0]['len'].plot(kind='hist')
# len 시각화 (label == 1)
df[df.label==1]['len'].plot(kind='hist')
# 데이터 샘플링 (1000개의 데이터로 축소=샘플링)
df = df[:1000]
# 토큰화(작은단위로 텍스트 나눔), 인코딩(토큰을 컴퓨터가 이해하는 형태로 변환)
vect = CountVectorizer(tokenizer=tokenizer.morphs)
vectors = vect.fit_transform(df['document'])
ㄴ토큰화작업은 이미 tokenizer 안에 okt 를 저장시켜놓았었음
라이브러리 불러오기 (okt라는 형태소 분석기)
import konlpy
from konlpy.tag import Okt
tokenizer = Okt()
(지도학습(분류) 노드의 5-5. 교차검증, 5-6. 평가(분류) 스텝에서 복습가능)
- 데이터를 K 등분한다. (이미지의 경우 K=5)
- 1/5 를 검증데이터로, 나머지 4/5 를 학습 데이터로
- 1/5 를 검증데이터를 바꾸며 성능 평가
- -> 총 5개의 성능 결과가 나올 것이다. 이 5개의 평균을 해당 학습 모델의 성능이라 한다.
분류모델 지도학습을 할때 보았던 방법으로서 머신 러닝 모델의 성능을 평가하는 기법 중 하나
모델의 일반화 성능을 평가하고 모델이 새로운 데이터에 얼마나 잘 일반화될 수 있는지를 확인하는 데 사용
일반적으로 모델을 학습시킬 때 데이터를 train set과 test set으로 나누어 train set을 가지고 학습을 수행합니다.
교차검증이란 여기서 train set을 다시 train set과 validation set으로 나누어 학습 중 검증과 수정을 수행하는 것을 의미합니다.
가장 일반적인 교차검증 방법 중 하나는 K-폴드 교차검증(K-fold cross-validation)입니다. 이 방법은 데이터를 K개의 폴드(부분 집합)로 나눈 뒤, K번의 반복을 거쳐 각각의 폴드를 테스트 세트로 사용하고 나머지 폴드를 훈련 세트로 사용하여 모델을 평가합니다. 마지막으로 이 K번의 평가를 평균하여 최종 성능을 측정합니다.
분류 모델의 평가 지표 중 하나로, 정밀도(precision)와 재현율(recall)의 조화평균을 나타냅니다.
정밀도(Precision): 모델이 양성으로 예측한 것 중에서 실제로 양성인 비율을 의미합니다. 정밀도는 거짓 양성(FP)을 줄이는 것에 초점을 맞춥니다.
재현율(Recall): 실제 양성 중에서 모델이 양성으로 예측한 것의 비율을 말합니다. 재현율은 거짓 음성(FN)을 줄이는 것에 초점을 맞춥니다.
F1 점수는 모델이 양성 클래스를 얼마나 정확하게 식별하는지에 대한 정보를 제공하며, 불균형한 클래스 크기나 데이터 불균형 상황에서 모델의 성능을 정확하게 평가하는 데 유용합니다.
높은 F1 점수는 정확도와 재현율이 모두 높은 경우를 의미하며, 이는 모델이 양성 클래스를 정확하게 식별하면서도 거짓 양성과 거짓 음성을 최소화한다는 것을 나타냅니다.
# 머신러닝
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
model = RandomForestClassifier(random_state=2022)
cross_val_score(model, vectors, df['label'], scoring='f1', cv=5).mean() # 5개로 나눔
자연어 전처리는 자연어 처리(Natural Language Processing, NLP) 작업을 수행하기 전에 텍스트 데이터를 정리하고 구조화하는 과정입니다. 표준화(데이터를 일관된 형식으로 전처리) 및 하기 이유들로 필요합니다.
00% 이상 나타나는 단어 무시
최소 N개의 문장에만 나타나는 단어만 유지
→ 전체 문서 집합에서 가장 높은 빈도를 가진 10개의 단어를 무시하도록 하는 것.
→ 모델의 일반화 능력을 향상시킴
# 토큰화
vect = CountVectorizer(tokenizer = tokenizer.morphs, max_df=10)
vectors = vect.fit_transform(df['document'])
# 머신러닝
model = RandomForestClassifier(random_state=2022)
cross_val_score(model, vectors, df['label'], scoring='accuracy', cv=5).mean()
최소 N개의 문장에만 나타나는 단어만 유지
→ 모델에 대한 통계적으로 유의미하지 않을 수 있는 경우를 필터링
# 토큰화
vect = CountVectorizer(tokenizer = tokenizer.morphs, min_df=2)
vectors = vect.fit_transform(df['document'])
# 머신러닝
model = RandomForestClassifier(random_state=2022)
cross_val_score(model, vectors, df['label'], scoring='accuracy', cv=5).mean()
큰 의미가 없는 단어
예) 을, 는, 이, 가, 여기, 저기
pycospacing 모듈 사용
링크텍스트
ignore 옵션
pre (Prefix) : 문장의 앞 부분에서만 띄어쓰기 교정을 수행하고, 나머지 부분은 무시
spacing("친구와함께bmw썬바이저를썼다.", ignore='pre')
"친구와 함께bmw 썬바이저를 썼다."
pre2 (Prefix2) : pre와 비슷하지만, 문장 앞부분 뿐만 아니라 앞에서 두 번째까지의 부분에서만 띄어쓰기 교정
spacing("친구와함께bmw썬바이저를썼다.", ignore='pre2')
"친구와 함께 bmw 썬바이저를 썼다."
post (Postfix) : 문장의 뒷 부분에서만 띄어쓰기 교정을 수행하고, 나머지 부분은 무시
spacing("친구와함께bmw썬바이저를썼다.", ignore='post')
"친구와 함께 bm w 썬바이저를 썼다."
none : 모든 부분에서 띄어쓰기 교정을 수행
spacing("친구와함께bmw썬바이저를썼다.", ignore='none')
"친구와 함께 bm w 썬바이저를 썼다.
hanspell 모듈로 부산대학교 맞춤법 검사기 API 사용
# 토큰화(max_df) N개 보다 큰 단어 수 무시
vect = CountVectorizer(tokenizer=tokenizer.morphs, max_df=10)
vectors = vect.fit_transform(df['document'])
model = RandomForestClassifier(random_state=2022)
cross_val_score(model, vectors, df['label'], scoring='accuracy', cv=5).mean()
# 토큰화(min_df) N개 보다 작은 단어 수 무시
vect = CountVectorizer(tokenizer=tokenizer.morphs, min_df=2)
vectors = vect.fit_transform(df['document'])
model = RandomForestClassifier(random_state=2022)
cross_val_score(model, vectors, df['label'], scoring='accuracy', cv=5).mean()
# stop_words
stop_words = ['에서','해요']
vect = CountVectorizer(stop_words=stop_words)
words = tokenizer.morphs(text)
vect.fit(words)
vect.vocabulary_
더 자세히: https://github.com/haven-jeon/PyKoSpacing
py-hanspell 설치
!pip install git+https://github.com/jungin500/py-hanspell
!pip install git+https://github.com/ssut/py-hanspell.git
# Spacing 설치
!pip install git+https://github.com/haven-jeon/PyKoSpacing.git
# 띄어쓰기
from pykospacing import Spacing
spacing = Spacing()
text = "함께탐험하며성장하는AI학교아이펠"
spacing_test = spacing(text)
print(text)
print(spacing_test)
더 자세히: https://github.com/lovit/soynlp
# soynlp 설치
!pip install soynlp
# 댓글 데이터에 등장하는 반복되는 이모티콘의 정리
from soynlp.normalizer import *
emoticon_normalize('하하하하ㅋㅋㅋㅋㅋㅠㅠㅠㅠㅠㅠ', num_repeats=3)
더 자세히: https://github.com/ssut/py-hanspell
# py-hanspell 설치
!pip install git+https://github.com/ssut/py-hanspell.git
# 맞춤법 검사
from hanspell import spell_checker
text = '알파고 이전, 2015년부터 만들 어진 최초의AI 커뮤니티 모두의연구소.학연, 지연, 모두연이라는 말이나올만큼 AI의 보금자리로서 중요한 역할을 하고있는 모두의연구소에서 만들었습니다. AI기술을 커뮤니티로 배우는 유일 한 기관 아이펠과 함께 밝은 미래를 만들어보세요.'
result = spell_checker.check(text)
result.as_dict()
# 수정된 문장 확인
result.checked