정규표현식
- 정규표현식(regularexpression)또는정규식은특정한규칙을가진문자열의집합을의미
- 주로패턴(pattern)으로부르는정규표현식은특정목적을위해필요한문자열집합을지정하기위해쓰이는식
ASCII | 설명 |
[A-Za-z0-9] | 영숫자 |
[A-Za-z0-9_] | 영숫자+"_" |
[^A-Za-z0-9_] | 낱말이아닌문자 |
[A-Za-z] | 알파벳문자 |
[\t] | 공백과탭 |
(?<=\W)(?=\w)|(?<=\w)(?=\ W) | 낱말경계 |
[0-9] | 숫자 |
[^0-9] | 숫자가아닌문자 |
[\x21-\x7E] | 보이는문자 |
[a-z] | 소문자 |
[\x20-\x7E] | 보이는문자및공백문자 |
[\t\r\n\v\f] | 공백문자 |
[^\t\r\n\v\f] | 공백이아닌모든문자 |
[A-Z] | 대문자 |
[A-Fa-f0-9] | 16진수 |
텍스트 분석과 자연어처리
Q 왜 fit은 train 에만 해줄까요? 어떤 대회는 test 를 함께 fit하는 것을 금지하고 있기도 합니다
test 는 현실 데이터는 알 수 없기 때문에
기준을 train 으로 해주어야 test도 같은 방법으로 전처리 할 수 있습니다.
train, test 각각 fit을 하게 되면 다른 기준으로 전처리 하게 됩니다.
텍스트 데이터를 각각 fit을 하게 되면 다른 단어사전으로 전처리 되어 기준이 다르게 됩니다.
- TF(단어빈도)
- 특정한 단어가 문서내에 얼마나 자주 등장하는지를 나타내는 값
- 이 값이 높을수록 문서에서 중요하다고 생각할 수 있지만 단어자체가문서군 내에서 자주 사용되는 경우,그 단어가 흔하게 등장한다는 의미
TF | (Term Frequency, 단어 빈도) |
|
|
DF | (Document Frequency, 문서 빈도) |
|
|
IDF | (Inverse Document Frequency, 역문서 빈도) |
|
|
TF-IDF | TF와 IDF를 곱한값 |
|
scikit-learn feature_extraction API
DictVectorizer -링크
특성-값 매핑 목록을 벡터로 변환
- Parameters
- dtype
- 특성 값의 유형
- Numpy 배열/scipy.sparse 행렬 생성자에 dtype 인수로 전달
- separator
- 원핫 인코딩을 위한 새로운 기능을 구성할 때 사용되는 구분자 문자열
- sparse
- 변환이 scipy.sparse 행렬을 생성해야 하는지 여부
- sort
- feature_names_와 vocabulary_를 학습할 때 정렬 여부
- dtype
HashingVectorizer -공식 문서
- 텍스트 문서 모음을 토큰 발생 매트릭스로 변환
- 해시 함수를 사용하여 단어에 대한 인덱스 번호를 생성하기 때문에 메모리 및 실행 시간 감소
- CountVectorizer는 모든 작업을 메모리 상에서 수행해 문서가 너무 크다면 실행이 불가능
TfidTransformer - 공식 문서
- 카운트 행렬을 정규화된 tf 또는 tf-idf 표현으로 변환
TfidVectorizer - 공식 문서
- 문서 모음을 TF-IDF 기능의 매트릭스로 변환
- 단어를 개수 그대로 카운트하지 않고 모든 문서에 공통적으로 들어있는 단어의 경우 가중치를 축소하는 방법
from sklearn.feature_extraction.text import TfidVectorizer
tfidf = TfidVectorizer(analyzer="word", max_df=1.0, min_df=1, ngram_range=(1, 1))
tf_wv = tfidf.fit_transform(document)
pd.DataFrame(tf_wv.toarray(), columns=tfidf.get_feature_names_out())
- norm='l2' 각 문서의 피처 벡터 정규화 방법
- L2 : 벡터의 각 원소의 제곱의 합이 1이 되도록 만드는 것이고 기본 값
- L1 : 벡터의 각 원소의 절댓값의 합이 1이 되도록 크기를 조절
- smooth_idf=False
- 피처를 만들 때 0으로 나오는 항목에 대해 작은 값을 더해서(스무딩을 해서) 피처를 만들지 아니면 그냥 생성할지를 결정
- sublinear_tf=False
- use_idf=True
- TF-IDF를 사용해 피처를 만들 것인지 아니면 단어 빈도 자체를 사용할 것인지 여부
요약
feature_extraction.DictVectorizer() | 특성-값 매핑 목록을 벡터로 변환 |
feature_extraction.text.CountVectorizer() | 텍스트 문서 모음을 토큰 수의 행렬로 변환 |
feature_extraction.text.HashingVectorizer() | 텍스트 문서 모음을 토큰 발생 매트릭스로 변환 |
feature_extraction.text.TfidTransformer() | 카운트 행렬을 정규화된 tf 또는 tf-idf 로 변환 |
feature_extraction.text.TfidVectorizer() | 문서 모음을 tf-idf 매트릭스로 변환 |
시연파일 1101
- 이미지를 다룰 때는 돈을 쓰지 않고 모델을 내 컴퓨터에서 돌리기 위해 이미지 사이즈, 레이어 개수 등을 조정했습니다.
- 텍스트 데이터에서 내 컴퓨터가 힘들어 한다면 여러 방법을 사용할 수 있는데 가장 간단한 방법이 max_features 를 작게 조정하는 것입니다.
- 비지도학습의 차원축소를 사용하게 되면 데이터를 압축해서 사용할 수도 있습니다.
- 그런데 차원축소 과정에서도 메모리 오류가 발생할 수도 있는데 그럴 때 max_features 를 내 컴퓨터가 계산할 사이즈로 적당하게 조정해 주면 로컬 PC로도 어느정도 돌려볼 수 있습니다.
- 여기에서 조금 더 조정한다면 min_df, max_df, stop_words 등을 조정해 볼 수 있습니다.
- 영어나 다른 많이 사용되는 언어는 불용어가 NLTK, Spacy 와 같은 도구에서 목록을 제공하고 있지만 한국어는 제공하지 않습니다.
- 한국어 전처리 도구에도 띄어쓰기, 맞춤법 검사 등의 다양한 API가 있습니다.
해당 실습에대한 참고하면 좋은 영상
1102(분류 모델)
레이블링 하는 법
- 코로나가 들어가면 보건, 안 들어가면 교통
df.loc[df['문서'].str.contains('코로나'), '분류'] = '보건'
df.loc[~df['문서'].str.contains('코로나'), '분류'] = '교통'
- 여러가지 방법으로 데이터셋 나누기
# 방법 1
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.2, random_state=42, stratify=y)
X_train.shape, X_test.shape, y_train.shape, y_test.shape
>> ((6, 16), (2, 16), (6,), (2,))
# 방법 2
X_train = X.sample(frac=0.8, random_state=42)
y_train = y[X_train.index]
X_test = X.drop(index=X_train.index)
y_test = y[X_test.index]
# 균형있게 나누기가 쉽지 않음
3번 방법
split_count = int(X.shape[0] * 0.8)
X_train = X[:split_count]
y_train = y[:split_count]
X_test = X.drop(X_train.index)
y_test = y[X_test.index]
데이터가 균형있게 나뉘어졌는지 확인해야 함
1103
- 데이터 로드
- 코랩에서 실습 시 아래 함수 실행을 통해 다운로드 가능
# 데이콘의 해당 데이터셋은 CC-BY-4.0 라이센스입니다. # 데이터 출처 : <https://dacon.io/competitions/official/235747/data> # 로컬 PC에서 실습 시 직접 데이콘 사이트에 회원가입하고 다운로드 해주세요. import os, platform base_path = "data/klue/" def file_exist_check(base_path): if os.path.exists(f"{base_path}train_data.csv"): print(f"{base_path} 경로에 파일이 이미 있음") return if platform.system() == "Linux": print(f"파일을 다운로드 하고 {base_path} 경로에 압축을 해제함") !wget <https://bit.ly/dacon-klue-open-zip> if not os.path.exists(base_path): os.makedirs(base_path) !unzip dacon-klue-open-zip -d data/klue else: print(f"""<https://dacon.io/competitions/official/235747/data> 에서 다운로드 하고 실습 경로 {base_path}에 옮겨주세요.""") return file_exist_check(base_path)
train = pd.read_csv(f"{base_path}train_data.csv", index_col="index") test = pd.read_csv(f"{base_path}test_data.csv", index_col="index")
파생변수 만들기
df["len"] = df['title'].map(lambda x:len(x))
문장 길이 세기
df["word_count"] = df["title"].map(lambda x: len(x.split()))
공백 기준 단어 수
# 형태소 분석기를 사용하면 단어의 수를 셀 때 중복을 더 제거할 수 있지만 # 여기에서는 우선 띄어쓰기 기준으로
df["unique_word_count"] = df["title"].map(lambda x: len(set(x.split())))
중복 제외 단어 수
문자 전처리
숫자 제거
- map, 정규표현식의 re.sub 을 통해 숫자 제거
import re
df["title"].map(lambda x : re.sub("[0-9]", "", x))
- 판다스 str.replace 기능을 통해 제거
df["title"].str.replace("[0-9]", "", regex=True)
특수문자 제거
- 특수 문자 사용시 정규표현식에서 메타 문자로 특별한 의미를 갖기 때문에 역슬래시를 통해 예외처리(escape)를 해주어야 함
- 특수문자 제거 시 구두점 참고
- string 라이브러리의 string.punctuation
# 특수 문자 제거 시 구두점 참고
import string
punct = string.punctuation
punct
>> !"#$%&\\\\'()*+,-./:;<=>?@[\\\\\\\\]^_`{|}~
# 특수 문자 사용시 정규표현식에서 메타 문자로 특별한 의미를 갖기 때문에 역슬래시를 통해 예외처리
# [!\\\\"\\\\$\\\\*] 일부 특수문자 제거 연습
df["title"] = df["title"].str.replace("[!\\\\"\\\\$\\\\*]", "", regex=True)
대문자 -> 소문자 변경
- 대소문자를 다른 문자로 보기 때문에 하나로 처리하기 위해
df["title"].str.lower()
한글, 영문과 공백만 남기고 모두 제거
df["title"].str.replace("[^ㄱ-ㅎㅏ-ㅣ가-힣 a-zA-Z]", "", regex=True)
[^ㄱ-ㅎㅏ-ㅣ가-힣 a-zA-Z] -> 을 사용하면 한글 공백 영문자만 제거
[^ㄱ-ㅎㅏ-ㅣ가-힣 ] -> 을 사용하면 한글 공백만 제거
[^ㄱ-ㅎㅏ-ㅣ가-힣] -> 을 사용하면 한글만 제거
공백 여러 개는 하나로 처리
df["title"].str.replace("[\\\\s]+", " ", regex=True)
\는 escape 처리해줄 수 있음, 특수기호의 의미를 살려주기 위한 escape 처리 기호이다.
이를 이용해서 중복되는 문자열을 하나로 처리할 수 있음
#EX
re.sub("[ㅋ]+", "ㅋ", "ㅋㅋㅋㅋㅋ")
불용어 제거
1번 방법:
df["title"].map(lambda x: remove_stopwords(x))
2번 방법:
df['title'].map(remove_stopwords)
워드클라우드
- 워드클라우드로 만들기 위해 시리즈 형태에서 하나의 문장으로 만들어줘야 함
"".join(df['title'])
- content를 위에서 만든 함수인 display_word_cloud로 워드클라우드를 시각화
display_word_cloud(' '.join(df['title']))
모든 기사 가져오기
하나의 기사만 가져오기
# join()을 이용하여 변수 title 리스트에서 문자열로 변환해 줍니다.
# content
display_word_cloud(df.loc[0, "title"])
특정 주제 가져오기
display_word_cloud(' '.join(df.loc[df['topic']== '세계', 'title']))
display_word_cloud(' '.join(df.loc[df['topic']=='정치', 'title']))
오답노트
TF-IDF는
단어 빈도를 의미하는 값인 TF와 역문서 빈도를 의미하는 IDF를 곱한 값이다.
문서 단어 행렬(DTM:Document-Term Matrix-다수의 문서에서 등장하는 각 단어들의 빈도를 행렬로 표현한 것) 내의 각 단어들마다 중요한 정도를 가중치로 주는 방법입니다.
이것은 모든 문서에서 자주 등장하는 단어는 중요도가 낮다고 판단하며, 특정 문서에만 자주 등장하는 단어는 중요도가 높다고 판단합니다.
따라서, TF-IDF 값이 낮으면 중요도가 낮고, TF-IDF 값이 높으면 중요도가 높습니다.
ngram_range
- (min_n, max_n) 튜플 값으로 설정할 수 있다.
- n-그램 범위를 나타내는 값이다.
- 한국어의 경우, 최솟값을 2이상으로 설정시 한글자 단어들이 누락될 수 있는 위험성이 있다.
- 기본값은 (1, 1)이다.
max_features
- 벡터라이저가 학습할 기능(어휘)의 양 제한한다.
- 포함시킬 최대(max)의 단어(feature) 수로 빈도수가 가장 높은 순으로 추출한다.
- 기본값은 None이며, 정수로 설정할 수 있다.
- 벡터의 shape가 (3, 15)인 데이터를 max_features=10으로 적용후 벡터의 shape를 확인하면 ( 3, 10 )으로 나타난다.
세로인 컬럼이 줄어야한다! 또한 max_features=10는 맥스값이 10개
참고자료 :
멋쟁이 사자처럼 AI School 7기 수업내용
'TIL > 딥러닝' 카테고리의 다른 글
12/15 목 NLP LSTM (0) | 2022.12.19 |
---|---|
(Stop Words,TF-IDF ,Bag of Words 방식과 시퀀스 방식, RNN과 LSTM) (1) | 2022.12.18 |
12월 12일 NLP BOW TF-IDF (0) | 2022.12.13 |
12월 6일 딥러닝 말라리아 CNN 분류 , cnn개념 용어 정리 !!! (1) | 2022.12.08 |
12월 5일 딥러닝 CNN 기초 (0) | 2022.12.06 |
댓글