1. 교육처 : 넥스트아이티교육센터(대전)
2. 프로젝트 내용 : 이전에 Spring 과제에서 만들었던 펀딩 사이트의 데이터를 활용하여 추천 시스템을 만들었다. 사용자가 찜한 펀딩 데이터를 기반으로 userbase와 contentbase로 유저가 좋아할 만한 펀딩을 추천하도록 했다. 여기서 만든 추천 리스트를 이후에 flask를 사용해서 홈 화면으로 보내주었다.
3. 과정 중 특이점 : contentbase에서 자신이 찜한 펀딩에 대한 개인 선호도가 없어서 비슷한 카테고리만 추천을 하는 부분이 아쉬웠고 다음번에는 좀 더 데이터가 다양한 내용으로 만들어야겠다고 생각했다. 최소한 별점이라도 있었다면 조금 더 좋았을 텐데... 팀프로젝트에서는 이 부분을 좀 더 신경써야겠다.
4. 화면 및 코드
1) DB에 더미데이터 만들기
회원이 찜을 했을 때 저장하는 mem_like 테이블에 더미데이터를 넣어서 사용자가 찜한 데이터를 임의로 만들었다
TRUNC(DBMS_RANDOM.VALUE(1,405))를 활용해서 랜덤하게 숫자를 넣고
CONNECT BY LEVEL <= 40 으로 들어갈 갯수를 조절하였다. 한 번에 40개씩 넣을 수 있어서 완전 편했음
INSERT INTO mem_like(like_no, mem_id, fu_no)
SELECT fu_seq.nextval,'qwer',TRUNC(DBMS_RANDOM.VALUE(1,405)) AS RANDOM_NUM
FROM dual
CONNECT BY LEVEL <= 40;
2) userbase : 자신과 비슷한 펀딩을 고른 유저가 찜한 펀딩 중 내가 찜한 펀딩을 제외한 나머지로 리스트를 만든다.
import pandas as pd
import mydb
from sklearn.metrics.pairwise import cosine_similarity
def get_user_recomment(userId):
db = mydb.Mydb()
sql = """
SELECT
mem_id , a.fu_no , fu_title , fu_cate, fu_like
FROM mem_like a, funding b
WHERE a.fu_no = b.fu_no
"""
df_funding = pd.read_sql(sql, con=db.conn)
df_funding.rename(columns={'MEM_ID': 'userId'}, inplace=True)
df_funding.rename(columns={'FU_NO': 'fu_no'}, inplace=True)
df_funding.rename(columns={'FU_TITLE': 'title'}, inplace=True)
df_funding.rename(columns={'FU_CATE': 'category'}, inplace=True)
df_funding.rename(columns={'FU_LIKE': 'like'}, inplace=True)
user_funding = df_funding.pivot_table('like', index='userId', columns='title')
user_funding.fillna(0, inplace=True)
user_base_metric = cosine_similarity(user_funding)
user_base_metric_df = pd.DataFrame(data=user_base_metric, index=user_funding.index
,columns=user_funding.index)
def get_user_base(id, df_fundings, user_base_metric_df):
sim_user = user_base_metric_df[id].sort_values(ascending=False)[:3]
user_like_funding = df_funding[df_funding['userId'] == userId]
user_like = set(user_like_funding['fu_no'].values.tolist())
id_list = sim_user.index.tolist()[1:]
data=[]
for i in id_list:
print(f'user: {i}')
item = get_user_item(i, id, df_fundings)
data = data + item
set_item = set(data) - user_like
return set_item
def get_user_item(id, userId, df_funding):
funding_list = df_funding[df_funding['userId'] == id]
best = funding_list.sort_values(by='like', ascending=False)[:4]
return best['fu_no'].values.tolist()
id = userId
result = get_user_base(str(id), df_funding, user_base_metric_df)
print(f'userbase: {result}')
funosql = """
SELECT fu_title, (fu_like)/10 as fu_like, fu_no, fu_cate, fu_amount, fu_img
FROM funding
WHERE fu_no= :1
"""
temp = []
for i in result:
user_recommend = db.get_select_param(funosql, [i])
temp.append(user_recommend[0])
print(temp)
result = pd.DataFrame(temp, columns=['title', 'like', 'fu_no', 'category', 'cnt', 'fu_img'])
return result
3) contentbase : 내가 찜한 펀딩과 비슷한 펀딩을 가지고 와서 리스트를 만든다. 별점이 없어서 찜한 펀딩 내에서 선호도를 구별해내지 못한 점이 아쉬웠다.
import pandas as pd
import mydb
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.feature_extraction.text import CountVectorizer
def get_cate_recomment(userId):
db = mydb.Mydb()
def get_imdbs_score(p_x, p_m, p_c):
p_v = p_x['cnt']
p_r = p_x['like']
return (p_v / (p_v + p_m) * p_r) + (p_m / (p_m + p_v) * p_c)
sql = """
SELECT fu_title , (fu_like)/10 as fu_like , fu_no , fu_cate, fu_amount, fu_img
FROM funding
"""
df_funding = pd.read_sql(sql, con=db.conn)
df_funding.fillna(0, inplace=True)
df_funding.rename(columns={'FU_TITLE': 'title'}, inplace=True)
df_funding.rename(columns={'FU_LIKE': 'like'}, inplace=True)
df_funding.rename(columns={'FU_NO': 'fu_no'}, inplace=True)
df_funding.rename(columns={'FU_AMOUNT': 'cnt'}, inplace=True)
df_funding.rename(columns={'FU_CATE': 'category'}, inplace=True)
df_funding.rename(columns={'FU_IMG': 'fu_img'}, inplace=True)
m = df_funding['cnt'].quantile(0.1)
m_data = df_funding.copy().loc[df_funding['cnt'] >= m]
c = m_data['like'].mean()
m_data['score'] = m_data.apply(get_imdbs_score, args=(m, c), axis=1)
m_data['category'] = m_data['category']
m_data.reset_index(drop=True, inplace=True)
count_vetor = CountVectorizer(ngram_range=(1, 1))
category_vector = count_vetor.fit_transform(m_data['category'])
AA = category_vector.toarray()
gensim_sim = cosine_similarity(category_vector, category_vector).argsort()[:, ::-1]
def get_contentbase_funding(data, d_sim, title, top=20):
target_movie_index = data[data['title'] == title].index.values
sim_index = d_sim[target_movie_index, :top].reshape(-1)
sim_index = sim_index[sim_index != target_movie_index]
result = data.iloc[sim_index].sort_values('score', ascending=False)[:9]
print(f'contentbase : {result}')
return result
titlesql = """
SELECT rnum,fu_title
FROM (SELECT rownum as rnum, fu_title
FROM (SELECT fu_title
FROM mem_like a , funding b
WHERE a.fu_no = b.fu_no
AND mem_id = :1
AND fu_cate = (SELECT fu_cate
FROM (SELECT fu_cate , count(fu_cate) as caterank
FROM mem_like a , funding b
WHERE a.fu_no = b.fu_no
AND a.mem_id = :1
group by fu_cate
ORDER BY caterank desc)
WHERE rownum < 2)
order by DBMS_RANDOM.RANDOM
) a
) b
WHERE rnum=1
"""
ranktitle = db.get_select_param(titlesql, [userId])
ranktitle = ranktitle[0]
text = ranktitle[1]
temp = get_contentbase_funding(m_data, gensim_sim, text)
result = temp.sample(frac=1).reset_index(drop=True)
return result
'파이썬' 카테고리의 다른 글
파이썬 프로젝트(3) : flask로 파이썬에서 Spring으로 데이터 보내기 (0) | 2022.11.23 |
---|---|
파이썬 프로젝트(2) : KoalaNLP으로 키워드 추출해내기 (0) | 2022.09.23 |
파이썬 : 멜론 일간 차트 크롤링하여 엑셀에 저장하기 (0) | 2022.07.26 |
파이썬 : 입력한 숫자만큼 로또 번호 출력하기 (0) | 2022.07.22 |
댓글