728x90
SMALL
- 오늘은 어제에 이어서 자연어를 전처리하는 방법 중, 정규 표현식, 인코딩, 패딩, 데이터 분할 방법에 대해서 배워보았습니다.
✍🏻 정규 표현식
- 정규 표현식은 모든 언어에서 공통적으로 사용되고, 쓰임새도 유사하니 익혀두면 추후에도 넓게 사용할 수 있을 것 같습니다.
✨ 기본적인 문법 정리
- 아래 표는 정규 표현식에서 사용되는 문자들인데, 이 기호들을 이용해서 특정 단어들이나 기호 등을 쉽게 표현할 수 있습니다.
특수문자 | 설명 |
. | 임의의 한 문자를 의미합니다. 단, 줄바꿈 문자(\n)는 제외됩니다. |
? | 앞의 문자가 있을 수도, 없을 수도 있음을 나타냅니다 (즉, 0개 또는 1개). |
* | 앞의 문자가 0개 이상, 즉 없어도 되고 무한히 있을 수도 있음을 의미합니다. |
+ | 앞의 문자가 1개 이상 반드시 있어야 함을 의미합니다. |
^ | 이 기호의 뒤의 문자열로 문자열이 시작되어야 합니다. |
$ | 이 기호의 앞에 있는 문자열로 문자열이 끝나야 합니다. |
{숫자} | 정확히 지정한 숫자만큼 반복되는 패턴임을 의미합니다. |
{숫자1, 숫자2} | 최소 숫자1번, 최대 숫자2번 반복됨을 의미합니다. |
{숫자,} | 지정한 숫자 이상 반복되는 패턴임을 의미합니다. |
[ ] | 대괄호 안에 있는 문자들 중 한 개와 일치함을 의미합니다. |
[^문자] | 대괄호 안의 특정 문자를 제외한 모든 문자와 일치함을 의미합니다. |
| | A|B와 같이 쓰이며 A 또는 B의 의미를 가집니다. |
✨ 자주 쓰이는 문자 규칙들
- 또, 정규 표현식에서 특별한 의미를 가지는 몇몇 문자들도 있습니다.
문자 규칙 | 설명 |
\\\ | 역슬래시 자체를 의미합니다. (특수문자를 일반 문자로 사용할 때 씁니다.) |
\\d | 모든 숫자(0-9)와 일치합니다. |
\\D | 숫자가 아닌 모든 문자와 일치합니다. |
\\s | 공백 문자(스페이스, 탭, 줄바꿈 등)와 일치합니다. ([\t\n\r\f\v]) |
\\S | 공백 문자를 제외한 모든 문자와 일치합니다. ([^\t\n\r\f\v]) |
\\w | 알파벳(대문자, 소문자), 숫자, 밑줄(_) 등 '단어'를 구성하는 문자와 일치합니다. ([a-zA-Z0-9]) |
\\W | 알파벳, 숫자, 밑줄이 아닌 모든 문자와 일치합니다. |
✨ 정규 표현식 모듈 함수
- 저희 파이썬의 re 모듈을 사용하면 정규 표현식을 조금 더 쉽게 다룰 수 있습니다!
모듈 함수 | 설명 |
re.compile() | 정규 표현식 패턴을 미리 컴파일해서, 이후 여러 번 사용할 수 있도록 준비합니다. |
re.search() | 문자열 전체를 검색하여, 정규 표현식에 맞는 부분이 있는지 확인합니다. (찾으면 첫 번째 매치 결과를 반환) |
re.match() | 문자열의 시작 부분이 정규 표현식과 일치하는지 검사합니다. |
re.split() | 정규 표현식을 기준으로 문자열을 분리하여, 리스트 형태로 결과를 반환합니다. |
re.findall() | 문자열에서 정규 표현식과 일치하는 모든 부분을 찾아 리스트로 반환합니다. |
re.finditer() | 문자열에서 정규 표현식과 일치하는 모든 부분을 반복 가능한 객체(iterator)로 반환합니다. |
re.sub() | 문자열에서 정규 표현식과 일치하는 부분을 다른 문자열로 대체합니다. |
✨ 기호를 어떻게 표현해야 할까?
- re.compile()에 정규 표현식을 먼저 컴파일하고, re.search()를 통해서 해당 정규 표현식이 입력 텍스트와 매치되는지를 확인합니다.
- 이 re.search()는 매치된다면 Match Object를 반환하고 매치되지 않으면 아무런 값도 출력되지 않습니다.
💡 . 기호
- .은 한 개의 임의의 문자를 나타냅니다.
- 예를 들어서 정규 표현식이 '안.녕'이라면, '안?녕', '안안녕', '안1녕' 등도 다 매치가 됩니다.
💡 ? 기호
- ? 앞의 문자가 존재할 수도 있고 존재하지 않을 수도 있는 경우를 나타낼 때 사용합니다.
- 정규 표현식이 '안?녕'이라면, r.search('녕')도 매치되고, r.search('안녕')도 매치됩니다.
💡 * 기호
- ?는 앞의 하나의 문자만을 의미하지만, *은 다수의 문자를 의미(0개 이상)합니다.
- 정규 표현식이 '안*녕'이라면, '녕', '안녕', '안안녕', '안안안녕', '안????녕' 등이 모두 매치됩니다.
💡 + 기호
- * 기호와 유사하지만, + 기호는 앞의 문자가 최소 1개 이상이 존재해야 합니다.
- 예를 들어서 정규 표현식이 '안+녕'이라면, '녕'은 매치가 안 되지만, '안녕', '안안녕', '안????녕' 등은 모두 매치가 됩니다.
💡 ^ 기호
- 시작되는 문자열을 지정해주는 기호입니다.
- 정규 표현식이 '^안녕'이라면 '안녕', '안녕?', '안녕하세요' 등이 매치될 수 있습니다.
💡 {숫자} 기호
- 문자에 해당 기호를 붙이면, 해당 문자를 숫자만큼 반복한 것을 의미합니다.
- 정규 표현식이 '안{2}녕'이라면, 무조건 '안안녕'만 매치되는 것입니다.
💡 {숫자1,숫자2} 기호
- 해당 문자를 숫자1 이상 숫자2 이하만큼 반복한 것을 의미합니다.
- 정규 표현식이 '안{1,2}녕'이라면, '안녕', '안안녕'만 매치되는 형식입니다.
- {}의 중괄호 안에 ,로 숫자들이 엮여있는데, 사용하실 때에 괄호 안에 공백이 없게 하셔야 합니다!
💡 {숫자,} 기호
- 해당 문자를 숫자 이상만큼 반복한 것을 찾아줍니다.
- 정규 표현식이 '안{1,}녕'이라고 하면, '녕'은 매치가 안 되고, '안녕', '안안녕', '안안안녕' 등은 매치가 됩니다.
🌟 [ ] 기호
- [ ] 안에 문자들을 넣으면 그 문자들 중 한 개의 문자와 매치하라는 의미입니다.
- 범위를 지정하는 것도 가능한데, [a-z], [a-c], [a-zA-Z], [0-9], [가-힣]와 같이 쓸 수 있습니다.
- 대부분의 언어가 이 [ ] 기호를 동일하게 사용한다고 합니다.
🌟 [^문자] 기호
- ^ 기호 뒤에 붙은 문자들을 제외한 모든 문자를 의미합니다.
- 이것도 범위를 지정하는 것이 가능한데, [^abc], [^a-z], [^0-9], [^가-힣]와 같이 사용할 수 있습니다.
✨ 함수는 어떻게 사용해야 할까?
💡 re.match() 와 re.search()의 차이
- search()가 정규 표현식 전체에 대해서 문자열이 매치하는지를 보는 용도라면, match()는 문자열의 첫 부분부터 정규 표현식과 매치하는지를 확인하는 함수입니다.
- 문자열 중간에 찾을 패턴이 있더라도 match() 함수는 문자열의 시작에서 패턴이 일치하지 않으면 더이상 찾지 않게 됩니다.
💡 re.split()
- split() 함수는 입력된 정규 표현식을 기준으로 문자열들을 분리해서 리스트로 반환해주는 친구입니다. (문자열에서의 split()과 유사해요...!)
- 토큰화에서 유용하게 쓰이는 친구이고, 이 함수는 공백을 기준으로 문자열 분리를 수행하고 결과로서 리스트를 반환해줍니다.
- 함수는 보통 re.split(' ', text)과 같이 쓰입니다.
💡 re.findall()
- 정규 표현식과 매치되는 모든 문자열들을 리스트로 반환해주는 역할을 합니다.
- 그렇지만, 매치되는 문자열이 없다면 빈 리스트를 반환합니다.
- 임의의 텍스트에 정규 표현식으로 숫자를 의미하는 규칙(\d)으로 findall()을 수행하면 전체 텍스트로부터 숫자만 찾아내서 리스트로 반환해주는데,
- 만약에 전화번호의 숫자를 찾는다면? re.findall("\d+", text) - ['010', '1234', '1234', '30']처럼 나타나게 됩니다.
💡 re.sub()
- 문자열의 replace()와 동일한 함수이지만, 쓰이는 방식만 살짝 다릅니다.
- 특히 정제 작업에 많이 사용되는데, 영어 문장에 각주 등과 같은 이유로 특수 문자가 섞여있는 경우에
- 이 특수 문자를 제거하고 싶다면, 알파벳 외의 문자는 공백으로 처리하는 등의 용도로 사용됩니다.
- re.sub('[^a-zA-Z]', ' ', text)와 같이 사용될 수 있습니다.
✨ 정규 표현식으로 텍스트 전처리해보기
💡 그 전에! 유용한 표현식 몇 가지
- \s+는 모든 공백을 찾아내는 정규 표현식입니다. 그래서 re.split('\s+', text)를 사용하면 모든 공백을 기준으로 문장들을 쪼개줍니다.
- re.findall('\d+',text)를 사용하면 모든 숫자를 찾아주고, re.findall('[A-Z]{4}',text)는 대문자가 연속적으로 네 번 등장하는 경우를 찾아서 반환해주는 식입니다.
- re.findall('[A-Z][a-z]+',text)과 같은 경우에는 처음이 대문자, 그 뒤는 소문자로 구성된 이름 등을 찾아낼 때 유용하게 쓰일 수 있습니다.
💡 토큰화 작업
- NLTK에서는 정규 표현식을 사용해서 단어 토큰화를 수행하는 RegexpTokenizer를 지원해준답니다.
- RegexpTokenizer() 생성자 안에 하나의 토큰으로 규정하기를 원하는 정규 표현식을 넣어서 토큰화를 수행합니다.
- tokenizer = RegexpTokenizer(r'[\s]+', gaps=True)와 같이 사용해서 공백 기준으로 토큰화할 수 있으며,
- 이때, gaps=True는 해당 정규 표현식을 토큰으로 나누기 위한 기준으로 사용한다는 의미합니다.
- tokenizer = RegexpTokenizer('[\s]+', gaps=True)와 같이 '[\s]+'의 정규 표현식을 사용하게 되는 경우에 SyntaxWarning이 발생하게 된다면,
- 이는 백슬래시(\)를 잘못 처리해서 발생하는 오류이기 때문에 r'[\s]+'와 같이 raw string을 사용하면 해결됩니닷!
⛲ 정수 인코딩
- 컴퓨터는 텍스트보다는 숫자를 더 잘 처리하고, 자연어 처리에서는 텍스트를 숫자로 바꾸는 여러 가지 기법이 존재합니다.
- 그래서 기법들을 본격적으로 적용시키기 위한 첫 단계로 각 단어를 고유한 정수에 맵핑(mapping)시키는 전처리 작업이 필요합니다.
- 이게 어떤 작업이냐면, 갖고 있는 텍스트에 단어가 5000개 있다고 가정했을 때, 5000개의 단어들 각각에 1번부터 5000번까지 단어와 맵핑되는 고유한 정수를 붙이는 작업입니다.
- 다른 표현으로는 인덱스를 부여한다고 보시면 되긴 하는데, 실제 인덱스와는 다른 개념입니다.
- 이 방법은 여러 가지가 있을 수 있는데 랜덤으로 부여하기도 하지만, 보통은 단어 등장 빈도수를 기준으로 정렬한 뒤에 부여하는 편입니다.
✨ 정수 인코딩 방법
- 정수 인코딩은 단어에 정수를 부여하는 방법 중 하나로 단어를 빈도수 순으로 정렬한 단어 집합(vocabulary)을 만들고,
- 빈도수가 높은 순서대로 낮은 숫자부터 정수를 부여하는 방법입니다.
- 그래서 이 작업을 하기 위해 먼저, NLTK 라이브러리에서 문장 토큰화와 불용어 처리를 위한 데이터를 다운로드받고 시작하게 되었습니다.
💡 문장 토큰화하기
- 원시 텍스트(raw_text)를 sent_tokenize()를 사용하여 먼저 문장 단위로 분리해줍니다.
from nltk.tokenize import sent_tokenize
raw_text = ("~~~")
sentences = sent_tokenize(raw_text)
💡 단어 토큰화 및 텍스트 정제해주기
- 각 문장을 단어 단위로 분리한 후, 소문자화, 불용어 제거, 그리고 길이가 2 이하인 단어를 필터링하여 정제했습니다.
- 길이 제한이나 불용어는 때에 따라, 프로젝트의 목적에 따라 다를 수도 있습니다.
- 그리고 그와 동시에 전체 단어의 빈도수를 계산해주었습니다.
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
stop_words = set(stopwords.words('english'))
preprocessed_sentences = [] # 정제된 문장들을 저장할 리스트
vocab = {} # 각 단어의 빈도수를 저장할 딕셔너리
for sentence in sentences:
tokenized_sentence = word_tokenize(sentence)
result = []
for word in tokenized_sentence:
word = word.lower() # 소문자화
# 불용어 말고, 길이가 2 초과인 단어만 사용
if word not in stop_words and len(word) > 2:
result.append(word)
vocab[word] = vocab.get(word, 0) + 1
if result:
preprocessed_sentences.append(result)
💡 단어 빈도수 기반 정수값 부여 및 OOV 처리
- 빈도수가 높은 단어에 낮은 인덱스를 부여해서 상위 N개의 단어 집합을 구성하는 단계입니다.
- 빈도수가 1보다 큰 단어 중에서 상위 5개 단어를 선택하고, 나머지 단어들은 모두 'OOV'(Out-Of-Vocabulary)로 처리했습니다.
# 빈도수 내림차순 정렬
vocab_sorted = sorted(vocab.items(), key=lambda x: x[1], reverse=True)
word_to_index = {}
i = 0
for word, frequency in vocab_sorted:
if frequency > 1: # 빈도수가 1인 단어는 제외
i += 1
word_to_index[word] = i
# 상위 5개 단어만 사용
vocab_size = 5
words_to_remove = [word for word, index in word_to_index.items() if index > vocab_size]
for w in words_to_remove:
del word_to_index[w]
# 단어 집합에 없는 단어 처리를 위해 'OOV' 키 값 추가
word_to_index['OOV'] = len(word_to_index) + 1
- 그 후에는 최종적으로 각 문장을 단어 시퀀스로 변환하였습니다.
encoded_sentences = []
for sentence in preprocessed_sentences:
encoded_sentence = [word_to_index.get(word, word_to_index['OOV']) for word in sentence]
encoded_sentences.append(encoded_sentence)
✨ Counter와 FreqDist를 활용한 단어 빈도수 계산
- 위 과정이 아니라 간단하게 Python의 collections.Counter나 NLTK의 FreqDist를 사용하면 전체 단어 빈도수를 더욱 편리하게 계산할 수도 있습니다.
- 아래는 Counter를 사용한 방법이고,
from collections import Counter
all_words = sum(preprocessed_sentences, [])
vocab_counter = Counter(all_words)
print('Counter를 활용한 상위 5개 단어:', vocab_counter.most_common(5))
- 아래 코드는 NLTK의 FreqDist를 사용하는 방법입니다.
from nltk import FreqDist
import numpy as np
vocab_freq = FreqDist(np.hstack(preprocessed_sentences))
print('FreqDist를 활용한 상위 5개 단어:', vocab_freq.most_common(5))
✨ Keras Tokenizer를 활용한 텍스트 전처리
- keras를 사용하면 이보다 더더욱 쉽게 정수 인코딩을 할 수 있습니다!
- 시퀀스들을 생성하기 위해서 Keras의 Tokenizer를 활용했고,
- 전처리된 문장들을 기반으로 단어 집합을 만들고, 정수 시퀀스로 변환하는 방법을 코드로 작성해보았습니다.
from tensorflow.keras.preprocessing.text import Tokenizer
# num_words는 상위 단어 개수 지정 (여기서는 상위 5개 단어+1: 0번은 사용하지 않음)
tokenizer = Tokenizer(num_words=5+1)
tokenizer.fit_on_texts(preprocessed_sentences)
print('Keras의 단어 인덱스:', tokenizer.word_index)
print('단어 등장 횟수:', tokenizer.word_counts)
print('문장을 인덱스 시퀀스로 변환:', tokenizer.texts_to_sequences(preprocessed_sentences))
- fit_on_texts() 함수는 텍스트에 등장하는 단어들을 빈도수 순으로 인덱싱해줍니다.
- num_words 파라미터를 지정하면 상위 n개의 단어만 사용하도록 제한할 수 있습니다.
- texts_to_sequences() 함수는 각 문장을 단어 인덱스로 이루어진 시퀀스로 변환해줍니다.
☃️ 패딩
- 자연어 처리를 하다보면 각 문장(또는 문서)은 서로 길이가 다를 수가 있습니다.
- 기계는 길이가 전부 동일한 문서들에 대해서는 하나의 행렬로 보고, 한꺼번에 묶어서 처리를 할 수 있기 때문에,
- 병렬 연산을 위해서 여러 문장의 길이를 임의로 동일하게 맞춰주는 작업이 필요합니다.
✨ Numpy로 직접 패딩하기
import numpy as np
from tensorflow.keras.preprocessing.text import Tokenizer
preprocessed_sentences = [
['~~~', '~~~'],
['~~~', '~~~']
...
]
tokenizer = Tokenizer()
tokenizer.fit_on_texts(preprocessed_sentences)
encoded = tokenizer.texts_to_sequences(preprocessed_sentences)
# 가장 긴 문장의 길이를 계산
max_len = max(len(item) for item in encoded)
# 각 문장이 max_len 길이가 되도록 0으로 패딩해주기 (후방 패딩)
for sentence in encoded:
while len(sentence) < max_len:
sentence.append(0)
padded_np = np.array(encoded)
✨ Keras의 pad_sequences()를 사용해서 패딩하기
- Keras의 pad_sequences()는 내부적으로 쉽게 패딩할 수 있는 기능을 제공해주며 여러 옵션들도 사용할 수 있습니다.
from tensorflow.keras.preprocessing.sequence import pad_sequences
encoded = tokenizer.texts_to_sequences(preprocessed_sentences)
# 앞쪽(기본 옵션) 패딩, 각 시퀀스가 동일한 길이가 됨
padded = pad_sequences(encoded)
# 후방 패딩 적용, padding='post'
padded = pad_sequences(encoded, padding='post')
# maxlen 지정, 길이가 maxlen보다 짧으면 0으로 패딩, 길면 잘라냄
padded = pad_sequences(encoded, padding='post', maxlen=5)
# truncating='post', maxlen을 초과할 경우 뒤쪽 단어들을 잘라냄
padded = pad_sequences(encoded, padding='post', truncating='post', maxlen=5)
# 사용자 지정 패딩 값 사용
# 현재 사용된 정수와 겹치지 않는 값을 패딩 값으로 지정
last_value = len(tokenizer.word_index) + 1
padded = pad_sequences(encoded, padding='post', value=last_value)
- 옵션은 크게 아래 4가지로 구성되어 있습니다.
- padding: 'pre' (기본, 앞쪽 패딩) 또는 'post' (후방 패딩)
- maxlen: 모든 시퀀스의 길이를 지정한 길이로 맞추며, 초과하는 단어는 잘라냅니다.
- truncating: maxlen 초과 시, 'pre' 또는 'post' 옵션으로 잘라낼 부분을 지정합니다.
- value: 패딩할 때 사용할 값(0 이외의 값)을 지정해줍니다. (예를 들어, 단어 집합의 크기보다 1 큰 값을 사용)
🔥 One-Hot 인코딩
- 자연어 처리에서는 텍스트 데이터를 컴퓨터가 이해할 수 있도록 수치형 벡터로 변환하는 작업이 필수적입니다. 그중 가장 기본적인 방법 중 하나가 One-Hot 인코딩입니다.
- 이 One-Hot 인코딩은 단어 집합의 크기를 벡터의 차원으로 설정하고, 각 단어의 인덱스에 해당하는 위치에만 1을 부여하고 나머지는 0으로 채워서 단어를 표현해줍니다.
- 예를 들어서 단어 집합이 ['나', '는', 'One', 'Hot', '을', '배운다', '.']라면,
- 'One'에 해당하는 인덱스(3번 위치)만 1이고 나머지는 모두 0인 벡터가 생성됩니다.
- 자연어 처리 과정에서는 보통 첫번째로 정수 인코딩을 진행한 후, 두번째 단계로 원-핫 인코딩을 적용한다고 합니다.
✨ 직접 구현해 본 One-Hot 인코딩
- Konlpy의 Okt()를 활용해서 한국어 문장을 형태소 단위로 분리한 다음, 각 단어에 대한 정수 인덱스를 생성했습니다.
from konlpy.tag import Okt
# Okt를 이용해 텍스트를 형태소 단위로 분리
okt = Okt()
tokens = okt.morphs('나는 One Hot을 배운다.')
# ['나', '는', 'One', 'Hot', '을', '배운다', '.']
# 각 토큰에 인덱스 부여
word_to_index = {word: index for index, word in enumerate(tokens)}
# {'나': 0, '는': 1, 'One': 2, 'Hot': 3, '을': 4, '배운다': 5, '.': 6}
# 특정 단어에 대해 원-핫 벡터를 만드는 함수 정의
def one_hot_encoding(word, word_to_index):
one_hot_vector = [0] * len(word_to_index)
index = word_to_index[word]
one_hot_vector[index] = 1
return one_hot_vector
- 위 코드는 단어별로 인덱스를 부여한 다음에, 해당 단어에 맞는 인덱스 위치만 1로 설정하는 One-Hot 인코딩 함수를 만드는 과정을 보여줍니다.
✨ Keras를 이용한 One-Hot 인코딩
- Keras에서는 정수 인코딩된 텍스트로부터 One-Hot 인코딩을 간편하게 수행할 수 있는 to_categorical() 함수가 제공됩니다.
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.utils import to_categorical
text = '나랑 점심 먹으러 갈래 점심 메뉴는 햄버거 갈래 갈래 햄버거 최고야'
# Tokenizer로 단어 집합 구축 및 정수 인코딩
tokenizer = Tokenizer()
tokenizer.fit_on_texts([text])
print(tokenizer.word_index)
# {'갈래': 1, '점심': 2, '햄버거': 3, '나랑': 4, '먹으러': 5, '메뉴는': 6, '최고야': 7}
# 원본 텍스트에서 일부 문장을 선택하여 정수 인코딩 수행
sub_text = '점심 먹으러 갈래 메뉴는 햄버거 최고야'
encoded = tokenizer.texts_to_sequences([sub_text])[0]
# 정수 인코딩된 결과를 원-핫 인코딩으로 변환
one_hot = to_categorical(encoded)
- 위 같은 방식은 직접 인덱스를 부여하는 번거로운 작업없이, Keras 내부에서 단어의 빈도수에 따라 정수 인코딩을 먼저 수행한 다음에 to_categorical() 함수를 이용해 One-Hot 벡터로 간단히 변환할 수 있습니다.
✨ 이런 One-Hot 인코딩에도 문제가 있나?
- One-Hot 인코딩은 구현이 간단하고 직관적이지만, 몇 가지 한계가 있는데요.
- 먼저, 단어 집합의 크기가 커질수록 벡터의 차원이 매우 커지게 되고, 그에 따라서 메모리 사용량도 증가합니다.
- 그리고 각 단어 벡터는 서로 독립적이기 때문에 단어 간의 유사도('햄버거'와 '버거'의 관계)를 표현하지 못합니다.
- 이러한 문제를 해결하기 위해 단어의 잠재적인 의미를 반영하는 임베딩 기법이 개발되고 있습니다.
- 대표적인 방법으로, LSA (잠재 의미 분석), HAL과 같은 카운트 기반 방법, NNLM, RNNLM, Word2Vec, FastText 등의 예측 기반 방법, 마지막으로 Glove와 같은 혼합적인 방법도 있습니다.
✂️ Splitting
- 지도학습에서는 모델을 학습시키기 위해 입력 데이터(X)와 정답 데이터(y)로 구성된 훈련 데이터와 테스트 데이터가 필요합니다.
- 예를 들면, 이메일 스팸 분류 문제에서는 이메일 본문이 입력(X)이고, 해당 이메일이 스팸인지 여부가 정답(y)이 됩니다.
- 여러 방법으로 이 Splitting 과정을 작성해봤는데, 리스트와 zip()을 활용한 방법, DataFrame과 Numpy 배열을 활용한 방법 등 다양했지만, 그 중에서 scikit-learn이 제공하는 train_test_split() 함수에 대해서만 간단히 작성하고 넘어가겠습니다.
✨ train_test_split을 이용한 데이터 분할
import numpy as np
from sklearn.model_selection import train_test_split
# X는 5행 2열의 배열, y는 0부터 4까지의 정답 레이블
X = np.arange(10).reshape((5, 2))
y = range(5)
# train_test_split을 사용하여 7:3 비율로 분리 (test_size=0.3)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1234)
- 함수에 사용되는 대표적인 매개 변수는 다음과 같습니다.
- X: 독립 변수(입력 데이터)
- y: 종속 변수(정답, 레이블 데이터)
- test_size: 테스트 데이터의 비율(또는 개수). 0보다 작은 실수면 비율을 의미합니다.
- train_size: 훈련 데이터의 비율(또는 개수). test_size와 둘 중 하나만 지정해도 됩니다.
- random_state: 데이터를 무작위로 분할할 때 사용되는 난수 시드로, 결과의 재현성을 보장해줍니다.
🤔 28일차 회고
- 오늘도 무지막지한 전처리들을 배웠습니다. 그래도 어제에 이어서 진행된 내용들이라 그리 복잡하진 않았습니다.
- 사실 정규 표현식에 대해서는 문자열을 깊게 공부할 때 항상 배웠던 내용인데, 오늘 드디어 하나하나씩 뜯어보면서 머리 속에 내장시킨 것 같습니다.
- 이에 더해서 정수 인코딩이나 패딩, One-Hot 인코딩 등은 keras나 sklearn에서 아주 간편하게 진행되도록 여러 함수들을 제공해주고 있기 때문에 이 함수들을 더더욱 빠삭하게 익혀두어야겠습니다.
- 이번 주에 연휴로 하루가 없었던 탓인지 굉장히 순식간에 지나간 듯한데, 다음 주부터 본격적으로 진행되는 자연어 데이터 처리 과정에서도 빛을 발할 수 있도록 열심히 갈고 닦아보겠습니다! ✨
728x90
LIST
'부트캠프 > LG U+' 카테고리의 다른 글
🤔 왜 달려도 달려도 끝이 없을까... (8) | 2025.03.12 |
---|---|
🤔 Words In My Bag (8) | 2025.03.11 |
🤔 자연어를 처리해보자 (6) | 2025.03.06 |
🤔 SQL 끝장내기 (2) | 2025.03.04 |
🤔 SQL과 날아올라 (4) | 2025.02.27 |