336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

다섯 번째 프로젝트

 

1. 추천 시스템에 대한 생각

2. 추천시스템(TFIDF, Word2Vec)

3. GUI로 앱처럼 사용할 수 있게 (PyQt5)


항상 과정이 비슷해서 앞에 부분은 코드는 생략합니다.

 

우선 로그인이 필요한 서비스라서 동적 크롤링으로 후기를 긁어왔다. 그리고 추가로 병원 이름, 클리닉명, 주소, 링크, 전화번호는 로그인 없이도 크롤링이 가능해서 BS4로 긁어왔다. 과정은 크롤링한 데이터를 전처리하고, 워드클라우드를 생성해서 불용어를 처리하고(중요), 하나의 문장으로 합쳤다.  

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from scipy.io import mmwrite, mmread #매트릭스 저장할 때 mmwrite, 읽을 땐 mmread
import pickle #변수 타입 그대로 저장
 
df_review_one_sentence = pd.read_csv('./preprocess/total_hospital_review_one_sentence.csv', index_col=0)
print(df_review_one_sentence.info())
 
Tfidf = TfidfVectorizer(sublinear_tf=True)      # sublinear_tf는 값의 스무딩 여부를 결정하는 파라미터
Tfidf_matrix = Tfidf.fit_transform(df_review_one_sentence['reviews'])       # fit_transform 된 Tfidf를 갖고 있으면 추후 데이터 추가 가능하므로 따로 저장
 
with open('./models/tfidf.pickle''wb'as f:
    pickle.dump(Tfidf, f)       # Tfidf 저장
 
mmwrite('./models/tfidf_hospital_review.mtx', Tfidf_matrix)        # 유사도 점수 매트릭스 저장
cs

TfidfVectorizer로 문서 내에서 단어 토큰을 생성하고, 각 단어의 수와 가중치를 조정하여 문자를 순서 벡터로 변환했다. 이 과정은 따로 건드리는 부분이 없다. 다만 데이터 전처리가 중요하다.

 

 

 

 

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
31
import pandas as pd
from sklearn.metrics.pairwise import linear_kernel
from scipy.io import mmwrite, mmread
import pickle
from gensim.models import Word2Vec
 
df_hospital_review_one_sentence = pd.read_csv('./preprocess/total_hospital_review_one_sentence.csv', index_col=0)       # 리뷰 읽어 df 생성
 
Tfidf_matrix = mmread('./models/tfidf_hospital_review.mtx').tocsr()        # matrix 불러오기
with open('./models/tfidf.pickle''rb'as f:      # tfidf 불러오기
    Tfidf = pickle.load(f)
 
def getRecommendation(cosine_sim):      # 코사인 유사도롤 활용하여 유사한 병원 추천하는 함수
    simScore = list(enumerate(cosine_sim[-1]))      # 각 코사인 유사도 값에 인덱스 붙임
    simScore = sorted(simScore, key=lambda x:x[1], reverse=True)        # simScore(코사인 유사도, x[1])가 큰 것부터 정렬. reverse=True 내림차순 정렬.
    simScore = simScore[1:11]       # 유사한 병원 10개 리스트. 0번 값은 자기 자신이므로 배제.
    hospital_idx = [i[0for i in simScore]     # 인덱스(i[0]) 뽑아서 리스트 생성
   recHospitalList = df_hospital_review_one_sentence.iloc[hospital_idx]        # df에서 해당 병원 리스트 추출
    return recHospitalList
 
 
#병원명 검색
hospital_idx = df_hospital_review_one_sentence[df_hospital_review_one_sentence['names']=='김이비인후과의원'].index[0]      # 병원 이름으로 인덱스 값 찾기
# hospital_idx = 127
# print(df_review_one_sentence.iloc[hospital, 0])
 
cosine_sim = linear_kernel(Tfidf_matrix[hospital_idx], Tfidf_matrix)      # linear_kernel은 각 Tfidf 값을 다차원 공간에 벡터(방향과 거리를 가짐)로 배치한 뒤, 코사인 유사도를 구해줌. cosine = 삼각형의 밑변 / 윗변
                                                                       # 비슷한 영화는 유사한 위치에 배치됨. 유사할수록 각이 줄어드므로 코사인 값이 1에 가까워짐. -1에 가까울수록 반대, 0에 가까울수록 무관
recommendation = getRecommendation(cosine_sim)
# print(recommendation)
print(recommendation.iloc[:, 1])
cs

pickle에 저장한 Tfidf를 불러와서 코사인 유사도를 활용하여 유사한 병원을 추천해준다. 우선 병원의 idx 값을 구한다. 그리고 추천시스템에 이와 유사한 병원들의 리스트를 반환 받아서 출력한다.

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import pandas as pd
from gensim.models import Word2Vec
 
review_word = pd.read_csv('./preprocess/total_cleaned_review.csv', index_col=0)
print(review_word.info())
cleaned_token_review = list(review_word['cleaned_sentences'])
print(len(cleaned_token_review))
cleaned_tokens = []
count = 0
for sentence in cleaned_token_review:
    token = sentence.split(' ')     # 띄어쓰기 기준으로 각 단어 토큰화
    cleaned_tokens.append(token)
# print(len(cleaned_tokens))
# print(cleaned_token_review[0])
# print(cleaned_tokens[0])
embedding_model = Word2Vec(cleaned_tokens, vector_size=100, window=4,
                           min_count=20, workers=4, epochs=100, sg=1)   # vector_size는 몇차원으로 줄일지 지정, window는 CNN의 kernel_size 개념, 앞뒤로 고려하는 단어의 개수를 나타냄
                                                                        # min_count는 출현 빈도가 20번 이상인 경우만 word track에 추가하라는 의미(즉, 자주 안 나오는 단어는 제외)
                                                                        # workers는 cpu 스레드 몇개 써서 작업할 건지 지정, sg는 어떤 알고리즘 쓸건지 지정
embedding_model.save('./models/word2VecModel_hospital.model')
print(embedding_model.wv.vocab.keys())
print(len(embedding_model.wv.vocab.keys()))
cs

Word2Vec 단어의 의미를 다차원에 분산시켜 표현하여, 단어간 위치를 파악해서 유사도를 분석해준다. Skip-Gram의 경우 중심 단어를 보고 주변에 어떤 단어가 있을지 예측. CBoW는 주변에 있는 단어들로 중간에 있는 단어를 예측한다.

 

 

 

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#리뷰 기반 키워드 검색
embedding_model = Word2Vec.load('./models/word2VecModel_hospital.model')
key_word = '친절'
 
sim_word = embedding_model.wv.most_similar(key_word, topn=10)
labels = []
sentence = []
for label, _ in sim_word:
    labels.append(label)
print(labels)
for i, word in enumerate(labels):
    sentence += [word] * (9-i)
sentence = ' '.join(sentence)
#sentence = [key_word] * 10      # tf에서 높은 값을 가지도록 리스트 복사
print(sentence)
 
sentence_vec = Tfidf.transform([sentence])
cosine_sim = linear_kernel(sentence_vec, Tfidf_matrix)
recommendation = getRecommendation(cosine_sim)
print(recommendation)
cs

키워드를 기반으로 하여 병원을 추천해주는 시스템이다.

 

 

+ Recent posts