2025. 2. 3. 15:23ㆍ자연어 처리/자연어 처리
1. 벡터화
* 벡터화는 텍스트 데이터를 숫자 형태로 변환하여 머신러닝 또는 딥러닝 모델에서 처리할 수 있도록 만드는 과정입니다.
* 이를 위해 단어의 빈도를 기반으로 한 Bag-of-Words(BOW), TF-IDF와 같은 방법부터, 단어 간의 의미적 관계를 학습하는 Word Embedding(단어 임베딩), 문장의 문맥과 구조를 반영하는 Transformer 기반 임베딩(BERT, GPT) 등 다양한 기법이 사용됩니다.
* 벡터화는 단어, 문장, 문서와 같은 텍스트 데이터의 특징을 수치적으로 표현하며, 단순히 단어의 빈도를 반영하거나 의미적 유사성을 학습하여 벡터 공간에서 단어 간 관계를 나타냅니다.
* 데이터의 특성과 분석 목적에 따라 적절한 벡터화 기법을 선택하는 것이 중요합니다.
2. 원-핫 인코딩
* 원-핫 인코딩(One-Hot Encoding)은 텍스트 데이터를 숫자 벡터로 변환하는 가장 단순한 방법 중 하나로, 단어 집합(vocabulary)에 있는 단어들을 고유한 숫자 벡터로 표현합니다.
* 이 방법은 각 단어를 벡터의 한 차원으로 지정하고, 해당 단어에만 1을 넣고 나머지는 0으로 설정합니다.
* 이를 통해 텍스트 데이터를 컴퓨터가 이해할 수 있는 숫자로 변환합니다.
* 예를 들어, 단어 집합이 ["I", "love", "Python"]이라면, "love"는 [0, 1, 0]으로 표현됩니다.
* 이 방법은 단어를 간단하고 직관적으로 표현할 수 있지만, 단어 간의 의미적 관계를 반영하지 못하며, 단어 집합 크기만큼 고차원 희소 벡터를 생성하므로 메모리 낭비가 큽니다.
희소 벡터
* 희소 벡터(Sparse Vector)는 대부분의 값이 0인 벡터를 의미하며, 자연어 처리에서 원-핫 인코딩(One-Hot Encoding)과 같은 방법으로 단어를 표현할 때 자주 나타납니다.
* 예를 들어, 단어 집합의 크기가 10,000이라면 각 단어를 표현하는 벡터는 10,000차원이 되고, 이 중 단 하나의 위치만 1이고 나머지는 모두 0으로 채워집니다.
* 이러한 벡터는 메모리 낭비와 계산 복잡도를 초래하며, 특히 단어 집합이 클수록 문제가 심각해집니다.
* 이를 해결하기 위해 단어를 저차원의 조밀한 벡터(Dense Vector)로 변환하는 워드 임베딩(Word Embedding) 기법이 자주 사용됩니다.
3. Bag of Words
* Bag of Words(BOW)는 텍스트 데이터를 벡터화하는 간단한 방법으로, 문장을 구성하는 단어들의 등장 빈도를 기반으로 표현합니다.
* 각 문장은 단어 집합(vocabulary)의 크기만큼 차원을 가지며, 단어가 해당 문장에 몇 번 나타나는지 그 빈도를 벡터의 값으로 나타냅니다.
* 예를 들어, 단어 집합이 ["I", "love", "Python"]이고 문장이 "I love Python Python"이라면, 벡터는 [1, 1, 2]로 표현됩니다.
* 단어의 순서나 문맥은 고려되지 않고 단순히 단어의 빈도만 반영되기 때문에, 문장의 구조나 의미를 표현하는 데는 한계가 있습니다.
* 하지만 구현이 간단하고 텍스트 데이터를 빠르게 벡터화할 수 있어 자연어 처리의 기초적인 방법으로 널리 사용됩니다.
* TF-IDF와 같은 확장 기법을 통해 BOW의 단점을 보완하기도 합니다.
예시 1)
from collections import Counter
documents = [
"I love Python Python",
"Python is great Python",
"I love coding coding coding"
]
예시 2)
# 1. 단어 집합 생성 ( set으로 중복 제거 )
vocab = set()
for doc in documents:
vocab.update(doc.split())
vocab = sorted(vocab) # 단어 집합 정렬
예시 3)
# 2. 단어에 인덱스 부여
word_to_index = {word: idx for idx, word in enumerate(vocab)}
word_to_index
--->
{'I': 0, 'Python': 1, 'coding': 2, 'great': 3, 'is': 4, 'love': 5}
예시 4)
# 3. 각 문장을 벡터로 변환
bow_vectors = []
for doc in documents:
word_counts = Counter(doc.split()) # 단어 등장 횟수 계산
bow_vector = [word_counts.get(word, 0) for word in vocab] # 단어 집합 순으로 벡터 생성
bow_vectors.append(bow_vector)
bow_vectors
--->
[[1, 2, 0, 0, 0, 1], [0, 2, 0, 1, 1, 0], [1, 0, 3, 0, 0, 1]]
예시 5)
print("단어 집합:", vocab)
print("단어 인덱스:", word_to_index)
print("Bag of Words 벡터:")
for i, vector in enumerate(bow_vectors):
print(f"문장 {i+1}: {vector}")
-->
단어 집합: ['I', 'Python', 'coding', 'great', 'is', 'love']
단어 인덱스: {'I': 0, 'Python': 1, 'coding': 2, 'great': 3, 'is': 4, 'love': 5}
Bag of Words 벡터:
문장 1: [1, 2, 0, 0, 0, 1]
문장 2: [0, 2, 0, 1, 1, 0]
문장 3: [1, 0, 3, 0, 0, 1]
4. TF-IDF
* TF-IDF(Term Frequency-Inverse Document Frequency)는 텍스트 데이터에서 단어의 중요도를 측정하는 방법으로, 단어의 빈도(TF)와 역문서 빈도(IDF)를 조합하여 계산됩니다.
* 단어 빈도(TF)는 특정 문서에서 해당 단어가 얼마나 자주 등장하는지를 나타내고, 역문서 빈도(IDF)는 해당 단어가 다른 문서들에 얼마나 흔하게 등장하는지를 반영하여 중요도를 조정합니다.
* 이를 통해, 특정 문서에서 자주 등장하면서도 다른 문서에서는 잘 나타나지 않는 단어의 가중치가 높아집니다.
* 예를 들어, 일반적으로 모든 문서에서 자주 등장하는 단어(예: "the", "is")는 낮은 가중치를 받고, 특정 문서에서만 중요한 단어는 높은 가중치를 받습니다.
* TF-IDF는 문서의 내용을 잘 나타내는 단어를 식별하고, 텍스트 데이터의 벡터화를 통해 검색 엔진, 텍스트 분류 등의 작업에서 널리 사용됩니다.
간단한 예제
예시 1)
예시 2)
예시 3)
예시 4)
> TF-IDF
* TF-IDF는 텍스트 데이터에서 특정 문서에 중요하면서도 전체 문서에서 흔하지 않은 단어를 찾아내기 위한 효과적인 방법입니다.
* TF-IDF는 TF와 IDF를 곱하기 때문에, 특정 문서에서 자주 등장하면서 다른 문서에서는 잘 나타나지 않는 단어일수록 TF-IDF 값이 높아집니다.
* TF-IDF의 값이 높으면 해당 단어는 특정 문서에서 중요하다는 것을 뜻합니다.
예시 1)
import pandas as pd
from math import log
예시 2)
# 4개의 문장
docs = [
'먹고 싶은 사과',
'먹고 싶은 바나나',
'길고 노란 바나나 바나나',
'저는 과일이 좋아요'
]
# 문서 리스트(docs)에서 고유한 단어들을 추출하고 정렬하여 출력하는 코드
vocab = list(set(w for doc in docs for w in doc.split())) # 문서 리스트(docs)에서 단어들을 추출하고, 중복을 제거하여 집합(set)으로 변환
vocab.sort() # 리스트 형태로 변환한 후, 알파벳 순서로 정렬
print(vocab) # 정렬된 단어 리스트 출력
--->
['과일이', '길고', '노란', '먹고', '바나나', '사과', '싶은', '저는', '좋아요']
예시 3)
# 총 문서의 수
N = len(docs)
print('총 문서의 수', N)
-->
총 문서의 수 4
예시 4)
# TF를 구하는 함수
def tf(t, d):
return d.count(t)
예시 5)
# IDF를 구하는 함수
def idf(t):
df = 0
for doc in docs:
df += t in doc
return log(N/(df+1))
예시 6)
# TF와 IDF의 값을 곱하는 함수
def tfidf(t, d):
return tf(t,d)* idf(t)
예시 7)
result = [] # 각 문서의 TF 값을 저장할 리스트
# 각 문서에 대해서 (docs[i]) 연산을 반복
for i in range(N):
result.append([]) # 각 문서에 대한 TF 값을 저장할 빈 리스트 추가
d = docs[i] # 현재 문서를 가져옴
for j in range(len(vocab)): # 각 단어(vocab[j])에 대해 반복
t = vocab[j] # 현재 단어 선택
result[-1].append(tf(t, d)) # tf 함수를 호출 : TF 값을 계산
tf_ = pd.DataFrame(result, columns = vocab) # 결과 리스트를 DataFrame으로 변환 (각 문서별 TF 값을 저장한 테이블 형태)
tf_ # 생성된 TF 테이블 출력
--->
예시 8)
result = [ ]
# 각 단어에 대해서 idf값을 계산
for j in range(len(vocab)):
t = vocab[j]
# idf 함수를 호출 : IDF 값을 계산
result.append(idf(t))
# IDF 출력
idf_ = pd.DataFrame(result, index=vocab, columns=["IDF"])
idf_
--->
예시 9)
result = []
for i in range(N):
result.append([])
d = docs[i]
for j in range(len(vocab)):
t = vocab[j]
# tfidf 함수를 호출 : TF-IDF 값 계산
result[-1].append(tfidf(t,d))
# TF-IDF 행렬
tfidf_ = pd.DataFrame(result, columns = vocab)
tfidf_
--->
5. 사이킷런을 이용한 DTM과 TF-IDF
예시 1)
# CountVectorizer는 텍스트 데이터를 벡터화(수치화)하는 도구
# Bag-of-Words(BoW) 모델을 기반으로 작동
from sklearn.feature_extraction.text import CountVectorizer
# 텍스트 데이터
corpus = [
'you know I want your love',
'I like you',
'what should I do ',
]
vector = CountVectorizer()
# 코퍼스로부터 각 단어의 빈도수를 기록
print(vector.fit_transform(corpus).toarray())
--->
[[0 1 0 1 0 1 0 1 1]
[0 0 1 0 0 0 0 1 0]
[1 0 0 0 1 0 1 0 0]]
예시 2)
#각 단어와 맵핑된 인덱스를 출력
print(vector.vocabulary_)
-->
{'you': 7, 'know': 1, 'want': 5, 'your': 8, 'love': 3, 'like': 2, 'what': 6, 'should': 4, 'do': 0}
예시 3)
from sklearn.feature_extraction.text import TfidfVectorizer
# 텍스트 데이터
corpus = [
'you know I want your love',
'I like you',
'what should I do ',
]
tfidfv = TfidfVectorizer().fit(corpus) # TfidfVectorizer 객체 생성 및 학습 (fit)
print(tfidfv.transform(corpus).toarray()) # 학습된 TF-IDF 변환기를 이용해 corpus를 TF-IDF 행렬로 변환
print(tfidfv.vocabulary_) # 각 단어에 대한 인덱스(어휘 사전) 출력
--->
[[0. 0.46735098 0. 0.46735098 0. 0.46735098
0. 0.35543247 0.46735098]
[0. 0. 0.79596054 0. 0. 0.
0. 0.60534851 0. ]
[0.57735027 0. 0. 0. 0.57735027 0.
0.57735027 0. 0. ]]
{'you': 7, 'know': 1, 'want': 5, 'your': 8, 'love': 3, 'like': 2, 'what': 6, 'should': 4, 'do': 0}
6. 코사인 유사도
* 코사인 유사도(Cosine Similarity)는 두 벡터 간의 방향(각도)을 기반으로 유사도를 측정하는 방법으로, 벡터 간의 크기가 아니라 방향이 얼마나 유사한지를 나타냅니다.
* 두 벡터의 코사인 유사도는 코사인 함수를 사용해 계산되며, 값의 범위는 -1에서 1 사이입니다.
* 두 벡터가 완전히 같은 방향이면 유사도가 1, 서로 수직이면 유사도가 0, 정반대 방향이면 유사도가 -1이 됩니다.
* 주로 텍스트 데이터를 벡터로 표현한 후(예: TF-IDF, 임베딩), 문서나 문장의 유사도를 계산하는 데 사용됩니다.
* 코사인 유사도는 벡터의 크기(빈도 차이)에 영향을 받지 않으므로, 단어 등장 횟수보다는 패턴이나 구조적인 유사성을 측정하는 데 적합합니다.
예시 1)
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
# 문서 벡터 정의 (각 문서를 벡터 형태로 표현)
doc1 = np.array([[0,1,1,1]])
doc2 = np.array([[1,0,1,1]])
doc3 = np.array([[2,0,2,2]])
# 문서 간 코사인 유사도 계산
print('문서 1과 문서2의 유사도 :',cosine_similarity(doc1, doc2))
print('문서 1과 문서3의 유사도 :',cosine_similarity(doc1, doc3))
print('문서 2와 문서3의 유사도 :',cosine_similarity(doc2, doc3))
-->
문서 1과 문서2의 유사도 : [[0.66666667]]
문서 1과 문서3의 유사도 : [[0.66666667]]
문서 2와 문서3의 유사도 : [[1.]]
7. 한국어 데이터 전처리
# 웹 스크레핑을 통해 뉴스 기사를 수집하고 분석하는데 사용
!pip install newspaper3k
설치 후 upgrade 해준다
pip install --upgrade --force-reinstall newspaper3k lxml nltk beautifulsoup4 lxml_html_clean
예시 1)
import newspaper
newspaper.languages()
-->
Your available languages are:
input code full name
da Danish
sv Swedish
ro Romanian
tr Turkish
zh Chinese
en English
mk Macedonian
ru Russian
fi Finnish
nb Norwegian (Bokmål)
de German
et Estonian
ja Japanese
ar Arabic
sl Slovenian
hr Croatian
it Italian
be Belarusian
nl Dutch
bg Bulgarian
no Norwegian
fa Persian
el Greek
ko Korean
hi Hindi
fr French
hu Hungarian
sw Swahili
uk Ukrainian
he Hebrew
sr Serbian
es Spanish
pl Polish
vi Vietnamese
id Indonesian
pt Portuguese
예시 2)
# 특정 뉴스 기사의 url 을 통해 기사를 다운로드, 파싱 할수 있음
from newspaper import Article
url = 'https://v.daum.net/v/20250203093508049' # 가져올 기사 url을 첨부함
article = Article(url, languages='ko') # url과 언어는 한국어로 가져옴
article.download() # 다운로드해줌
article.parse() # 파싱해줌
예시 3)
print('title', article.title)
-->
title 조깅에 스트레칭 더하면 ‘금상첨화’…최적 시간은 ‘4분’
예시 4)
print('content', article.text)
-->
content 유연성을 높여주는 최적의 스트레칭 시간은 4분이라는 연구 결과가 나왔다. 사진은 연구진이 생활 스트레칭으로 권하는 ‘허벅지 뒤쪽 근육(햄스트링) 펴주기’ 동작이다. 픽사베이
(☞한겨레 뉴스레터 H:730 구독하기. 검색창에 ‘한겨레 h730’을 쳐보세요.)
건강을 위해 운동을 한다고 심폐 기능이나 근력 같은 신체 능력을 강화하는 운동만 해선 안 된다. 굳은 근육을 풀어주는 스트레칭도 병행해야 더 좋은 효과를 볼 수 있다.
스트레칭의 가장 기본적인 효과는 우리 몸에 있는 관절의 작동 범위를 넓혀주는 데서 나온다. 이렇게 하면 몸의 유연성이 높아져 신체 활동력이 좋아지고 부상 위험도 줄어든다. 또 혈액 순환과 자세 교정에도 도움이 되는 등 다양한 효과가 있다.
보통 스트레칭이라 하면 일정 시간 동안 특정 부위의 근육을 늘린 상태를 유지해주는 정적 스트레칭을 말한다. 스트레칭은 어떤 강도로 얼마나 오랫 동안, 얼마나 자주 하는 것이 좋을까? 유산소 및 무산소 운동과 달리 스트레칭에 대해선 아직 뚜렷한 권고 지침이 나와 있지 않다.
사우스오스트레일리아대 연구진이 2023년 한 해 동안 전 세계에서 발표된 189건의 연구 결과를 분석한 결과를 토대로, 최적의 효과를 볼 수 있는 스트레칭 기준을 찾아내 국제학술지 ‘스포츠의학’에 발표했다.
유연성이 떨어지는 사람은 유연성이 높은 사람에 비해 스트레칭 해야 할 근육이 더 많으므로 더 많은 시간을 투자해야 한다. 사진은 연구진이 생활 스트레칭으로 권하는 ‘허벅지 앞쪽 근육(대퇴사두근) 펴주기’ 동작이다. 픽사베이
강도나 횟수보다 전체 시간 중요
분석 대상으로 삼은 연구들은 스트레칭을 하지 않은 사람들과 한 번 또는 여러번 정적 스트레칭을 한 사람들의 유연성을 비교한 것들이다.
분석 결과, 유연성을 그 자리에서 높여주는 최적의 스트레칭 시간은 4분이었다. 4분 이상 스트레칭을 한다고 해서 더 좋은 효과를 보지는 못하는 것으로 나타났다.
그러나 높은 유연성을 계속해서 유지하려면 더 오랫동안 스트레칭을 해줘야 한다. 연구진은 일주일에 10분 정도 할 경우 최고의 효과를 볼 수 있는 것으로 나타났다고 밝혔다. 연구진은 그러나 스트레칭을 한꺼번에 몰아서 할 필요는 없다고 덧붙였다.
통증을 느낄 정도로 스트레칭을 강하게 하는 것이 더 효과가 있을까? 언뜻 그럴 것으로 생각하기 쉽다. 하지만 연구진은 스트레칭의 강도는 중요하지 않다고 밝혔다. 통증을 느낄 정도로 강하게 하는 스트레칭이나 그렇지 않은 스트레칭이나 모두 유연성을 높여줬다는 것이다.
스트레칭 횟수도 그다지 중요하지 않은 것으로 나타났다. 횟수보다 중요한 것은 전체 시간이었다. 연구진은 스트레칭이 필요한 근육 부위에 대해 일주일에 10분 정도씩 스트레칭을 해주는 것을 권했다. 예컨대 매일 1분여씩 할 수도 있고, 일주일에 두 차례 5분씩 할 수도 있다.
전체적인 스트레칭 시간은 스트레칭이 필요한 근육의 수에 따라 달라진다. 유연성이 떨어지는 사람은 유연성이 높은 사람에 비해 스트레칭 해야 할 근육이 더 많으므로 더 많은 시간을 투자해야 한다.
스트레칭으로 굳은 몸을 푸는 것은 하루를 시작하고 마무리하는 아주 좋은 방법이다. 사진은 연구진이 생활 스트레칭으로 권하는 ‘삼두근 펴주기’ 동작이다. corelens/Canva
연구진이 권하는 기본 스트레칭 3가지
연구진은 연구자 매체 ‘더 컨버세이션’ 기고를 통해 “스트레칭의 효과는 나이나 성별에 관계없이 유연성을 높이는 데 도움이 된다”며 언제 어디서나 아무런 장비 없이 할 수 있는 운동인만큼 스트레칭으로 굳은 몸을 푸는 것은 하루를 시작하고 마무리하는 아주 좋은 방법이라고 강조했다.
연구진은 이와 함께 일상 생활에서 필요한 스트레칭으로 세 가지를 권했다.
첫째는 허벅지 뒤쪽 근육(햄스트링)을 펴주는 동작이다. 벤치나 의자 등받이에 한 쪽 발을 올려놓고 무릎을 곧게 편 상태에서 허리를 앞으로 숙인다.
둘째는 허벅지 앞쪽 근육(대퇴사두근)을 펴주는 동작이다. 한 쪽 무릎을 구부려 발목을 엉덩이에 댄 뒤, 한 손으로 발목을 잡고 무릎을 최대한 당겨준다. 이 동작을 할 때는 서 있는 동안 몸의 균형을 잡을 수 있도록 다른 한 손으로 책상이나 의자 등을 잡고 있는 게 좋다.
셋째는 삼두근을 펴주는 동작이다. 두 팔을 올려 머리 뒤쪽에서 팔꿈치를 마주 보게 구부린 뒤 한쪽 팔을 뻗어 다른 쪽 팔을 당겨준다.
*논문 정보
https://doi.org/10.1007/s40279-024-02143-9
Optimising the Dose of Static Stretching to Improve Flexibility: A Systematic Review, Meta-analysis and Multivariate Meta-regression. Sports Med (2024).
곽노필 선임기자 nopil@hani.co.kr
예시 5)
# 예시 4에 밑에 첨부함
additional_info = [
"※ 기자 김사과 apple@apple.com 취재 반하나 banana@banana.com ",
"<h2>조깅에 스트레칭 더하면 ‘금상첨화’…최적 시간은 ‘4분’</h2>",
"이 기사는 임시 데이터임을 알립니다 …",
"<br> ☞ 이 기사는 건강 섹션으로 분류되었습니다 … <br>",
"#기사 #건강 #조깅 #스트레칭"
]
context = article.text.split('\n\n')
context += additional_info
context
--->
'*논문 정보',
'https://doi.org/10.1007/s40279-024-02143-9',
'Optimising the Dose of Static Stretching to Improve Flexibility: A Systematic Review, Meta-analysis and Multivariate Meta-regression. Sports Med (2024).',
'곽노필 선임기자 nopil@hani.co.kr',
'※ 기자 김사과 apple@apple.com 취재 반하나 banana@banana.com ',
'<h2>조깅에 스트레칭 더하면 ‘금상첨화’…최적 시간은 ‘4분’</h2>',
'이 기사는 임시 데이터임을 알립니다 …',
'<br> ☞ 이 기사는 건강 섹션으로 분류되었습니다 … <br>',
'#기사 #건강 #조깅 #스트레칭']
예시 6)
# context 리스트의 각 요소를 인덱스와 함께 출력하는 코드
# 인덱스 숫자와 텍스트를 출력하는 코드
# enumerate(context): 리스트 context의 요소를 (인덱스, 값) 형태로 반환
# i: 현재 요소의 인덱스 (0부터 시작)
# text: context 리스트에서 i번째 요소
for i, text in enumerate(context):
print(i, text) # 인덱스와 해당 요소 출력
--->
0 유연성을 높여주는 최적의 스트레칭 시간은 4분이라는 연구 결과가 나왔다. 사진은 연구진이 생활 스트레칭으로 권하는 ‘허벅지 뒤쪽 근육(햄스트링) 펴주기’ 동작이다. 픽사베이
1 (☞한겨레 뉴스레터 H:730 구독하기. 검색창에 ‘한겨레 h730’을 쳐보세요.)
2 건강을 위해 운동을 한다고 심폐 기능이나 근력 같은 신체 능력을 강화하는 운동만 해선 안 된다. 굳은 근육을 풀어주는 스트레칭도 병행해야 더 좋은 효과를 볼 수 있다.
3 스트레칭의 가장 기본적인 효과는 우리 몸에 있는 관절의 작동 범위를 넓혀주는 데서 나온다. 이렇게 하면 몸의 유연성이 높아져 신체 활동력이 좋아지고 부상 위험도 줄어든다. 또 혈액 순환과 자세 교정에도 도움이 되는 등 다양한 효과가 있다.
4 보통 스트레칭이라 하면 일정 시간 동안 특정 부위의 근육을 늘린 상태를 유지해주는 정적 스트레칭을 말한다. 스트레칭은 어떤 강도로 얼마나 오랫 동안, 얼마나 자주 하는 것이 좋을까? 유산소 및 무산소 운동과 달리 스트레칭에 대해선 아직 뚜렷한 권고 지침이 나와 있지 않다.
5 사우스오스트레일리아대 연구진이 2023년 한 해 동안 전 세계에서 발표된 189건의 연구 결과를 분석한 결과를 토대로, 최적의 효과를 볼 수 있는 스트레칭 기준을 찾아내 국제학술지 ‘스포츠의학’에 발표했다.
6 유연성이 떨어지는 사람은 유연성이 높은 사람에 비해 스트레칭 해야 할 근육이 더 많으므로 더 많은 시간을 투자해야 한다. 사진은 연구진이 생활 스트레칭으로 권하는 ‘허벅지 앞쪽 근육(대퇴사두근) 펴주기’ 동작이다. 픽사베이
7 강도나 횟수보다 전체 시간 중요
8 분석 대상으로 삼은 연구들은 스트레칭을 하지 않은 사람들과 한 번 또는 여러번 정적 스트레칭을 한 사람들의 유연성을 비교한 것들이다.
9 분석 결과, 유연성을 그 자리에서 높여주는 최적의 스트레칭 시간은 4분이었다. 4분 이상 스트레칭을 한다고 해서 더 좋은 효과를 보지는 못하는 것으로 나타났다.
10 그러나 높은 유연성을 계속해서 유지하려면 더 오랫동안 스트레칭을 해줘야 한다. 연구진은 일주일에 10분 정도 할 경우 최고의 효과를 볼 수 있는 것으로 나타났다고 밝혔다. 연구진은 그러나 스트레칭을 한꺼번에 몰아서 할 필요는 없다고 덧붙였다.
11 통증을 느낄 정도로 스트레칭을 강하게 하는 것이 더 효과가 있을까? 언뜻 그럴 것으로 생각하기 쉽다. 하지만 연구진은 스트레칭의 강도는 중요하지 않다고 밝혔다. 통증을 느낄 정도로 강하게 하는 스트레칭이나 그렇지 않은 스트레칭이나 모두 유연성을 높여줬다는 것이다.
12 스트레칭 횟수도 그다지 중요하지 않은 것으로 나타났다. 횟수보다 중요한 것은 전체 시간이었다. 연구진은 스트레칭이 필요한 근육 부위에 대해 일주일에 10분 정도씩 스트레칭을 해주는 것을 권했다. 예컨대 매일 1분여씩 할 수도 있고, 일주일에 두 차례 5분씩 할 수도 있다.
13 전체적인 스트레칭 시간은 스트레칭이 필요한 근육의 수에 따라 달라진다. 유연성이 떨어지는 사람은 유연성이 높은 사람에 비해 스트레칭 해야 할 근육이 더 많으므로 더 많은 시간을 투자해야 한다.
14 스트레칭으로 굳은 몸을 푸는 것은 하루를 시작하고 마무리하는 아주 좋은 방법이다. 사진은 연구진이 생활 스트레칭으로 권하는 ‘삼두근 펴주기’ 동작이다. corelens/Canva
15 연구진이 권하는 기본 스트레칭 3가지
16 연구진은 연구자 매체 ‘더 컨버세이션’ 기고를 통해 “스트레칭의 효과는 나이나 성별에 관계없이 유연성을 높이는 데 도움이 된다”며 언제 어디서나 아무런 장비 없이 할 수 있는 운동인만큼 스트레칭으로 굳은 몸을 푸는 것은 하루를 시작하고 마무리하는 아주 좋은 방법이라고 강조했다.
17 연구진은 이와 함께 일상 생활에서 필요한 스트레칭으로 세 가지를 권했다.
18 첫째는 허벅지 뒤쪽 근육(햄스트링)을 펴주는 동작이다. 벤치나 의자 등받이에 한 쪽 발을 올려놓고 무릎을 곧게 편 상태에서 허리를 앞으로 숙인다.
19 둘째는 허벅지 앞쪽 근육(대퇴사두근)을 펴주는 동작이다. 한 쪽 무릎을 구부려 발목을 엉덩이에 댄 뒤, 한 손으로 발목을 잡고 무릎을 최대한 당겨준다. 이 동작을 할 때는 서 있는 동안 몸의 균형을 잡을 수 있도록 다른 한 손으로 책상이나 의자 등을 잡고 있는 게 좋다.
20 셋째는 삼두근을 펴주는 동작이다. 두 팔을 올려 머리 뒤쪽에서 팔꿈치를 마주 보게 구부린 뒤 한쪽 팔을 뻗어 다른 쪽 팔을 당겨준다.
21 *논문 정보
22 https://doi.org/10.1007/s40279-024-02143-9
23 Optimising the Dose of Static Stretching to Improve Flexibility: A Systematic Review, Meta-analysis and Multivariate Meta-regression. Sports Med (2024).
24 곽노필 선임기자 nopil@hani.co.kr
25 ※ 기자 김사과 apple@apple.com 취재 반하나 banana@banana.com
26 <h2>조깅에 스트레칭 더하면 ‘금상첨화’…최적 시간은 ‘4분’</h2>
27 이 기사는 임시 데이터임을 알립니다 …
28 <br> ☞ 이 기사는 건강 섹션으로 분류되었습니다 … <br>
29 #기사 #건강 #조깅 #스트레칭
예시 7)
# 불용어(stopword) 처리
# 불필요한 태그 및 특수 문자 제거
# 코퍼스 내 등장 빈도가 적은 단어 제거
# 보편적으로 선택할 수 있는 한국어 불용어 리스트 : https://www.ranks.nl/stopwords/korean
# https://www.ranks.nl/stopwords/korean
# 불용어(stopwords) 리스트 정의
stopwords = ['※', '☞', '…', '*논문', '189건의', '@']
# 불용어를 제거하는 함수 정의
def delete_stopwords(context):
preprocessed_text = [] # 불용어 제거 후 저장할 리스트
# context 리스트의 각 문장에 대해 반복
for text in context:
# 문장을 공백(' ')을 기준으로 단어 단위로 분할한 후,
# 불용어 리스트(stopwords)에 없는 단어들만 남김
text = [w for w in text.split(' ') if w not in stopwords]
# 리스트로 나눈 단어들을 다시 하나의 문자열로 결합
preprocessed_text.append(' '.join(text))
return preprocessed_text # 전처리된 텍스트 리스트 반환
-->
0 유연성을 높여주는 최적의 스트레칭 시간은 4분이라는 연구 결과가 나왔다. 사진은 연구진이 생활 스트레칭으로 권하는 ‘허벅지 뒤쪽 근육(햄스트링) 펴주기’ 동작이다. 픽사베이
1 (☞한겨레 뉴스레터 H:730 구독하기. 검색창에 ‘한겨레 h730’을 쳐보세요.)
2 건강을 위해 운동을 한다고 심폐 기능이나 근력 같은 신체 능력을 강화하는 운동만 해선 안 된다. 굳은 근육을 풀어주는 스트레칭도 병행해야 더 좋은 효과를 볼 수 있다.
3 스트레칭의 가장 기본적인 효과는 우리 몸에 있는 관절의 작동 범위를 넓혀주는 데서 나온다. 이렇게 하면 몸의 유연성이 높아져 신체 활동력이 좋아지고 부상 위험도 줄어든다. 또 혈액 순환과 자세 교정에도 도움이 되는 등 다양한 효과가 있다.
4 보통 스트레칭이라 하면 일정 시간 동안 특정 부위의 근육을 늘린 상태를 유지해주는 정적 스트레칭을 말한다. 스트레칭은 어떤 강도로 얼마나 오랫 동안, 얼마나 자주 하는 것이 좋을까? 유산소 및 무산소 운동과 달리 스트레칭에 대해선 아직 뚜렷한 권고 지침이 나와 있지 않다.
5 사우스오스트레일리아대 연구진이 2023년 한 해 동안 전 세계에서 발표된 연구 결과를 분석한 결과를 토대로, 최적의 효과를 볼 수 있는 스트레칭 기준을 찾아내 국제학술지 ‘스포츠의학’에 발표했다.
6 유연성이 떨어지는 사람은 유연성이 높은 사람에 비해 스트레칭 해야 할 근육이 더 많으므로 더 많은 시간을 투자해야 한다. 사진은 연구진이 생활 스트레칭으로 권하는 ‘허벅지 앞쪽 근육(대퇴사두근) 펴주기’ 동작이다. 픽사베이
7 강도나 횟수보다 전체 시간 중요
8 분석 대상으로 삼은 연구들은 스트레칭을 하지 않은 사람들과 한 번 또는 여러번 정적 스트레칭을 한 사람들의 유연성을 비교한 것들이다.
9 분석 결과, 유연성을 그 자리에서 높여주는 최적의 스트레칭 시간은 4분이었다. 4분 이상 스트레칭을 한다고 해서 더 좋은 효과를 보지는 못하는 것으로 나타났다.
10 그러나 높은 유연성을 계속해서 유지하려면 더 오랫동안 스트레칭을 해줘야 한다. 연구진은 일주일에 10분 정도 할 경우 최고의 효과를 볼 수 있는 것으로 나타났다고 밝혔다. 연구진은 그러나 스트레칭을 한꺼번에 몰아서 할 필요는 없다고 덧붙였다.
11 통증을 느낄 정도로 스트레칭을 강하게 하는 것이 더 효과가 있을까? 언뜻 그럴 것으로 생각하기 쉽다. 하지만 연구진은 스트레칭의 강도는 중요하지 않다고 밝혔다. 통증을 느낄 정도로 강하게 하는 스트레칭이나 그렇지 않은 스트레칭이나 모두 유연성을 높여줬다는 것이다.
12 스트레칭 횟수도 그다지 중요하지 않은 것으로 나타났다. 횟수보다 중요한 것은 전체 시간이었다. 연구진은 스트레칭이 필요한 근육 부위에 대해 일주일에 10분 정도씩 스트레칭을 해주는 것을 권했다. 예컨대 매일 1분여씩 할 수도 있고, 일주일에 두 차례 5분씩 할 수도 있다.
13 전체적인 스트레칭 시간은 스트레칭이 필요한 근육의 수에 따라 달라진다. 유연성이 떨어지는 사람은 유연성이 높은 사람에 비해 스트레칭 해야 할 근육이 더 많으므로 더 많은 시간을 투자해야 한다.
14 스트레칭으로 굳은 몸을 푸는 것은 하루를 시작하고 마무리하는 아주 좋은 방법이다. 사진은 연구진이 생활 스트레칭으로 권하는 ‘삼두근 펴주기’ 동작이다. corelens/Canva
15 연구진이 권하는 기본 스트레칭 3가지
16 연구진은 연구자 매체 ‘더 컨버세이션’ 기고를 통해 “스트레칭의 효과는 나이나 성별에 관계없이 유연성을 높이는 데 도움이 된다”며 언제 어디서나 아무런 장비 없이 할 수 있는 운동인만큼 스트레칭으로 굳은 몸을 푸는 것은 하루를 시작하고 마무리하는 아주 좋은 방법이라고 강조했다.
17 연구진은 이와 함께 일상 생활에서 필요한 스트레칭으로 세 가지를 권했다.
18 첫째는 허벅지 뒤쪽 근육(햄스트링)을 펴주는 동작이다. 벤치나 의자 등받이에 한 쪽 발을 올려놓고 무릎을 곧게 편 상태에서 허리를 앞으로 숙인다.
19 둘째는 허벅지 앞쪽 근육(대퇴사두근)을 펴주는 동작이다. 한 쪽 무릎을 구부려 발목을 엉덩이에 댄 뒤, 한 손으로 발목을 잡고 무릎을 최대한 당겨준다. 이 동작을 할 때는 서 있는 동안 몸의 균형을 잡을 수 있도록 다른 한 손으로 책상이나 의자 등을 잡고 있는 게 좋다.
20 셋째는 삼두근을 펴주는 동작이다. 두 팔을 올려 머리 뒤쪽에서 팔꿈치를 마주 보게 구부린 뒤 한쪽 팔을 뻗어 다른 쪽 팔을 당겨준다.
21 정보
22 https://doi.org/10.1007/s40279-024-02143-9
23 Optimising the Dose of Static Stretching to Improve Flexibility: A Systematic Review, Meta-analysis and Multivariate Meta-regression. Sports Med (2024).
24 곽노필 선임기자 nopil@hani.co.kr
25 기자 김사과 apple@apple.com 취재 반하나 banana@banana.com
26 <h2>조깅에 스트레칭 더하면 ‘금상첨화’…최적 시간은 ‘4분’</h2>
27 이 기사는 임시 데이터임을 알립니다
28 <br> 이 기사는 건강 섹션으로 분류되었습니다 <br>
29 #기사 #건강 #조깅 #스트레칭
예시 8)
# 이메일 제거 함수
def delete_email(context):
preprocessed_context = [ ]
for text in context:
text = re.sub(r'[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+', '', text).strip()
preprocessed_context.append(text)
return preprocessed_context
preprocessed_context = delete_email(preprocessed_context)
preprocessed_context
-->
'https://doi.org/10.1007/s40279-024-02143-9',
'Optimising the Dose of Static Stretching to Improve Flexibility: A Systematic Review, Meta-analysis and Multivariate Meta-regression. Sports Med (2024).',
'곽노필 선임기자',
'기자 김사과 취재 반하나',
'<h2>조깅에 스트레칭 더하면 ‘금상첨화’…최적 시간은 ‘4분’</h2>',
'이 기사는 임시 데이터임을 알립니다',
'<br> 이 기사는 건강 섹션으로 분류되었습니다 <br>',
'#기사 #건강 #조깅 #스트레칭']
예시 9)
# HTML 태그 제거 함수
def delete_html(context):
preprocessed_context = [ ]
for text in context:
text = re.sub(r'<[%>]+Ws+(?=<)|<[^>]+>', '', text).strip()
preprocessed_context.append(text)
return preprocessed_context
preprocessed_context = delete_html(preprocessed_context)
preprocessed_context
-->
'https://doi.org/10.1007/s40279-024-02143-9',
'Optimising the Dose of Static Stretching to Improve Flexibility: A Systematic Review, Meta-analysis and Multivariate Meta-regression. Sports Med (2024).',
'곽노필 선임기자',
'기자 김사과 취재 반하나',
'조깅에 스트레칭 더하면 ‘금상첨화’…최적 시간은 ‘4분’',
'이 기사는 임시 데이터임을 알립니다',
'이 기사는 건강 섹션으로 분류되었습니다',
'#기사 #건강 #조깅 #스트레칭']
예시 10)
# 해시 태그 제거 함수
def delete_hashtag(context):
preprocessed_context = [ ]
for text in context:
text = re.sub(r'#\w+', '', text).strip()
preprocessed_context.append(text)
return preprocessed_context
preprocessed_context = delete_hashtag(preprocessed_context)
preprocessed_context
-->
'정보',
'https://doi.org/10.1007/s40279-024-02143-9',
'Optimising the Dose of Static Stretching to Improve Flexibility: A Systematic Review, Meta-analysis and Multivariate Meta-regression. Sports Med (2024).',
'곽노필 선임기자',
'기자 김사과 취재 반하나',
'조깅에 스트레칭 더하면 ‘금상첨화’…최적 시간은 ‘4분’',
'이 기사는 임시 데이터임을 알립니다',
'이 기사는 건강 섹션으로 분류되었습니다',
'']
예시 1)
문장 분리 설치 kss
#문장 분리
!pip install kss
예시 2)
import kss
# kss(Korean Sentence Splitter)를 사용하여 문장을 분리하는 함수
def sentence_seperator(context):
splited_context = [] # 분리된 문장을 저장할 리스트
# context 리스트의 각 문장에 대해 반복
for text in context:
text = text.strip() # 앞뒤 공백 제거 (불필요한 공백 방지)
if text: # 빈 문자열이 아닐 경우에만 처리
splited_text = kss.split_sentences(text) # 문장 단위로 분리
splited_context.extend(splited_text) # 리스트에 분리된 문장 추가
return splited_context # 문장 단위로 분리된 텍스트 리스트 반환
# 문장 분리 함수 실행 (전처리된 텍스트를 문장 단위로 분리)
preprocessed_context = sentence_seperator(preprocessed_context)
# 분리된 문장을 인덱스와 함께 출력
for i, text in enumerate(preprocessed_context):
print(i, text)
--->
0 유연성을 높여주는 최적의 스트레칭 시간은 4분이라는 연구 결과가 나왔다.
1 사진은 연구진이 생활 스트레칭으로 권하는 ‘허벅지 뒤쪽 근육(햄스트링) 펴주기’ 동작이다.
2 픽사베이
3 (☞한겨레 뉴스레터 H:730 구독하기. 검색창에 ‘한겨레 h730’을 쳐보세요.)
4 건강을 위해 운동을 한다고 심폐 기능이나 근력 같은 신체 능력을 강화하는 운동만 해선 안 된다.
5 굳은 근육을 풀어주는 스트레칭도 병행해야 더 좋은 효과를 볼 수 있다.
6 스트레칭의 가장 기본적인 효과는 우리 몸에 있는 관절의 작동 범위를 넓혀주는 데서 나온다.
7 이렇게 하면 몸의 유연성이 높아져 신체 활동력이 좋아지고 부상 위험도 줄어든다.
8 또 혈액 순환과 자세 교정에도 도움이 되는 등 다양한 효과가 있다.
9 보통 스트레칭이라 하면 일정 시간 동안 특정 부위의 근육을 늘린 상태를 유지해주는 정적 스트레칭을 말한다.
10 스트레칭은 어떤 강도로 얼마나 오랫 동안, 얼마나 자주 하는 것이 좋을까?
11 유산소 및 무산소 운동과 달리 스트레칭에 대해선 아직 뚜렷한 권고 지침이 나와 있지 않다.
12 사우스오스트레일리아대 연구진이 2023년 한 해 동안 전 세계에서 발표된 연구 결과를 분석한 결과를 토대로, 최적의 효과를 볼 수 있는 스트레칭 기준을 찾아내 국제학술지 ‘스포츠의학’에 발표했다.
13 유연성이 떨어지는 사람은 유연성이 높은 사람에 비해 스트레칭 해야 할 근육이 더 많으므로 더 많은 시간을 투자해야 한다.
14 사진은 연구진이 생활 스트레칭으로 권하는 ‘허벅지 앞쪽 근육(대퇴사두근) 펴주기’ 동작이다.
15 픽사베이
16 강도나 횟수보다 전체 시간 중요
17 분석 대상으로 삼은 연구들은 스트레칭을 하지 않은 사람들과 한 번 또는 여러번 정적 스트레칭을 한 사람들의 유연성을 비교한 것들이다.
18 분석 결과, 유연성을 그 자리에서 높여주는 최적의 스트레칭 시간은 4분이었다.
19 4분 이상 스트레칭을 한다고 해서 더 좋은 효과를 보지는 못하는 것으로 나타났다.
20 그러나 높은 유연성을 계속해서 유지하려면 더 오랫동안 스트레칭을 해줘야 한다.
21 연구진은 일주일에 10분 정도 할 경우 최고의 효과를 볼 수 있는 것으로 나타났다고 밝혔다.
22 연구진은 그러나 스트레칭을 한꺼번에 몰아서 할 필요는 없다고 덧붙였다.
23 통증을 느낄 정도로 스트레칭을 강하게 하는 것이 더 효과가 있을까?
24 언뜻 그럴 것으로 생각하기 쉽다.
25 하지만 연구진은 스트레칭의 강도는 중요하지 않다고 밝혔다.
26 통증을 느낄 정도로 강하게 하는 스트레칭이나 그렇지 않은 스트레칭이나 모두 유연성을 높여줬다는 것이다.
27 스트레칭 횟수도 그다지 중요하지 않은 것으로 나타났다.
28 횟수보다 중요한 것은 전체 시간이었다.
29 연구진은 스트레칭이 필요한 근육 부위에 대해 일주일에 10분 정도씩 스트레칭을 해주는 것을 권했다.
30 예컨대 매일 1분여씩 할 수도 있고, 일주일에 두 차례 5분씩 할 수도 있다.
31 전체적인 스트레칭 시간은 스트레칭이 필요한 근육의 수에 따라 달라진다.
32 유연성이 떨어지는 사람은 유연성이 높은 사람에 비해 스트레칭 해야 할 근육이 더 많으므로 더 많은 시간을 투자해야 한다.
33 스트레칭으로 굳은 몸을 푸는 것은 하루를 시작하고 마무리하는 아주 좋은 방법이다.
34 사진은 연구진이 생활 스트레칭으로 권하는 ‘삼두근 펴주기’ 동작이다.
35 corelens/Canva
36 연구진이 권하는 기본 스트레칭 3가지
37 연구진은 연구자 매체 ‘더 컨버세이션’ 기고를 통해 “스트레칭의 효과는 나이나 성별에 관계없이 유연성을 높이는 데 도움이 된다”며 언제 어디서나 아무런 장비 없이 할 수 있는 운동인만큼 스트레칭으로 굳은 몸을 푸는 것은 하루를 시작하고 마무리하는 아주 좋은 방법이라고 강조했다.
38 연구진은 이와 함께 일상 생활에서 필요한 스트레칭으로 세 가지를 권했다.
39 첫째는 허벅지 뒤쪽 근육(햄스트링)을 펴주는 동작이다.
40 벤치나 의자 등받이에 한 쪽 발을 올려놓고 무릎을 곧게 편 상태에서 허리를 앞으로 숙인다.
41 둘째는 허벅지 앞쪽 근육(대퇴사두근)을 펴주는 동작이다.
42 한 쪽 무릎을 구부려 발목을 엉덩이에 댄 뒤, 한 손으로 발목을 잡고 무릎을 최대한 당겨준다.
43 이 동작을 할 때는 서 있는 동안 몸의 균형을 잡을 수 있도록 다른 한 손으로 책상이나 의자 등을 잡고 있는 게 좋다.
44 셋째는 삼두근을 펴주는 동작이다.
45 두 팔을 올려 머리 뒤쪽에서 팔꿈치를 마주 보게 구부린 뒤 한쪽 팔을 뻗어 다른 쪽 팔을 당겨준다.
46 정보
47 https://doi.org/10.1007/s40279-024-02143-9
48 Optimising the Dose of Static Stretching to Improve Flexibility: A Systematic Review, Meta-analysis and Multivariate Meta-regression.
49 Sports Med (2024).
50 곽노필 선임기자
51 기자 김사과 취재 반하나
52 조깅에 스트레칭 더하면 ‘금상첨화’…최적 시간은 ‘4분’
53 이 기사는 임시 데이터임을 알립니다
54 이 기사는 건강 섹션으로 분류되었습니다
8. 유사도 측정 실습
예 1)
sen_1 = '오늘 점심에 배가 너무 고파서 밥을 너무 많이 먹었다'
sen_2 = '오늘 점심에 배가 고파서 밥을 많이 먹었다'
sen_3 = '오늘 배가 너무 고파서 점심에 밥을 너무 많이 먹었다'
sen_4 = '오늘 점심에 배가 고파서 지하철을 많이 먹었다'
sen_5 = '어제 저녁에 밥을 너무 많이 먹었더니 배가 부르다'
sen_6 = '이따가 오후 6시에 출발하는 비행기가 3시간 연착되었다고 하네요'
예 2)
# training_documents에 문장을 담음
training_documents = [sen_1, sen_2, sen_3, sen_4, sen_5, sen_6]
# training_documents을 text로 정의
for text in training_documents:
print(text)
-->
오늘 점심에 배가 너무 고파서 밥을 너무 많이 먹었다
오늘 점심에 배가 고파서 밥을 많이 먹었다
오늘 배가 너무 고파서 점심에 밥을 너무 많이 먹었다
오늘 점심에 배가 고파서 지하철을 많이 먹었다
어제 저녁에 밥을 너무 많이 먹었더니 배가 부르다
이따가 오후 6시에 출발하는 비행기가 3시간 연착되었다고 하네요
예 3)
# CountVectorizer 클래스는 텍스트 데이터를 단어의 개수(빈도) 기반으로 벡터화하는 도구
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer() # CountVectorizer 객체를 생성
# fit 메서드를 사용하여 training_documents(학습용 문서)를 분석
# 해당 문서에서 고유한 단어들을 학습(어휘 사전 구축)
vectorizer.fit(training_documents)
--->
예 4)
word_idx = vectorizer.vocabulary_ # 학습된 단어 사전(어휘집)을 딕셔너리 형태로 저장
word_idx # 단어별 인덱스를 출력
-->
{'오늘': 13,
'점심에': 17,
'배가': 8,
'너무': 3,
'고파서': 2,
'밥을': 7,
'많이': 4,
'먹었다': 5,
'지하철을': 18,
'어제': 11,
'저녁에': 16,
'먹었더니': 6,
'부르다': 9,
'이따가': 15,
'오후': 14,
'6시에': 1,
'출발하는': 19,
'비행기가': 10,
'3시간': 0,
'연착되었다고': 12,
'하네요': 20}
예 5)
# word_idx를 idx 순서대로 정렬
for key, idx in sorted(word_idx.items()):
print(f'{key} : {idx}')
--->
3시간 : 0
6시에 : 1
고파서 : 2
너무 : 3
많이 : 4
먹었다 : 5
먹었더니 : 6
밥을 : 7
배가 : 8
부르다 : 9
비행기가 : 10
어제 : 11
연착되었다고 : 12
오늘 : 13
오후 : 14
이따가 : 15
저녁에 : 16
점심에 : 17
지하철을 : 18
출발하는 : 19
하네요 : 20
예 6)
import pandas as pd
# word_idx에 따라 dataframe을 생성
# 컬럼 : key, 인덱스 : 문장 idx, 값: 빈도수
result = [] # 각 문장의 단어 빈도수를 저장할 리스트
vocab = list(word_idx.keys()) # word_idx의 key(단어)를 리스트로 변환하여 어휘 목록 생성
# 각 문서(문장)에 대해 단어 빈도수를 계산
for i in range(len(training_documents)): # 문서 개수만큼 반복
result.append([]) # 새로운 문서의 단어 빈도수를 저장할 리스트 추가
d = training_documents[i] # 현재 문서(문장) 가져오기
for j in range(len(vocab)): # 어휘집에 있는 모든 단어에 대해 반복
target = vocab[j] # 현재 확인할 단어
result[-1].append(d.count(target)) # 문서에서 해당 단어의 등장 횟수를 세어 리스트에 추가
예 7)
tf_ = pd.DataFrame(result, columns = vocab)
tf_
--->
예 8)
# 각 문장을 CountVectorizer를 사용하여 벡터화
# toarray()[0]를 사용하여 numpy 배열 형태로 변환
# 각 문장을 벡터화하여 배열로 변환
vector_sen_1 = vectorizer.transform([sen_1]).toarray()[0]
vector_sen_2 = vectorizer.transform([sen_2]).toarray()[0]
vector_sen_3 = vectorizer.transform([sen_3]).toarray()[0]
vector_sen_4 = vectorizer.transform([sen_4]).toarray()[0]
vector_sen_5 = vectorizer.transform([sen_5]).toarray()[0]
vector_sen_6 = vectorizer.transform([sen_6]).toarray()[0]
print(vector_sen_1)
print(vector_sen_2)
print(vector_sen_3)
print(vector_sen_4)
print(vector_sen_5)
print(vector_sen_6)
--->
[0 0 1 2 1 1 0 1 1 0 0 0 0 1 0 0 0 1 0 0 0]
[0 0 1 0 1 1 0 1 1 0 0 0 0 1 0 0 0 1 0 0 0]
[0 0 1 2 1 1 0 1 1 0 0 0 0 1 0 0 0 1 0 0 0]
[0 0 1 0 1 1 0 0 1 0 0 0 0 1 0 0 0 1 1 0 0]
[0 0 0 1 1 0 1 1 1 1 0 1 0 0 0 0 1 0 0 0 0]
[1 1 0 0 0 0 0 0 0 0 1 0 1 0 1 1 0 0 0 1 1]
예 9)
# 코사인 기반 유사도
import numpy as np
from numpy import dot
from numpy.linalg import norm
def cos_sim(A, B):
return dot(A, B) / (norm(A) * norm(B))
예 10)
# sen_1 = '오늘 점심에 배가 너무 고파서 밥을 너무 많이 먹었다'
# sen_2 = '오늘 점심에 배가 고파서 밥을 많이 먹었다'
# 조사 생략 후 문장 벡터 간 코사인 유사도 계산 및 출력
f'sen_1, sen_2 : {cos_sim(vector_sen_1, vector_sen_2)}'
--->
sen_1, sen_2 : 0.7977240352174656
예 11)
# sen_1 = '오늘 점심에 배가 너무 고파서 밥을 너무 많이 먹었다'
# sen_3 = '오늘 배가 너무 고파서 점심에 밥을 너무 많이 먹었다'
# 순서 변경 후 문장 벡터 간 코사인 유사도 계산 및 출력
f'sen_1, sen_3 : {cos_sim(vector_sen_1, vector_sen_3)}'
-->
sen_1, sen_3 : 1.0
예 12)
# sen_2 = '오늘 점심에 배가 고파서 밥을 많이 먹었다'
# sen_4 = '오늘 점심에 배가 고파서 지하철을 많이 먹었다'
# 문장 내 단어를 임의의 단어로 치환한 문장
f'sen_2, sen_4 : {cos_sim(vector_sen_2, vector_sen_4)}'
--->
sen_2, sen_4 : 0.857142857142857
예 13)
# sen_1 = '오늘 점심에 배가 너무 고파서 밥을 너무 많이 먹었다'
# sen_5 = '어제 저녁에 밥을 너무 많이 먹었더니 배가 부르다'
# 의미는 다르지만 비슷한 주제를 가지는 문장
f'sen_1, sen_5 : {cos_sim(vector_sen_1, vector_sen_5)}'
--->
sen_1, sen_5 : 0.5330017908890261
예 14)
# sen_1 = '오늘 점심에 배가 너무 고파서 밥을 너무 많이 먹었다'
# sen_6 = '이따가 오후 6시에 출발하는 비행기가 3시간 연착되었다고 하네요'
# 의미가 서로 다른 문장
f'sen_1, sen_6 : {cos_sim(vector_sen_1, vector_sen_6)}'
--->
sen_1, sen_6 : 0.0
예 15)
# TF-IDF 기반 행렬을 활용한 문장 간 유사도 측정
from sklearn.feature_extraction.text import TfidfVectorizer # TF-IDF 벡터화를 위한 라이브러리 임포트
tfidfv = TfidfVectorizer().fit(training_documents) # training_documents를 학습하여 TF-IDF 어휘 사전 생성
예 16)
# 학습된 TF-IDF 어휘 사전(vocabulary)을 정렬하여 출력
for key, idx in sorted(tfidfv.vocabulary_.items()): # 단어(키) 기준으로 정렬
print(f'{key} : {idx}') # 단어와 해당 단어의 인덱스 출력
-->
3시간 : 0
6시에 : 1
고파서 : 2
너무 : 3
많이 : 4
먹었다 : 5
먹었더니 : 6
밥을 : 7
배가 : 8
부르다 : 9
비행기가 : 10
어제 : 11
연착되었다고 : 12
오늘 : 13
오후 : 14
이따가 : 15
저녁에 : 16
점심에 : 17
지하철을 : 18
출발하는 : 19
하네요 : 20
예 17)
# 학습된 TF-IDF 벡터라이저를 사용하여 training_documents를 TF-IDF 행렬로 변환
tf_idf = tfidfv.transform(training_documents).toarray()
# 변환된 TF-IDF 행렬 출력
print(tf_idf)
--->
[[0. 0. 0.28941449 0.67547293 0.24993256 0.28941449
0. 0.28941449 0.24993256 0. 0. 0.
0. 0.28941449 0. 0. 0. 0.28941449
0. 0. 0. ]
[0. 0. 0.39248775 0. 0.33894457 0.39248775
0. 0.39248775 0.33894457 0. 0. 0.
0. 0.39248775 0. 0. 0. 0.39248775
0. 0. 0. ]
[0. 0. 0.28941449 0.67547293 0.24993256 0.28941449
0. 0.28941449 0.24993256 0. 0. 0.
0. 0.28941449 0. 0. 0. 0.28941449
0. 0. 0. ]
[0. 0. 0.34642121 0. 0.29916243 0.34642121
0. 0. 0.29916243 0. 0. 0.
0. 0.34642121 0. 0. 0. 0.34642121
0.58392899 0. 0. ]
[0. 0. 0. 0.29913919 0.22136971 0.
0.43208699 0.25633956 0.22136971 0.43208699 0. 0.43208699
0. 0. 0. 0. 0.43208699 0.
0. 0. 0. ]
[0.35355339 0.35355339 0. 0. 0. 0.
0. 0. 0. 0. 0.35355339 0.
0.35355339 0. 0.35355339 0.35355339 0. 0.
0. 0.35355339 0.35355339]]
예 18)
# TF-IDF 행렬에서 얻어지는 유사도의 값을 0~1로 스케일링
def l1_normalize(v):
norm = np.sum(v)
return v / norm
예 19)
# TF-IDF 벡터라이저 생성
tfidf_vectorizer = TfidfVectorizer()
# training_documents를 TF-IDF 행렬로 변환
tfidf_matrix_l1 = tfidf_vectorizer.fit_transform(training_documents)
# L1 정규화를 적용한 TF-IDF 행렬 생성
tfidf_norm_l1 = l1_normalize(tfidf_matrix_l1)
# 정규화된 TF-IDF 행렬 출력
tfidf_norm_l1
-->
<6x21 sparse matrix of type '<class 'numpy.float64'>'
with 46 stored elements in Compressed Sparse Row format>
예 20)
# 각 문장의 L1 정규화된 TF-IDF 벡터를 추출하여 NumPy 배열로 변환
# 여섯번째 까지 문장의 벡터
tf_sen_1 = tfidf_norm_l1[0:1].toarray()
tf_sen_2 = tfidf_norm_l1[1:2].toarray()
tf_sen_3 = tfidf_norm_l1[2:3].toarray()
tf_sen_4 = tfidf_norm_l1[3:4].toarray()
tf_sen_5 = tfidf_norm_l1[4:5].toarray()
tf_sen_6 = tfidf_norm_l1[5:6].toarray()
print(tf_sen_1)
print(tf_sen_2)
print(tf_sen_3)
print(tf_sen_4)
print(tf_sen_5)
print(tf_sen_6)
-->
[[0. 0. 0.01807927 0.04219575 0.0156129 0.01807927
0. 0.01807927 0.0156129 0. 0. 0.
0. 0.01807927 0. 0. 0. 0.01807927
0. 0. 0. ]]
[[0. 0. 0.0245181 0. 0.02117334 0.0245181
0. 0.0245181 0.02117334 0. 0. 0.
0. 0.0245181 0. 0. 0. 0.0245181
0. 0. 0. ]]
[[0. 0. 0.01807927 0.04219575 0.0156129 0.01807927
0. 0.01807927 0.0156129 0. 0. 0.
0. 0.01807927 0. 0. 0. 0.01807927
0. 0. 0. ]]
[[0. 0. 0.0216404 0. 0.01868821 0.0216404
0. 0. 0.01868821 0. 0. 0.
0. 0.0216404 0. 0. 0. 0.0216404
0.03647714 0. 0. ]]
[[0. 0. 0. 0.01868676 0.01382862 0.
0.0269918 0.01601313 0.01382862 0.0269918 0. 0.0269918
0. 0. 0. 0. 0.0269918 0.
0. 0. 0. ]]
[[0.02208593 0.02208593 0. 0. 0. 0.
0. 0. 0. 0. 0.02208593 0.
0.02208593 0. 0.02208593 0.02208593 0. 0.
0. 0.02208593 0.02208593]]
예 21)
# 유클리디안 거리 기반 유사도 측정
# 두 점(벡터) 사이의 직선 거리를 측정하여 유사도를 판단하는 방법
from sklearn.metrics.pairwise import euclidean_distances
# 문장 간 유클리디안 거리 계산 및 출력
# 각 문장 사이의 거리
print(euclidean_distances(tf_sen_1, tf_sen_2))
print(euclidean_distances(tf_sen_1, tf_sen_3))
print(euclidean_distances(tf_sen_2, tf_sen_4))
print(euclidean_distances(tf_sen_1, tf_sen_5))
print(euclidean_distances(tf_sen_1, tf_sen_6))
-->
[[0.04527262]]
[[0.]]
[[0.04446567]]
[[0.06917355]]
[[0.08834373]]
예 22)
# 맨하탄 거리(Manhattan Distance) 기반 유사도 측정
# 축을 따라 이동하는 방식(격자 형태)으로 두 벡터 간 거리를 측정
from sklearn.metrics.pairwise import manhattan_distances
# 문장 간 맨하탄 거리 계산 및 출력
# 각 문장 사이의 거리
print(manhattan_distances(tf_sen_1, tf_sen_2))
print(manhattan_distances(tf_sen_1, tf_sen_3))
print(manhattan_distances(tf_sen_2, tf_sen_4))
print(manhattan_distances(tf_sen_1, tf_sen_5))
print(manhattan_distances(tf_sen_1, tf_sen_6))
-->
[[0.08551076]]
[[0.]]
[[0.07747632]]
[[0.209428]]
[[0.34050538]]
'자연어 처리 > 자연어 처리' 카테고리의 다른 글
6. RNN(Recurrent Neural Network, RNN) (0) | 2025.02.06 |
---|---|
5. CNN Text Classification (0) | 2025.02.06 |
4. 신경망 기반의 벡터화 (2) | 2025.02.05 |
2. IMDB Dataset를 활용한 데이터 전처리 (0) | 2025.01.24 |
1. 자연어 처리 (2) | 2025.01.23 |