-- Data --/- 데이터 분석 -

[ kaggle ] cosmetics ecommerce 분석 : 추천 시스템 구현

녕녀기 2024. 7. 29. 14:49

목차

1. 개요

2. interaction score

3. 사용자 기반 협업 필터링

4. 잠재 요인 협업 필터링

5. 모델 비교 및 결론

6. 배운 점, 어려웠던 점


1. 개요

  • kaggle에서 제공되는 'cosmetics e Commerce' 이벤트 데이터를 사용하여, 제품을 추천하는 시스템을 구현하고자 함
  • 사용자의 제품 평가 점수가 존재하지 않으므로, 사용자와 제품의 이벤트 전환율에 따른 상호작용을 임의로 계산(interaction score)
  • interaction score와 코사인 유사도(cosine similarity)를 사용하여, 사용자 기반 협업 필터링(user based collaborative filtering) 구현
  • interaction score와 특이값 분해(SVD)로 행렬 분해하여, 잠재 요인 협업 필터링(latent factor collaborative filtering ) 구현

2. interaction score

추천 시스템을 구현하기 위해서는 사용자가 해당 제품에 대해 평점(explicit information)이 필요합니다. 하지만 해당 데이터는 제품에 대한 평점이 존재하지 않습니다. 따라서 사용자가 특정 제품을 구매했을 때 여러 이벤트를 가지고 임의의 interaction score 계산해서 추천 시스템에 사용하겠습니다.


분석에 사용하던 데이터는 2019년 10월부터 2022년 2월까지 기록을 담았습니다. 하지만 5개월치 데이터를 불러오는 시간이 오래 걸렸고, 계산 도중 Google Colab의 세션이 다운되는 일이 잦았습니다. 따라서, 해당 데이터 중 매출이 가장 높았던 2019년 11월 데이터만 사용해서 추천 시스템을 구현해 보겠습니다.

# 11월
df_con = csv_to_df('2019-Nov.csv')

# view의 quartile?

product_funnel = df_con.groupby(['product_id', 'event_type'])['user_session'].count()
product_funnel = product_funnel.reset_index(level=[0,1], drop=False)
product_funnel = product_funnel.pivot_table(index='product_id', columns='event_type', values='user_session', aggfunc='mean')

under_10 = product_funnel[product_funnel['view'] <= 10].index

product_funnel.describe(include='all')

 

Fig 1. 제품별 이벤트 통계치

 

위 코드와 Fig 1은 제품 id별 이벤트의 통계치를 나타냅니다. 한 달 동안 제품의 50%가 view 이벤트 발생이 15번도 되지 않는 것을 확인할 수 있습니다. view 이벤트를 boxplot으로 살펴봤을 때, 

Fig 2. view 이벤트의 boxplot

 

 

view 이벤트가 많이 발생하는 제품이 이상치로 보일만큼, 대부분의 제품의 view 이벤트 발생이 적습니다. view 이벤트 발생의 1사분위수에 해당하는 수만큼 view 이벤트가 발생했을 때, purchase 이벤트 발생을 살펴 보겠습니다.

# view 이벤트가 25%이하일 때 purchase 이벤트 발생?
under_25 = product_funnel[product_funnel['view'] == product_funnel.describe(include='all').loc['25%', 'view']]
under_25.replace({np.nan : 0}, inplace=True)

under_25.describe()

Fig 3. view 이벤트가 적을 때 purchase 이벤트 발생

 

view 이벤트 발생이 1사분위수 이하일 때 purchase 이벤트 발생은 거의 없다고 볼 수 있습니다. 관심조차 가지지 않는 제품(view 이벤트 발생 X)을 추천하는 것은 구매로 이어질 가능성이 낮다고 생각하므로, 해당 제품들은 추천에서 거의 배제해야 한다고 생각합니다.


사용자의 제품 구매 과정에서의 이벤트 전환율을 interaction score로 사용할 수 있는지 확인해 보겠습니다. 

funnel = df_con.groupby(['user_id','product_id', 'event_type'])['user_session'].count() # 사용자별, 제품 id별, 이벤트 타입별 grouping을 통한 count
funnel = funnel.reset_index(level=list(range(3)), drop=False)
funnel = funnel.pivot(index=['user_id', 'product_id'], columns='event_type', values='user_session')  # 단계별 퍼널 전환율을 구하기 위한 pivot
funnel.replace({np.nan : 0}, inplace=True)
funnel = funnel.reset_index(level=1, drop=False)

# 단계별 전환율 계산
funnel['cart_per_view'] = funnel.apply(lambda d : d['cart'] / d['view'] if d['view'] != 0 else 0, axis=1)
funnel['remove_per_cart'] = funnel.apply(lambda d : d['remove_from_cart'] / d['cart'] if d['cart'] != 0 else 0, axis=1)
funnel['purchase_per_view'] = funnel.apply(lambda d : d['purchase'] / d['view'] if d['view'] != 0 else 0, axis=1)

funnel[['cart_per_view', 'remove_per_cart', 'purchase_per_view']].describe()

 

cart 이벤트와 purchase 이벤트는 view 이벤트를 기준으로, remove_from_cart 이벤트는 cart 이벤트를 기준으로 전환율을 계산했습니다. 

Fig 4. 이벤트별 전환율

 

전환율임에도 불구하고, 1을 초과하는 제품이 있다는 것을 확인했습니다. 해당 제품들의 기록을 확인해 본 결과,

 

Fig 5. purchase 전환율이 3 이상인 제품

 

view 이벤트가 한 번이어도 purchase 이벤트가 여러 번 발생할 수 있다는 것을 확인했습니다. 이는 해당 제품을 여러 개 구매할 때, 해당 구매 기록에 제품 숫자를 기록하는 것이 아니라 구매한 숫자만큼 이벤트를 발생시킨다는 것으로 추측할 수 있습니다. 또한 어떤 제품은 view 이벤트 없이 cart 이벤트나 purchase 이벤트가 발생한 경우도 있는 만큼(이전 기간에 제품을 장바구니에 담아놨을 가능성이 존재), 전환율을 interaction score에 이용하기는 힘들 것으로 판단됩니다(∵통일성이 없이 기록된 이벤트 데이터를 어떤 규칙으로 통일하는 것에 대한 어려움이 존재).


그렇다면 제품별 기록에서 각 이벤트들이 차지하고 있는 비율을 interaction score로 이용하는 방안에 대해 생각해 보겠습니다. 

funnel['sum'] = funnel[['cart', 'purchase', 'remove_from_cart', 'view']].sum(axis=1)

# 제품별 이벤트의 비율 계산
funnel['rate_view'] = funnel.apply(lambda d : d['view'] / d['sum'] if d['sum'] != 0 else 0, axis=1)
funnel['rate_cart'] = funnel.apply(lambda d : d['cart'] / d['sum'] if d['sum'] != 0 else 0, axis=1)
funnel['rate_remove'] = funnel.apply(lambda d : d['remove_from_cart'] / d['sum'] if d['sum'] != 0 else 0, axis=1)
funnel['rate_purchase'] = funnel.apply(lambda d : d['purchase'] / d['sum'] if d['sum'] != 0 else 0, axis=1)

funnel[['rate_view','rate_cart', 'rate_remove', 'rate_purchase']].describe()

Fig 6. 제품별 이벤트의 비율

 

제품별 이벤트 비율로 계산했을 때 최대값이 1을 초과하지 않으므로 해당 비율을 interaction score의 기준으로 사용하겠습니다.


def conversion(df, rm_id, score : float = 0.01) :
  start_time = time.time()
  print('doing conversion...')
  ###########################
  funnel = df.groupby(['user_id','product_id', 'event_type'])['user_session'].count() # 사용자별, 제품 id별, 이벤트 타입별 grouping을 통한 count
  funnel = funnel.reset_index(level=list(range(3)), drop=False)
  funnel = funnel.pivot(index=['user_id', 'product_id'], columns='event_type', values='user_session')  # 단계별 퍼널 전환율을 구하기 위한 pivot
  funnel.replace({np.nan : 0}, inplace=True)
  funnel = funnel.reset_index(level=1, drop=False)

  funnel_o = funnel[~funnel['product_id'].isin(rm_id)]  # 25% quartile 보다 큰 제품만 추출
  funnel_x = funnel[funnel['product_id'].isin(rm_id)]  # 25% quartile 이하인 제품은 따로 저장

  # 각 이벤트 비율 계산

  funnel_o['sum'] = funnel_o[['cart', 'purchase', 'remove_from_cart', 'view']].sum(axis=1)

  funnel_o['rate_view'] = funnel_o.apply(lambda d : d['view'] / d['sum'] if d['sum'] != 0 else 0, axis=1)
  funnel_o['rate_cart'] = funnel_o.apply(lambda d : d['cart'] / d['sum'] if d['sum'] != 0 else 0, axis=1)
  funnel_o['rate_remove'] = funnel_o.apply(lambda d : d['remove_from_cart'] / d['sum'] if d['sum'] != 0 else 0, axis=1)
  funnel_o['rate_purchase'] = funnel_o.apply(lambda d : d['purchase'] / d['sum'] if d['sum'] != 0 else 0, axis=1)

  # 이벤트 비율에 따른 interaction score 계산

  def max_score(row) :
    if row['rate_purchase'] != 0 :
      return 5 * (1 + row['rate_purchase'])
    elif row['rate_purchase'] == 0 and row['rate_cart'] != 0 and row['rate_remove'] != 0 :
      return 2 * (1 + row['rate_cart']) - 0.5 * (1 + row['rate_remove'])
    elif row['rate_purchase'] == 0 and row['rate_cart'] != 0 and row['rate_remove'] == 0 :
      return 2 * (1 + row['rate_cart'])
    elif row['rate_purchase'] == 0 and row['rate_cart'] == 0 and row['rate_remove'] == 0 and row['rate_view'] != 0 :
      return row['rate_view']
    else :
      return 0

  funnel_o['interaction_score'] = funnel_o.apply(max_score, axis=1)

  funnel_o = funnel_o[['product_id','interaction_score']]

  funnel_x['interaction_score'] = score  # view 이벤트가 적은 제품은 값을 작게 설정
  funnel_x = funnel_x[['product_id','interaction_score']]

  funnel_all = pd.concat([funnel_o, funnel_x], axis=0)
  funnel_all = funnel_all.reset_index(level=0, drop=False)

  del funnel

  # pivoting
  fun_array = funnel_all.to_numpy()

  rows, row_pos = np.unique(fun_array[:, 0], return_inverse=True)
  cols, col_pos = np.unique(fun_array[:, 1], return_inverse=True)

  rows = list(map(int, rows))
  cols = list(map(int, cols))

  pivot_table = np.zeros((len(rows), len(cols)), dtype=fun_array.dtype)
  pivot_table[row_pos, col_pos] = fun_array[:, 2]

  print('array로....')

  funnel_all = pd.DataFrame(data = pivot_table, index=rows, columns=cols)

  #############################################
  end_time = time.time()
  print('finished!')
  print('operating time : ', round((end_time - start_time) / 60, 3),'min')

  return funnel_all

 

위 함수는 사용자별, 제품별 이벤트 수를 count 한 뒤 이벤트 비율을 계산해 비율별로 임의의 interaction score를 계산한 과정입니다.

 

해당 과정은

  1. 사용자별, 제품별로 이벤트를 count 한 뒤, view 이벤트 발생이 적은 제품은 interaction score 계산에서 잠시 제외
    • iew 이벤트 발생이 적은 제품 데이터를 drop 하지 않은 이유는 해당 제품을 구매한 사용자의 id도 같이 제거될 것을 우려(사용자 기반 협업 필터링은 사용자의 기록이 없으면 추천 불가능)
  2. 이벤트별로 임의의 점수를 부여
    • 각 점수는 이벤트 비율에 따라 최대 2배까지 계산될 수 있음( n * (1 + 이벤트 비율) )(n은 이벤트별 점수)
    • 각 이벤트 점수가 최대 2배로 계산돼도, 영향력이 더 높은 이벤트 점수를 초과하지 않음
    • purchase 이벤트는 5점 부과(최대 10점)
    • cart 이벤트는 2점 부과(최대 4점)
    • remove_from_cart 이벤트는 -0.5점 부과(최대 -1점)
      • 해당 이벤트를 감점으로 설정한 이유는, 장바구니에 담겼다가 제거된 제품에 대한 선호도가 장바구니에 담긴 후 제거되지 않은 제품의 선호도보다 낮다고 판단
    • view 이벤트는 비율을 점수로 사용
    • view 이벤트 발생이 적은 제품의 점수는 최소 수치로 적용(해당 함수에서는 0.01로 설정)
      • 해당 점수는 부서 협의에 따라 임의로 설정할 수 있음
  3. row를 사용자 id로, column을 제품 id인 pivot table 형성

해당 함수를 통해 interaction score를 적용한 '사용자 id - 제품 id' matrix를 형성했습니다.


3. 사용자 기반 협업 필터링

위에서 구한 matrix를 기반으로 코사인 유사도를 계산하겠습니다.

funnel.shape

# >> (368232, 43419)

 

위 데이터를 전부 사용하고 코사인 유사도를 계산했을 때, Colab 세션이 자주 다운되는 문제가 발생했습니다(Colab TPU 기준 RAM 사용량이 300GB를 초과함). 따라서 sklearn의 train_test_split을 사용하여 데이터의 10%만으로 계산해 보겠습니다. 

X_train, X_test = train_test_split(funnel, test_size=0.9, random_state=21)

print(X_train.shape)
print(X_test.shape)

# >> (36823, 43419)
# >> (331409, 43419)

 

그리고 코사인 유사도와 유사도를 바탕으로 제품을 추천하는 함수를 작성합니다.

class user_based_col :
  """
  코사인 유사도를 바탕으로 구현한 사용자 기반 협업 필터링 클래스입니다.
  """
  def __init__(self, R) :
    self.R = R

  def cosine_sim(self) :

    values = self.R.values

    # pandas to tensor
    tensor = torch.tensor(values).to(torch.float32)

    # 정규화
    norm_tensor = F.normalize(tensor, p=2, dim=1)

    # 코사인 유사도 계산
    cos_sim = torch.mm(norm_tensor, norm_tensor.t())

    cos_sim = pd.DataFrame(data = cos_sim, index = self.R.index, columns = self.R.index)

    self.cos_sim = cos_sim

    return self.cos_sim

  def recommender_sys(self, id : int, min_cos = 0.5, similarity = None) :
    if similarity == None :
      pass
    else :
      self.cos_sim = similarity

    start_time = time.time()

    # 유저의 상호작용 점수 리스트
    user_df = self.R.loc[id]

    # 위 리스트에서 관심이 없던 제품 추출
    not_purchase = user_df[user_df==0].index

    # 유저의 코사인 유사도 리스트
    user_cs = self.cos_sim.loc[id]

    item_score = {}

    for i in not_purchase :

        # 구매 안 한 제품 id에서 점수가 부여된 유저 id 추출
        id_purchase = self.R[self.R[i] > 0].index

        if len(id_purchase) >= 10 :

          # 해당 제품의 점수와 코사인 유사도를 곱한 후 전부 더함
          sum_score = sum(user_cs.loc[d] * self.R.loc[d, i] for d in id_purchase)
          # 코사인 유사도를 전부 더함
          sum_cosine_sim = sum(user_cs.loc[d] for d in id_purchase)

          if (sum_cosine_sim != 0) and (sum_score / sum_cosine_sim > 5) and (sum_cosine_sim >= min_cos):

            if sum_cosine_sim != 0 :
                item_score[i] = sum_score / sum_cosine_sim
            else :
                item_score[i] = 0

    item_score = dict(sorted(item_score.items(), key=lambda x : x[1], reverse=True))

    item_score = pd.DataFrame({'product_id' : item_score.keys()
                                , 'expected score' : item_score.values()})

    item_score = item_score.head(10)

    end_time = time.time()

    end_start = end_time - start_time

    print(f'추천 시간 : {round(end_start / 60, 3)} min')

    return item_score

 

해당 과정은

  1. 코사인 유사도 계산
    • interaction score matrix를, pandas dataframe에서 pytorch tensor로 변환
    • 변환된 tensor를 L2 정규화를 한 후, 정규화된 tensor와 transpose된 tensor와의 행렬 곱을 진행
  2. 제품 추천
    • 사용자의 id 입력
    • interaction score matrix에서 점수가 0인 제품을 추출
    • 위 제품의 점수가 존재하는 다른 사용자의 코사인 유사도와 점수를 곱한 후 전부 더함( SUM(코사인 유사도 * 점수) )
    • 위 제품의 점수가 존재하는 다른 사용자의 코사인 유사도를 전부 더함 ( SUM(코사인 유사도) )
    • { SUM(코사인 유사도 * 점수) / SUM(코사인 유사도) } 계산을 통해 예측 점수 제공
      • 다른 사용자와 적어도 10번 이상 상호작용한 제품 + SUM(코사인 유사도)가 최소치를 만족하는 제품 + 예측 점수가 5점 이상인 제품만 추천
    • 점수가 높은 상위 10개의 제품 추천

 

위 함수를 통해 사용자 id가 514497069인 사용자에게 제품을 추천해 보겠습니다.

# 코사인 유사도의 합이 최소 0.5일 때 추천 목록

ubcf = user_based_col(R=X_train)

ubcf.cosine_sim()

ubcf_rc = ubcf.recommender_sys(id=514497069)

ubcf_rc

Fig 7. 코사인 유사도 합이 최소 0.5 일 때 추천 목록 (추천 시간 : 1.075 min)
Fig 8. 코사인 유사도 합이 최소 0.7 일 때 추천 목록 (추천 시간 : 0.904 min)

 

코사인 유사도의 최소 기준이 달라질 때마다 추천되는 제품이 다른 것을 확인할 수 있습니다. 두 기준 모두 가장 추천하고 싶은 제품은 5754853 제품입니다.

 


4. 잠재 요인 협업 필터링

위에서 구한 interaction score를 기반으로 SVD로 행렬 분해해, 사용자가 상호작용하지 않은 제품의 score를 예측해 보겠습니다.

class latent_factor_col :

  def __init__(self, R) :

    self.R = R

  def matrix_for_svd(self) :

    R_new = self.R.copy().replace({0 : np.nan})

    # 결측치가 있는 위치 저장
    nan_positions = R_new.isna()

    mean_col = R_new.mean(axis=0)  # 각 컬럼의 평균값

    mean_col = mean_col.replace({np.nan : 0})

    R_new.fillna(mean_col, inplace=True)   # 결측치를 각 컬럼의 평균값으로 대체

    mean_row = R_new.mean(axis=1)  # 각 행의 평균값

    R_new['mean_row'] = mean_row  # 각 행의 평균값을 계산한 컬럼

    new_columns = [c for c in R_new.columns if c != 'mean_row']

    for c in new_columns :

        R_new[c] = R_new[c] - R_new['mean_row']  # 각 컬럼에서 행 평균값을 뺌

    R_new.drop(labels='mean_row', axis=1, inplace=True)

    self.nan_positions = nan_positions
    self.mean_col = mean_col
    self.mean_row = mean_row
    self.R_new = R_new

    return self.R_new

  def recommender_svd(self, id : int, k=10) :
    # svd를 통해 행렬 분해
    # U_tr = 사용자 행렬
    # s_tr = 특이값 행렬
    # Vt_tr = 제품 행렬

    U_tr, s_tr, Vt_tr = svds(A = self.R_new.values, k = k)

    s_mat = np.diag(s_tr)

    tsvd_pred = np.dot(np.dot(U_tr, s_mat), Vt_tr)

    pred = pd.DataFrame(data=tsvd_pred, index = self.R_new.index, columns = self.R_new.columns)

    ########################################################################

    pred['mean_row'] = self.mean_row.copy()  # 각 행의 평균값을 계산한 컬럼

    new_columns = [c for c in pred.columns if c != 'mean_row']

    for c in new_columns :

        pred[c] = pred[c] + pred['mean_row']  # 각 컬럼에서 행 평균값을 다시 더함

    pred.drop(labels='mean_row', axis=1, inplace=True)

    start_time = time.time()

    # 추천받고자 하는 사용자의 interaction score
    series_id = self.R.loc[id]

    # 사용자와 상호작용이 없던 제품의 id
    product_idx = self.R.loc[id][self.R.loc[id] == 0].index

    item_score = {}

    for i in tqdm(product_idx) : 
      users = self.R[i]
      
      min_num_users = users[users >= 5].shape[0]

      # 사용자 구매가 최소 10번은 일어난
      if min_num_users >= 10 : 

        if pred.loc[id, i] >= 5:

          item_score[i] = pred.loc[id, i]

    item_score = dict(sorted(item_score.items(), key=lambda x : x[1], reverse=True))

    item_score = pd.DataFrame({'product_id' : item_score.keys()
                                , 'expected score' : item_score.values()})

    item_score = item_score.head(10)

    end_time = time.time()

    end_start = end_time - start_time

    print(f'추천 시간 : {round(end_start / 60, 3)} min')

    return item_score

 

해당 과정은

  1. SVD를 위해 matrix 조정
    • 상호작용이 이뤄지지 않은 위치에 컬럼 평균으로 대체
    • 그 이후 행의 평균값을 뺌
  2. SVD를 통한 행렬 분해
    • 사용자 행렬 - 특이값 행렬 - 제품 행렬로 행렬 분해(k=10)
    • 분해된 행렬을 다시 곱하여 유사 행렬로 만듦
    • 만들어진 행렬에 1번에서 계산된 행 평균값을 다시 더해줌
  3. 제품 추천
    • 사용자의 id 입력
    • interaction score matrix에서 점수가 0인 제품을 추출
    • 다른 사용자와 적어도 10번 이상 상호작용한 제품 + 예측 점수가 5점 이상인 제품만 추천
    • 점수가 높은 상위 10개의 제품 추천

위 함수를 통해 사용자 id가 514497069인 사용자에게 제품을 추천해 보겠습니다.

lfcf = latent_factor_col(R=X_train)

lfcf.matrix_for_svd()

rec = lfcf.recommender_svd(id=514497069)

rec

# >> 추천 시간 : 0.472 min

Fig 9. k=10 일 때 추천 목록 (추천 시간 : 0.472 min)

 

행렬 분해 협업 필터링이 추천해 주는 제품은 5853712 제품 입니다.


5. 모델 비교 및 결론

<장단점>

  • 사용자 기반 협업 필터링(코사인 유사도 사용)(Memory-Based Approch)
    • 장점 : 쉽게 만들 수 있음. 결과의 설명력이 좋음. 도메인에 의존적이지 않음
    • 단점 : 데이터가 계속 축적되거나, sparse하면 성능이 낮음. 확장 가능성이 낮음(데이터가 많으면 속도 저하)
  • 잠재 요인 협업 필터링(SVD 사용)(Model-Based Approach)
    • 장점 : Sparse한 데이터도 처리 가능
    • 단점 : 결과의 설명력이 낮음

실제로 두 모델을 비교했을 때 사용자 기반 협업 필터링은 추천까지 약 1분, 잠재 요인 협업 필터링은 약 30초의 시간이 소요되는 것을 알 수 있습니다. 다른 사용자에게 제품 추천에 시간이 오래 걸린다면, 제품에 대한 구매 의사 타이밍과 맞지 않을 수도 있기 때문에(해당 제품을 구매할 가능성도 낮아질 것) 속도 측면에서는 잠재 요인 협업 필터링이 나은 방법이라고 생각이 듭니다.

 

해석의 측면에서는 확실히 사용자 기반 협업 필터링이 더 나은 방법이라고 여겨집니다. 사용자 기반 협업 필터링을 화장품 산업에서 생각해 봤을 때, 비슷한 피부 타입 or 비슷한 브랜드 선호도를 가지는 사용자가 사용하는 다른 제품은 추천 받은 사용자에게도 적합할 수 있는 것입니다. 

 

두 모델이 추천해 준 제품의 purchase 이벤트 발생 수와 매출을 비교해 보면

Fig 10. 두 모델이 추천해 준 제품 비교

 

사용자 기반 협업 필터링이 추천해 준 제품은 잠재 요인 협업 필터링이 추천해 준 제품보다 purchase 수도 높고, purchase 당 매출도 높은 것을 확인할 수 있습니다. 5754853 제품은 5853712 제품보다 추천 받은 사용자의 취향과 비교적 일치할 가능성이 높고 인기가 많은 제품으로 추측되기에, 구매 확률이 조금 더 높다고 예상할 수 있습니다.

 

반면 5853712 제품은 추천된 이유를 해석할 수 없는 문제가 존재하지만, 5853712 제품이 의의로 사용자 취향과 일치할 가능성이 있기 때문에, 두 모델에 대한 테스트를 고려할 필요가 있다고 생각합니다.


6. 배운 점, 어려웠던 점

6-1. 배운 점

추천 시스템을 한번 구현을 통해 서비스 내 사용자의 참여도를 높이고 경험의 질을 올릴 수 있는 방법에 대해 공부해 볼 수 있었습니다. 공부를 하면서 협업 필터링과 딥러닝이 추천 시스템에 많이 사용되는 것을 알 수 있었는데, 기회가 된다면 딥러닝으로도 추천 시스템을 구현해 보고 싶습니다.

 

Numpy와 PyTorch의 사용법을 익힐 수 있는 좋은 시간이었습니다. 예전에는 주로 Pandas와 sklearn 계산을 주로 했었는데, 시간이 오래 걸리는 단점이 있었습니다. 

Fig 11. PyTorch로 계산한 코사인 유사도 연습
Fig 12. Numpy로 계산한 코사인 유사도 연습

 

Fig 13. sklearn으로 계산한 코사인 유사도 연습

 

하지만 특정 계산 영역에 Numpy와 PyTorch를 사용함으로써 계산 시간을 줄일 수 있었습니다. 앞으로도 분석 과정에서 계산 시간을 줄일 수 있도록, 두 라이브러리 연습을 열심히 하도록 하겠습니다.

6-2. 어려웠던 점

Colab 사용에 어려움을 겪었습니다. 예전 분석에서는 데이터 용량이 크지 않다보니, 로컬에서 쉽게 작업할 수 있었습니다. 그러나 이번 데이터는 0.3 ~ 1.5 Gbyte의 데이터를 계산하다보니, Colab에서 TPU로 작업하지 않으면 작업이 불가능했었습니다. 심지어 Colab에서 작업을 할 때도 할당된 리소스 안에서 작업을 해야 하기 때문에, RAM 허용량에서 돌아가도록 코드를 짜야 했습니다. 물론 덕분에 Numpy를 좀 더 공부하게 됐고, PyTorch 라이브러리를 사용해 보는 좋은 경험이 됐습니다. 또한 한정된 작업 영역에서 작업하는 방법도 익힌 것 같습니다.


참조

https://blog.naver.com/bycho211/221804613549

 

근접 문자열 매칭 (Approximate String Matching)

* 근접 문자열 매칭 (Approximate String Matching) - 유사한 문자열을 찾는 기술 ※ 근접 문자열 매칭...

blog.naver.com

https://kmhana.tistory.com/31

 

추천 시스템 기본 - 협업 필터링(Collaborative Filtering) - ①

*크롬으로 보시는 걸 추천드립니다* 우리 일상생활에 녹아있는 "인공지능(AI)"에는 추천 시스템이 있다는 것을 소개해 드렸습니다 https://kmhana.tistory.com/30 Have A Nice AI kmhana.tistory.com 이제 부터는 조

kmhana.tistory.com

https://data-science-hi.tistory.com/82

 

SVD 를 활용한 협업필터링

협업필터링은 메모리 기반과 모델 기반으로 나뉜다고 했다. 근데 여기서 모델기반 중 클러스터링 기법, 행렬 축소 기법, 딥러닝 기법이 있는데 이번 장에서는 행렬 축소 기법 중 하나인 SVD(특잇

data-science-hi.tistory.com

https://medium.com/@toprak.mhmt/collaborative-filtering-3ceb89080ade

 

Collaborative Filtering

In this blog, I’ll be covering a recommender system technique called collaborative filtering. So let’s get started. Collaborative…

medium.com

https://big-dream-world.tistory.com/69

 

4. 행렬 분해를 이용한 잠재요인 협업 필터링

< 목차 > 용어정의 행렬 분해의 이해 확률적 경사하강법(SGD)를 이용한 행렬 분해 확률적 경사하강법(SGD) 활용예제 행렬 분해를 이용한 개인화 영화 추천시스템 개발 1. 용어정의 피드백 후 작성예

big-dream-world.tistory.com

https://www.kaggle.com/code/luthien5921/ecommerce-neural-net-for-recommendation-system

 

eCommerce: Neural Net for Recommendation System

Explore and run machine learning code with Kaggle Notebooks | Using data from eCommerce Events History in Cosmetics Shop

www.kaggle.com

https://www.kaggle.com/code/sarasaber22/online-shop-with-svd

 

online shop with SVD

Explore and run machine learning code with Kaggle Notebooks | Using data from eCommerce Events History in Cosmetics Shop

www.kaggle.com

 

- Hui Fang, Danning Zhang, Yiheng Shu, Guibing. (2020). "Deep Learning for Sequential Recommendation : Algorithms, Influential Factors, and Evaluations". 『ACM Transactions on Information Systems (TOIS)』, 39(1), 1-42. doi.org/10.1145/3426723

 

- Gawesh Jawaheer, Peter Weller, Patty Kostkova. (2014). "Modeling User Preferences in Recommender Systems : A Classification Framework for Explicit and Implicit User Feedback". 『 ACM Transactions on Interactive Intelligent Systems (TiiS)』, 4(2), 1-26. doi.org/10.1145/2512208