250x250
Notice
Recent Posts
Recent Comments
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- r
- 이력서
- spring MVC(모델2)방식
- word2vec
- 방식으로 텍스트
- 크롤링
- pytorch
- 코사인 유사도
- 과학백과사전
- 파이썬
- 네이버뉴스
- test
- 幼稚园杀手(유치원킬러)
- java
- 지마켓
- Topics
- jsp 파일 설정
- mysql
- 토픽추출
- 게시판 만들기
- db
- (깃)git bash
- Python
- oracle
- RESFUL
- tomoto
- Websocket
- 자바
- lda
- Gmarket
Archives
- Today
- Total
무회blog
python: 200629-gensim_bm25-Copy1, BM25Okapi 본문
In [381]:
import codecs
from gensim.corpora.dictionary import Dictionary
# from gensim.summarization import bm25
# from gensim.summarization.bm25 import get_bm25_weights
import os
import re , pandas as pd
from nltk.corpus import stopwords
from nltk.tokenize import sent_tokenize ,word_tokenize
In [382]:
### %pip install rank-bm25
### BM25Okapi 방식
from rank_bm25 import BM25Okapi
corpus = [
"Hello there good man!",
"It is quite windy in London",
"How is the weather today?"
]
tokenized_corpus = [doc.split(" ") for doc in corpus]
bm25 = BM25Okapi(tokenized_corpus)
# query = "windy London"
query = "weather"
tokenized_query = query.split(" ")
print(bm25.get_scores(tokenized_query))
print(bm25.get_top_n(tokenized_query, corpus, n=1))
# ['It is quite windy in London']
In [384]:
## # step_4, 공통 코드 , 텍스트 클리닝
def text_cleaning(text):
#이모티콘 제거
EMOJI = re.compile('[\U00010000-\U0010ffff]', flags=re.UNICODE)
text= EMOJI.sub(r'', text)
#이메일 주소 제거
email =re.compile('([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)')
text = email.sub('', text)
#URL 제거
url =re.compile('(http|ftp|https)://(?:[-\w.]|(?:%[\da-fA-F]{2}))+')
text = url.sub('', text)
#HTML 제거
html =re.compile('<[^>]*>')
text = html.sub('', text)
#특수문자를 공백으로 대체(문장을 살리기위헤 마침표는 남겨둠)
#special =re.compile('[^\w\s]')
#text = special.sub(' ', text)
special= ['*', '{', ',', ':', ']', '$', '+', '[', '#', '(', '%', '&', '}', '`', '‘', '’','·',
'=', ';', '>','>', '/', '"', '“', '”', '\\', '?', '~', "'", '<', ')', '^', '!', '_',
'|', '@','@','©','ⓒ', '℗','®','①', '-','▶','…','☞','▲','◆','■'] #'.', 빼고
for chr in special :
text=text.replace(chr,' ')
################################## gensim 사용을 위한 정규표현식 200624
hangul_path9 = '[가-힣]+\.' # 한글로 포함되다 .
hangul_path0 = '[가-힣]+\.[가-힣]{1}' # 한글 . + 한글 처리
hangul_path1 = '[가-힣]+\.[\d]{1}' # 한글 . + 숫자 처리 [0-9]
hangul_path2 = '[가-힣]+\.[a-z]{1}' # 한글 . + 영어 소문자
hangul_path3 = '[가-힣]+\.[A-Z]{1}' # 한글 . + 영어 대문자
hangul_path4 = '[가-힣]+\.[\S]{1}' # 한글 . + 비공백 [^ \t\n\r\f\v]와 같다.
hangul_path5 = '[가-힣]+\.[\s]{1}' # 한글 . + 공백 [ \t\n\r\f\v]와 같다.
hangul_path6 = '[가-힣]+\.[\W]{1}' # 한글 . + 숫자 + 문자가 아닌 것 [^a-zA-Z0-9]와 같다.
hangul_path7 = '[가-힣]+\.[\w]{1}' # 한글 . + 숫자 + 문자 [a-zA-Z0-9]와 같다.
hangul_path8 = '[가-힣]+\.[\b]{1}' # 한글 . + 단어 경계 (`\w`와 `\W`의 경계)
reg_path = hangul_path0 + '|' + hangul_path1 + '|'+ hangul_path2 + '|'+ hangul_path3 + '|'+ hangul_path4+ '|'+ hangul_path5
hangul = re.compile(reg_path) # 한글 + 모모로 포함되다 .
result = hangul.findall(text) # 정규식에 일치되는 부분을 리스트 형태로 저장, 단어 반환
result = list(set(result))
for x in result:
text = text.replace(x, x[:-1] + ' \n' + x[-1:])
text = re.sub('\[.+?\]','', text) # 대괄호 [] 이내 모든 문자 삭제
################################## gensim 사용을 위한 정규표현식 200624
#특수문자 제거 후 생기는 중복된 공백 제거
while text.find(' ') > 0:
text = text.replace(' ',' ' ) # 중복된 공백 제거
#특수문자 제거 후 생기는 중복된 개행 제거
while text.find('\n\n') > 0:
text = text.replace('\n\n','\n' ) # 중복된 개행 제거
# .텍스트 -> ".텍스트" -> ". 텍스트"
#좌우측 공백 삭제
text = text.strip()
# 좌측 공백 삭제
# text.lstrip()
# 우측 공백 삭제
#text.rstrip()
return text
In [388]:
### gensim 의 소스
import math
from six import iteritems
from six.moves import xrange
# BM25 parameters.
PARAM_K1 = 1.5
PARAM_B = 0.75
EPSILON = 0.25
class BM25(object):
def __init__(self, corpus):
self.corpus_size = len(corpus)
self.avgdl = sum(map(lambda x: float(len(x)), corpus)) / self.corpus_size
self.corpus = corpus
self.f = []
self.df = {}
self.idf = {}
self.initialize()
def initialize(self):
for document in self.corpus:
frequencies = {}
for word in document:
if word not in frequencies:
frequencies[word] = 0
frequencies[word] += 1
self.f.append(frequencies)
for word, freq in iteritems(frequencies):
if word not in self.df:
self.df[word] = 0
self.df[word] += 1
for word, freq in iteritems(self.df):
self.idf[word] = math.log(self.corpus_size - freq + 0.5) - math.log(freq + 0.5)
def get_score(self, document, index, average_idf):
score = 0
for word in document:
if word not in self.f[index]:
continue
idf = self.idf[word] if self.idf[word] >= 0 else EPSILON * average_idf
score += (idf * self.f[index][word] * (PARAM_K1 + 1)
/ (self.f[index][word] + PARAM_K1 * (1 - PARAM_B + PARAM_B * self.corpus_size / self.avgdl)))
return score
def get_scores(self, document, average_idf):
scores = []
for index in xrange(self.corpus_size):
score = self.get_score(document, index, average_idf)
scores.append(score)
return scores
### 가중치를 구해준다 .
def get_bm25_weights(corpus):
bm25 = BM25(corpus)
average_idf = sum(map(lambda k: float(bm25.idf[k]), bm25.idf.keys())) / len(bm25.idf.keys())
weights = []
for doc in corpus:
scores = bm25.get_scores(doc, average_idf)
weights.append(scores)
return weights
In [423]:
## 对目录下的所有文本进行预处理,构建字典
dirname = './news002/bm25/'
result = []
corpus = []
filenames = []
for root,dirs,files in os.walk(dirname):
for f in files:
f = root+f # 경로 + 파일명
with open(f, 'r', encoding='utf-8') as f:
text = f.read()
texts = text_cleaning(text)
corpus.append(word_tokenize(texts))
text = text_cleaning(text)
text = sent_tokenize(text)
print(text)
print('-'*50)
filenames.append(text)
dictionary = corpora.Dictionary(corpus)
print(dictionary)
In [424]:
## doc2bow , 모든 중복되는 단어의 빈도수를 구한다 .
## vec1 , 첫번째 doc_vectors 의 중복되는 단어의 빈도수를 구한다 .
## vec1_sorted , vec1 의 디센딩을 구한다 .
## for , vec1_sorted 의 상위 5개를 뽑아낸다 .
doc_vectors = [dictionary.doc2bow(text) for text in corpus]
vec1 = doc_vectors[0]
vec1_sorted = sorted(vec1,reverse=True)
vec1_sorted
for term, freq in vec1_sorted[:5]:
print(dictionary[term])
bm25Model = BM25(corpus)
# result = get_bm25_weights(corpus)
# print('result 가중치 : {}'.format(result))
In [425]:
average_idf = sum(map(lambda k: float(bm25Model.idf[k]), bm25Model.idf.keys())) / len(bm25Model.idf.keys())
query_str = '흘러갈 활동하시고 활발하게'
query = []
for word in query_str.strip().split():
print(word)
query.append(word)
scores = bm25Model.get_scores(query,average_idf)
idx = scores.index(max(scores)) # 0 번재에 가장 높은 값이 있음
fname = filenames[idx]
fname
Out[425]:
In [426]:
list1 = ['physics', 'chemistry', 'maths']
print ('Index of chemistry', list1.index('chemistry'))
# print ('Index of C#', list1.index('C#'))
'Python' 카테고리의 다른 글
200701-yoyag_test_010, 요약뉴스처리,파이썬, 전처리 (0) | 2020.07.01 |
---|---|
200624-파이썬_004.010_headless_결측치제거_ddf_yoyag_cnt추가_news (0) | 2020.06.30 |
200625-yoyag_test_008-006.002, 젠심 요약본뉴스 (0) | 2020.06.25 |
python: # python 200623-yoyag_test_008-005 (0) | 2020.06.24 |
파이썬 정규표현식 관련, 범위지정 삭제, 수정 (0) | 2020.06.24 |
Comments