정보검색 관련한 건데..

현재 MysqlDB에  한테이블에 1만개 정도의 인스턴스들이 존재합니다.

테이블은 word, doc_id, tf로 구성되어 있습니다.

word에는 단어 , doc_id는 그 단어가 나타난 문서, tf는 한 문서내에서 word가 나타난 횟수입니다.


문서는 대략 416개정도이고 단어는 1만개를 좀 넘습니다. 전체 행 개수는 14만개 정도 되네요..

위 테이블을 가지고 tf*idf값을 구해야 하는데.

처음에는 일일이 쿼리를 날려 값을 받아와 tf,idf값을 계산했는데... 이게 속도가 너무 느려서..

이번에는 DB의 모든 데이터를 가져와서 프로그램에서 이를 처리하려고 하고 있습니다... 그런데 이것도 만만치 않게 느리네요..


def print_high_rank(path):
with open(path, "w") as f:
con = pymysql.connect(host='localhost', #database 접속
user='root',
password='password',
db='index',
charset='utf8',
cursorclass=pymysql.cursors.DictCursor)

try: #sql쿼리
with con.cursor() as cur:
cur.execute('SELECT * FROM df') #db에서 모든 데이터 뽑아냄
table = cur.fetchall()

docs = set(sorted([doc["doc_id"] for doc in table])) #table에서 doc_id만 뽑아내어 정렬
doc_num = len(docs) #모든 문서의 수

for doc_id in docs: #doc_id순서로 문서 탐색
f.write("DOC ID : " + str(doc_id)+" ")
print('caculating : %s/%s', (str(doc_id), str(doc_num)))

#현재 문서에서 나타난 단어들 tf값 기준으로 내림차순 정렬
wordlist = sorted([word for word in table if word['doc_id'] == doc_id], key=lambda x: x['tf'], reverse=True)

max_tf = wordlist[0]['tf'] #현재 문서에서 최대 tf값
weight = {} #현재 문서에서 단어들의 weight(tf*idf)을 저장할 사전

for word in wordlist: #단어 탐색
df = len(set([doc['doc_id'] for doc in table if doc['word'] is word['word']])) #현재 단어가 나타난 문서들의 수 df
tf = 0.5+(0.5*word['tf']/max_tf) #tf값 정규화
idf = math.log10(doc_num/df) #idf = log(전체문서수 / df)
weight[word['word']] = tf*idf

for weight in sorted(weight.items(), key=operator.itemgetter(1), reverse=True)[:10]: #weight를 정렬하여 상위 10개만 탐색
term = weight[0].split(" ")
f.write(term[0] + ' ' + term[1] + " weight(tf*idf) : " + str(weight[1]) + " ")
f.write(' ')

except pymysql.Error as e: #SQL예외 발생
try:
print('MySQL Error [%d]: %s', (e.args[0], e.args[1]))
except IndexError:
print('MySQL Error: %s', str(e))

except Exception as e: #그 외 에러시 처리
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, exc_obj, "-", fname, exc_tb.tb_lineno, "line") #예외타입, 예외내용, 예외발생 파일, 예외발생 라인 출력

con.close() #db접속 종료


현재 tf*idf값을 구해서 각 문서별 tf*idf값을 기준으로 상위 10개만 파일에 출력하는 소스입니다.


처음에 tf값을 기준으로 상위 10개를 뽑아내면 될줄 알았는데.. 막상 해보니 idf값과 곱해지면서 가장큰 가중치를 모르는 문제가 있기에.

문서내 모든 단어에 대해서 tf,idf값을 구해서 정렬해야 되더군요. 그러더니 속도가 갑자기 확 떨어지는 문제가 발생했습니다.


이걸 어떻게 최적화 해야할까요??? 180개 문서에 대해 tf*idf값을 구하는데만 20분이 걸리네요... 전체가 416개인데...

환경은 CPU: i7 하스웰    램:8기가     운영체제:윈8.1     IDE:파이참