부스트코스의 "머신러닝을 위한 파이썬" 강좌 필기 내용
https://www.boostcourse.org/ai222/lecture/253409/?isDesc=false
텍스트 마이닝 실습 코드로
문서의 유사도를 측정하는 모듈 작성
import os
'''
로직 :
문자 => 벡터와 숫자로 표현
방식은 원핫인코딩 / bag of words => 각각의 단어별로 인덱스를 부여해서 한 문장의 단어 개수를 표현할 수 있다
벡터화된 문자들의 유사도를 거리로 측정할 수 있다
유사도 측정에는 유클리드 거리, 코사인 유사도 측정
=> 코사인 유사도가 더 많이 쓰이고 적중률이 높음
프로세스 :
- 파일을 불러오기
- 파일 읽어서 단어 사전 만들기
- 단어별로 index 만들기
- 만들어진 인덱스로 문별로 bag of words vector를 생성
- 비교하고자 하는 문서 비교하기
- 얼마나 맞는지 측정하기
=> 첫번째 문서와 나머지 문서의 유사도 측정
=> 같은거 축구 혹은 야구에 대한 유사한 문서 뽑기
'''
def get_file_list(dir_name):
return os.listdir(dir_name)
def get_conetents(file_list):
y_class = []
X_text = []
class_dict = {
1: "0", 2: "0", 3:"0", 4:"0", 5:"1", 6:"1", 7:"1", 8:"1"} # 0은 야구 , 1은 축구
for file_name in file_list:
try:
f = open(file_name, "r", encoding="cp949") # cp949 = 윈도우로 작성된 파일 열 때
category = int(file_name.split(os.sep)[1].split("_")[0]) # 카테고리 값은 파일명 제일 앞에 있는 숫자
y_class.append(class_dict[category]) # 0과 1일때 구분해서 y값으로 넣어준다
X_text.append(f.read())
f.close()
except UnicodeDecodeError as e:
print(e)
print(file_name)
return X_text, y_class # 각각 40개, 총 80개 반환해줌 = > x에는 텍스트, y에는 숫자 = 카테고리 값이 들어가게 됨
def get_cleaned_text(text): # 의미 없는 문장 부호등은 제거한다
import re
text = re.sub('\W+','', text.lower() ) # 문장부호를 없애고 소문자로 만드는 함수
return text
def get_corpus_dict(text):
text = [sentence.split() for sentence in text] # 80개의 document가 들어있는데 단어 개수대로 잘려져 있음 = 2 dimentional
clenad_words = [get_cleaned_text(word) for words in text for word in words] # 텍스트에서 단어들을 뽑아 오고, 그 단어들에서 word를 다시 한글자씩 뽑아서 1차원 array로 바꿔준다
from collections import OrderedDict
corpus_dict = OrderedDict()
for i, v in enumerate(set(clenad_words)): # 단어와 인덱스 값을 각각 뽑아줌
corpus_dict[v] = i
return corpus_dict
def get_count_vector(text, corpus):
text = [sentence.split() for sentence in text]
word_number_list = [[corpus[get_cleaned_text(word)] for word in words] for words in text] # 똑 같은 방식으로 전처리 해서 다시 corupus에 넘겨서 인덱스와 밸류 값으로 받을 수 있게 됨
X_vector = [[0 for _ in range(len(corpus))] for x in range(len(text))] # 80개의 문서에 대해서 4302 벡터 스페이스를 만들어주는 방식
# 언더바를 쓰면 이 변수를 쓰지 않고 모두 0으로 채워주는 코드
for i, text in enumerate(word_number_list): # 모두 0으로 채워진 행렬에 인덱스 값을 가져오면서 올려줌
for word_number in text:
X_vector[i][word_number] += 1
return X_vector
import math
def get_cosine_similarity(v1,v2): #첫번째 문서와 두번째 문서에 대한 유사도 계산
"compute cosine similarity of v1 to v2: (v1 dot v2)/{||v1||*||v2||)"
sumxx, sumxy, sumyy = 0, 0, 0
for i in range(len(v1)):
x = v1[i]; y = v2[i]
sumxx += x*x
sumyy += y*y
sumxy += x*y
return sumxy/math.sqrt(sumxx*sumyy)
def get_similarity_score(X_vector, source):
source_vector = X_vector[source]
similarity_list = []
for target_vector in X_vector:
similarity_list.append(
get_cosine_similarity(source_vector, target_vector))
return similarity_list # 1개의 문서와 80개를 각각 비교한 값
def get_top_n_similarity_news(similarity_score, n):
import operator
x = {i:v for i, v in enumerate(similarity_score)}
sorted_x = sorted(x.items(), key=operator.itemgetter(1))
return list(reversed(sorted_x))[1:n+1]
def get_accuracy(similarity_list, y_class, source_news):
source_class = y_class[source_news]
return sum([source_class == y_class[i[0]] for i in similarity_list]) / len(similarity_list)
if __name__ == "__main__":
dir_name = "news_data" # 뉴스데이터 파일에서 가져옴
file_list = get_file_list(dir_name) # 파일 리스트라는 리스트 타입 변수에 넣어둔다
file_list = [os.path.join(dir_name, file_name) for file_name in file_list] # os.path로 조인을 해주어야 슬래쉬와 역슬래쉬를 운영체제에 맞춰서 조인을 해줌 => 폴더명과 파일명 합쳐서 나옴 => 80개
X_text, y_class = get_conetents(file_list)
corpus = get_corpus_dict(X_text)
print("Number of words : {0}".format(len(corpus)))
X_vector = get_count_vector(X_text, corpus)
source_number = 10
result = []
for i in range(80):
source_number = i
similarity_score = get_similarity_score(X_vector, source_number)
similarity_news = get_top_n_similarity_news(similarity_score, 10) # 가장 유사한 거 10개를 뽑아오게 => accuracy 변수로 연결해줌
accuracy_score = get_accuracy(similarity_news, y_class, source_number)
result.append(accuracy_score)
print(sum(result) / 80)
하지만 실전에서는 이와 같이 코드를 짜서 하는 일은 거의 없고
Numpy와 Pandas만 이용하여도 쉽게 구현할 수 있다.
Scikit-learn의 Countvectorizer 를 이용하면 손쉽게 구현 가능.
from sklearn.feature_extraction.text import Countvectorizer
vectorizer = CountVectorizer()
corpus = [
'This is the first document.',
'This is the second second document.',
'And the third one.',
'Is this the first document?',
]
X = vectorizer.fit_transform(corpus)
X.toarray()
.
.
.
.
.
.
반응형
'Programming > Python' 카테고리의 다른 글
파이썬 넘파이 numpy 기초 문법 (0) | 2022.10.14 |
---|---|
파이썬 저장 경로 아주 쉽게 확인하는 법 (0) | 2022.10.14 |
파이썬으로 간단한 행렬 연산 / 선형대수 (0) | 2022.10.14 |
파이썬에서 자료구조(data structure)를 간단하게 다루도록 도와주는 모듈 (1) | 2022.10.14 |
파이쏘닉 Pythonic 코드 쓰는 법 (0) | 2022.10.14 |