6.2 특잇값 분해 평점 예측

기준선 추정과 특잇값 분해를 사용한 예측 평점 계산은 기준선 추정으로 추정된 평점 기준선과 원본 평점의 잔차 데이터를 특잇값 분해하여 나온 사용자와 아이템의 특징 벡터와 특잇값 벡터로 예측 평점을 계산하여 추천하는 방법을 살펴봅니다.

6.2.1 수식 살펴보기

여기에서는 SVD 기반 협업 필터링 추천에서 기준선 추정과 특잇값 분해를 사용한 예측 평점에 대한 수식을 살펴봅니다.

6.2.1.1 평점 기준선 추정

평점 데이터는 3장에서 살펴본 바와 같이, 사용자가 아이템에 매기는 평점은 사용자와 아이템 사이에서 이루어진 관계와 특성으로 사용자가 어떤 기준과 성향에 따라 평점을 매기는지에 따라 달라집니다. 기준선 추정( Baseline Estimates)은 사용자가 선호하는 특정 아이템에 대한 평점을 후하게 주거나, 특정 아이템이 특히 후한 평점을 받는 경우와 같이 사용자와 아이템의 평점 성향의 차이를 반영합니다.

사용자 $u$가 아이템i에 매긴 평점의 기준선 추정값은 다음과 같이 정의됩니다.

$${b_{ui}} = \mu + {b_u} + {b_i}$$

여기에서 $\mu $는 전체 평점 평균(Overall Average Rating), ${b_u}$와 ${b_i}$는 사용자 $u$와 아이템 $i$의 기준선([Bias]{.mark}), ${b_{ui}}$는 평점 기준선 추정값(Baseline Estimate)입니다.

사용자와 아이템의 기준선 추정

이전에 살펴본 평점 기준선 추정 수식에서 사용자가 아이템에 매긴 평점 기준선 추정값은 전체 평점과 사용자가 아이템에 매긴 평점 사이의 편향값인 사용자 기준선, 아이템에 매겨진 사용자 평점 사이의 편향값인 아이템 기준선의 합으로 이루어집니다. 여기에서는 사용자와 아이템 기준선을 계산하기 위한 단순한 방법과 일반적인 방법을 살펴봅니다.

먼저 사용자와 아이템의 기준선 추정을 위한 단순한 방법을 살펴봅니다. 사용자 기준선 추정인 경우에는 사용자 $u$에게 평가된 아이템 집합 ${I_u}$의 평점을 대상으로 합니다. 사용자 기준선 추정의 단순식은 다음과 같이 정의됩니다.

$${b_u} = {\mu _u} - \mu $$

여기에서 ${\mu _u}$은 ${I_u}$의 평점 평균, $\mu $는 전체 평점 평균, ${b_u}$는 기준선 추정값입니다.

아이템 기준선 추정인 경우에는 아이템 $i$에 매겨진 사용자 집합 ${U_i}$의 평점을 대상으로 합니다. 아이템 기준선 추정은 다음과 같이 정의됩니다.

$${b_i} = {\mu _i} - \mu $$

여기에서 ${\mu _i}$은 ${U_i}$의 평점 평균, $\mu $는 전체 평점 평균, ${b_i}$는 기준선 추정값입니다.

사용자와 아이템의 기준선 추정을 위한 단순한 방법에서는 전체 평점 평균에서 사용자 또는 아이템의 평점 평균으로만 평점 성향의 차이(편향)인 기준선을 추정하였습니다.

다음으로 사용자와 아이템의 기준선 추정을 위한 일반적인 방법을 살펴봅니다. 여기에서는 사용자 기준선을 계산하기위해 필요한 아이템 기준선을 먼저 살펴봅니다. 마찬가지로 아이템 기준선 추정인 경우에는 아이템 $i$에 매겨진 사용자 집합 ${U_i}$의 평점을 대상으로 합니다. 아이템 기준선 추정은 다음과 같이 정의됩니다.

$${b_i} = \frac{{\sum\nolimits_{i \in {I_u}} {(r_{ui} - \mu )} }}{{\left| {{U_i}} \right| + \lambda 2}}$$

여기에서 $r_{ui}$은 사용자 $u$가 아이템 $i$에 매긴 평점, $\mu $는 전체 평점 평균, $\left| {{U_i}} \right|$는 ${U_i}$의 원소 개수, $\lambda 2$는 정규화 매개변수(Regularization Parameter), ${b_i}$는 기준선 추정값입니다.

사용자 기준선 추정인 경우에도 마찬가지로 사용자 $u$에게 평가된 아이템 집합 ${I_u}$의 평점을 대상으로 합니다. 사용자 기준선 추정의 단순식은 다음과 같이 정의됩니다.

$${b_u} = \frac{{\sum\nolimits_{i \in {I_u}} {(r_{ui} - \mu - {b_i})} }}{{\left| {{I_u}} \right| + \lambda 3}}$$

여기에서 $r_{ui}$은 사용자 $u$가 아이템 $i$에 매긴 평점, $\left| {{I_u}} \right|$는 ${I_u}$의 원소 개수, $\lambda 3$는 정규화 매개변수, ${b_u}$는 기준선 추정값입니다.

Note:

각 수식에서 $\lambda 2$와 $\lambda 3$은 과적합(Overfitting)을 줄이기 위해 사용하는 정규화 매개변수로 상수입니다. 넷플릭스 프라이즈(Netflix Prize)에서는 $\lambda 2$는 25, $\lambda 3$은 10이 사용되었습니다. 정규화 매개변수는 alpha, lambda, regularization parameter, penalty term으로 표현되기도 하지만 모두 같은 뜻으로 여기에서는 자세히 다루지는 않습니다.

평점 잔차

평점 기준선 추정값은 평점만을 근사하지만, 평점에서 평점 기준선 추정값을 뺀 잔차(Residual, Fitting Error)를 사용하면 좀 더 고유 특성이 적용된 모델을 학습할 수 있습니다. 잔차는 추정값(평점 기준선 추정값)과 실제 값(원본 평점)의 차이로 추정 오차(Estimation Error)와 거의 같은 의미입니다.

사용자가 아이템에 매긴 평점의 잔차는 다음과 같이 정의됩니다.

$${z_{ui}} = r_{ui} - {b_{ui}}$$

여기에서 $r_{ui}$은 사용자 $u$가 아이템 $i$에 매긴 평점, ${b_{ui}}$는 기준선 추정값, ${z_{ui}}$는 평점 잔차입니다.

6.2.1.2 특잇값 분해

차원축소(dimension reduction) 기법으로 많이 사용되는 특잇값 분해(Singular Value Decomposition)는 행렬분해(Matrix Factorization) 방식 중 하나로 데이터의 차원 수를 줄여 계산 효율성을 높이고, 행간에 담긴 의미(Latent)를 이끌어 내기 위한 방법 중 하나입니다.

SVD는 영상 압축에 자주 사용되기도 하지만 추천 시스템에서도 사용되는 이유는 사용자와 아이템으로 이루어지는 평점 데이터는 사용자나 아이템 수에 따라 차원(Dimension)이 너무 크기도 하고, 사용자와 아이템에 따라 매겨진 평점이 희소(Sparse)하게 퍼져 있기 때문입니다. 또한, 특잇값 분해는 차원 축소를 위한 행렬 분해를 통해 잠재 요인(Latent Factor)을 찾고, 이를 통해 원본 행렬을 복원할 수도 있습니다.

크기가 $m \times n$인 행렬 $A$를 세 개의 행렬로 분해하는 특잇값 분해는 다음과 같이 정의됩니다.

$$A = U\sum {V^T}$$

여기에서, $m \times m$ 직교 행렬인 $U$와 $n \times n$ 직교 행렬인 ${V^T}$의 행(또는 $V$의 열 )들은 $A{A^T}$와 ${A^T}A$의 고유 벡터(eigenvector)들이며 각각을 행렬 A의 왼쪽 특이 벡터(left singular vector)와 오른쪽 특이 벡터(right singular vector)라 합니다. $T$는 전치 행렬 연산자입니다. $\sum $는 행렬 A의 특잇값( Singular Value)들을 대각 행렬의 값으로 하는 $m \times n$ 행렬입니다.

이처럼 $m > n$이면서 크기가 $m \times n$인 행렬 $A$를 $m \times m$ 크기인 $U$와 $m \times n$ 크기인 $\sum $, $n \times n$ 크기인 ${V^T}$로 특잇값 분해(SVD)하는 것을 Full SVD라고 합니다. 하지만 $\sum $의 대각 원소에 계산이 불필요한 0이 포함된 full SVD보다는 0 이상의 값 중 의미가 있는 값만 사용하거나 특정 값 이하의 값을 모두 0으로 바꾸어 행렬을 재구성하는 reduced SVD를 일반적으로 사용합니다.

다음으로 $\sum $의 대각 원소 중 상위 k개만 추출하여 원본 데이터의 손실은 불가피하지만 원본 행렬을 근사할 수 있는 Truncated SVD를 살펴봅니다.

k-계수(Rank)로 절단된 특잇값 분해(Truncated SVD)는 다음과 같이 정의됩니다.

$${A_k} \approx {U_k}{\Sigma _k}{V_k}^{\rm{T}}$$

여기에서 ${U_k}$, ${\Sigma _k}$, ${V_k}$는 $m \times k$, $k \times k$, $n \times k$ 행렬입니다. $k$는 계수로 $k \le \min { m,n} $입니다.

6.2.1.3 평점 예측

평점 기준선 추정값을 절단된 특잇값 분해로 분해하고 이를 통해 평점을 근사할 수 있습니다.

절단된 특잇값 분해로 분해된 근사된 예측 평점 매트릭스 ${\rm{hat R}}$은 다음과 같이 정의됩니다.

$${\rm{\hat R}} \approx {\rm{B + }}{{\rm{P}}_{\rm{k}}}{\Sigma _k}Q_k^{\rm T}$$

여기에서 ${\rm{B}}$는 평점 기준선, ${{\rm{P}}_{\rm{k}}}$와 ${\Sigma _k}$, 그리고 ${Q_k}$는 평점 잔차 행렬($R - B$)을 $k$-절단된 특잇값 분해로 분해된 사용자 특징 행렬, 특잇값 행렬, 그리고 아이템 특징 행렬입니다.

사용자 $u$가 평가하지 않은 아이템 $i$에 대한 근사된 예측 평점은 다음과 같이 정의됩니다.

$$ \begin{flalign} \hat r_{ui} & = {b_{ui}} + ({{\bf{p}}_u} \times {\bf{\sigma }}) \cdot {{\bf{q}}_i} \\ & = {b_{ui}} + \sum\limits_k {{p_{uk}}{\sigma _k}{q_{ik}}} \end{flalign} $$
여기에서 ${b_{ui}}$는 평점 기준선 추정값, ${p_{uk}}$는 사용자 $u$의 사용자 특징 벡터 ${{\bf{p}}_u}$의 $k$번째 값, ${\sigma _k}$는 특잇값 벡터 ${\bf{\sigma }}$의 $k$번째 값, ${q_{ik}}$는 아이템 $i$의 아이템 특징 벡터 ${{\bf{q}}_i}$의 $k$번째 값입니다.

Singular value decomposition of A (a) full-rank r (b) rank-k approximation. Download

참고를 걸거나 그림을 새롭게 그리기

6.2.2 직접 계산해보기

이제부터 예제 데이터셋을 사용하여 앞서 살펴본 수식으로 직접 계산해 볼 것입니다. 다음 표는 평점 데이터를 사용자는 행, 아이템은 열로 나타낸 것입니다.

예제 데이터셋의 평점 데이터

사용자/아이템 $i_1$ $i_2$ $i_3$ $i_4$ $i_5$ $i_6$ $i_7$ $i_8$ $i_9$ $i_{10}$
$u_1$ 0.5 5 1 3 3.5 5 2.5
$u_2$ 3 2 3.5 2 4 4 1
$u_3$ 3.5 1 3.5 4 1 3.5
$u_4$ 3 5 0.5 3.5 3.5 4.5
$u_5$ 3 4 2.5 4

예를 들어 사용자 $u_4$가 평가하지 않은 아이템들에 대한 예측 평점을 사용자와 아이템 기준선을 계산하기 위한 단순한 방법을 사용한 평점 기준선 추정값과 절단된 특잇값 분해를 사용하여 계산해 봅니다.

6.2.2.1 평점 기준선 추정 및 잔차

예를 들어 사용자 $u_4$가 아이템 $i_1$에 매긴 평점의 기준선을 단순 기준선 추정을 사용하여 계산해 봅니다. 또한, 일반 기준선 추정도 추가로 계산해 볼 것입니다. 일반 기준선 추정에서의 아이템 기준선과 사용자 기준선의 정규화 매개변수는 계산 과정을 쉽게 이해하는 데 $\lambda 2 = 0$과 $\lambda 3 = 0$, $\lambda 2 = 25$과 $\lambda 3 = 10$로 가정합니다.

아이템 기준선 추정

먼저 평점 데이터를 사용하여 아이템 $i_1$의 아이템 기준선을 예측해 봅니다. 다음 표는 평점 데이터의 아이템별 평점 평균을 나타낸 것입니다.

평점 데이터의 아이템별 평점 평균

아이템 $i_1$ $i_2$ $i_3$ $i_4$ $i_5$ $i_6$ $i_7$ $i_8$ $i_9$ $i_{10}$
평점 평균 2.1666666 3.7 2.375 2 4 2.5 3.8333333 3.5 4.3333333 1.75

여기에서 전체 평점 평균은 3, 아이템 $i_1$의 평점 평균은 2.1666666으로 아이템 $i_1$의 아이템 기준선은 아이템 $i_1$의 평점 평균에서 전체 평점 평균을 뺀 $-0.8333333$이 됩니다.

$${b_{i_1}} = 2.1666666 - 3 = -0.8333333$$

참고로, 일반 기준선 추정을 사용하여 아이템 기준선을 계산해 봅니다. 다음 표는 아이템$i_1$의 평점 데이터를 아이템은 행, 사용자는 열로 나타낸 것입니다.

아이템 $i_1$의 평점 데이터

사용자/아이템 $u_1$ $u_2$ $u_4$
$i_1$ 0.5 3 3

여기에서 전체 평점 평균은 3, 아이템 $i_1$을 평가한 사용자인 ($u_1$, $u_2$, $u_4$)에 대한 평점 (0.5, 3, 3)의 개수는 3입니다. 만일 아이템 기준선의 정규화 매개변수 $\lambda 2 = 0$이면 아이템 $i_1$의 아이템 기준선은 아이템 $i_1$의 평균 중심화된 평점의 합을 평점 개수에 정규화 매개변수를 더한 값으로 나눈 $-0.8333333$입니다.

$${b_{i_1}} = \frac{-2.5}{3} = -0.8333333$$

아이템 기준선의 정규화 매개변수 $\lambda 2 = 25$이면 아이템 $i_1$의 아이템 기준선은 $-0.0892857$이 됩니다.

$${b_{i_1}} = \frac{-2.5}{28} = -0.0892857$$

다음 표는 직접 계산한 결괏값을 나타낸 것입니다.

계산 결과

아이템 전체 평점 평균 아이템 $i_1$의 평점 평균 단순 기준선 추정 일반 기준선 추정($\lambda 2 = 0$) 일반 기준선 추정($\lambda 2 = 25$)
$i_3$ 3 2.1666666 -0.8333333 -0.8333333 -0.0892857

같은 방법으로 아이템 기준선을 모두 계산해 봅니다. 다음 표는 단순 기준선 추정과 일반 기준선 추정(정규화 매개변수 $\lambda 2 = 0$ 또는 $\lambda 2 = 25$)으로 계산된 아이템 기준선을 나타낸 것입니다.

평점 데이터의 아이템 기준선

아이템 단순 기준선 추정 일반 기준선 추정($\lambda 2 = 0$) 일반 기준선 추정($\lambda 2 = 25$)
$i_1$ -0.8333333 -0.8333333 -0.0892857
$i_2$ 0.7 0.7 0.1166667
$i_3$ -0.625 -0.625 -0.0862069
$i_4$ -1 -1 -0.1071429
$i_5$ 1 1 0.0740741
$i_6$ -0.5 -0.5 -0.0689655
$i_7$ 0.8333333 0.8333333 0.0892857
$i_8$ 0.5 0.5 0.0192308
$i_9$ 1.3333333 1.3333333 0.1428571
$i_{10}$ -1.25 -1.25 -0.0925926
사용자 기준선 추정

다음으로 평점 데이터를 사용하여 사용자 $u_4$의 사용자 기준선을 예측해 봅니다. 다음 표는 평점 데이터의 사용자별 평점 평균을 나타낸 것입니다.

평점 데이터의 사용자별 평점 평균

사용자 $u_1$ $u_2$ $u_3$ $u_4$ $u_5$
평점 평균 2.9285714 2.7857143 2.75 3.3333333 3.375

여기에서 전체 평점 평균은 3, 사용자 $u_4$의 평점 평균은 3.3333333입니다. 사용자 $u_4$의 사용자 기준선은 사용자 $u_4$의 평점 평균에서 전체 평점 평균을 뺀 $0.3333333$이 됩니다.

$$b_{u_4} = 3.3333333 - 3 = 0.3333333$$

마찬가지로, 일반 기준선 추정을 사용하여 사용자 기준선을 계산해 봅니다. 다음 표는 사용자 $u_4$의 평점 데이터를 사용자는 행, 아이템은 열로 나타낸 것입니다.

사용자 $u_4$의 평점 데이터

사용자 아이템 $i_1$ $i_2$ $i_4$ $i_6$ $i_8$ $i_9$
$u_4$ 3 5 0.5 3.5 3.5 4.5

다음 표는 사용자 $u_4$가 평가한 아이템의 아이템 기준선을 나타낸 것입니다.

사용자 $u_4$가 평가한 아이템의 아이템 기준선

아이템 평점 단순 기준선 추정 일반 기준선 추정($\lambda 2 = 0$) 일반 기준선 추정($\lambda 2 = 25$)
$i_1$ 3 -0.8333333 -0.8333333 -0.0892857
$i_2$ 5 0.7 0.7 0.1166667
$i_4$ 0.5 -1 -1 -0.1071429
$i_6$ 3.5 -0.5 -0.5 -0.0689655
$i_8$ 3.5 0.5 0.5 0.0192308
$i_9$ 4.5 1.3333333 1.3333333 0.1428571

여기에서 전체 평점 평균은 평점 집합의 평점 평균으로 3, 사용자 $u_4$가 평가한 아이템인 {$i_1$, $i_2$, $i_4$, $i_6$, $i_8$, $i_9$}에 대한 평점 (3, 5, 0.5, 3.5, 3.5, 4.5)의 개수는 6입니다. 만일 아이템 기준선과 사용자 기준선의 정규화 매개변수가 $\lambda 2 = 0$과 $\lambda 3 = 0$이면 사용자 $u_4$의 사용자 기준선은 사용자 $u_4$의 평균 중심화된 평점에서 아이템 기준선을 뺀 값을 평점 개수에 정규화 매개변수를 더한 값으로 나눈 $0.3$입니다.

$$b_{u_4} = \frac{1.8}{6} = 0.3$$

아이템 기준선과 사용자 기준선의 정규화 매개변수가 $\lambda 2 = 25$과 $\lambda 3 = 10$이면 사용자 $u_4$의 사용자 기준선은 $0.1241649$이 됩니다.

$$b_{u_4} = \frac{1.9866395}{16} \approx 0.1241649$$

다음 표는 직접 계산한 결괏값을 나타낸 것입니다.

계산 결과

사용자 전체 평점 평균 사용자 $u_4$의 평점 평균 단순 기준선 추정 일반 기준선 추정($\lambda 2 = 0$) 일반 기준선 추정($\lambda 2 = 25$)
$u_4$ 3 3.3333333 0.3333333 0.3 0.1241649

같은 방법으로 사용자 기준선을 모두 계산해 봅니다. 다음 표는 단순 기준선 추정과 일반 기준선 추정($\lambda 3 = 0$, $\lambda 3 = 10$**)**으로 계산된 사용자 기준선을 나타낸 것입니다.

평점 데이터의 사용자 기준선

사용자 단순 기준선 추정 일반 기준선 추정( $\lambda 2 = 0$과 $\lambda 3 = 0$$) 일반 기준선 추정($\lambda 2 = 25$과 $\lambda 3 = 10$)
$u_1$ -0.0714286 -0.022619 -0.0301035
$u_2$ -0.2142857 -0.0464286 -0.0826352
$u_3$ -0.25 -0.4013889 -0.0982052
$u_4$ 0.3333333 0.3 0.124165
$u_5$ 0.375 0.2729167 0.1035157
평점 기준선 추정

앞서 계산한 아이템 기준선과 사용자 기준선을 사용하여 사용자 $u_4$의 아이템 $i_1$에 대한 평점 기준선을 계산해 봅니다. 여기에서 전체 평점 평균은 3, 사용자 $u_4$의 사용자 기준선은 0.3333333, 아이템 $i_1$의 아이템 기준선은 -0.8333333입니다. 사용자 $u_4$의 아이템 $i_1$에 대한 평점 기준선은 전체 평점 평균에 사용자 기준선과 아이템 기준선을 더한 $2.5$가 됩니다.

$$b_{u_4,i_1} = 3 + 0.3333333 - 0.8333333 = 2.5$$

참고로, 일반 기준선 추정을 사용하여 사용자 $u_4$의 아이템 $i_1$에 대한 평점 기준선을 계산해 봅니다. 여기에서 전체 평점 평균은 3입니다.
만일 아이템 기준선과 사용자 기준선의 정규화 매개변수가 $\lambda 2 = 0$과 $\lambda 3 = 0$이면 사용자 $u_4$의 사용자 기준선은 0.3, 아이템 $i_1$의 아이템 기준선은 -0.8333333으로 사용자 $u_4$의 아이템 $i_1$에 대한 평점 기준선은 전체 평점 평균에 사용자 기준선과 아이템 기준선을 더한 $2.4666667$이 됩니다.

$$b_{u_4,i_1} = 3 + 0.3 - 0.8333333 = 2.4666667$$

아이템 기준선과 사용자 기준선의 정규화 매개변수가 $\lambda 2 = 25$과 $\lambda 3 = 10$이면 사용자 $u_4$의 사용자 기준선은 0.124165, 아이템 $i_1$의 아이템 기준선은 -0.0892857으로 사용자 $u_4$의 아이템 $i_1$에 대한 평점 기준선은 $3.0348793$이 됩니다.

$$b_{u_4,i_1} = 3 + 0.124165 - 0.0892857 = 3.0348793$$

다음 표는 직접 계산한 결괏값을 나타낸 것입니다.

계산 결과

시용자 아이템 전체 평점 평균 평점 기준선 평점 기준선($\lambda 2 = 0$, $\lambda 3 = 0$) 평점 기준선($\lambda 2 = 25$, $\lambda 3 = 10$)
$u_4$ $i_1$ 3 2.5 2.4666667 3.0348793

같은 방법으로 사용자가 평가하거나 평가하지 않은 아이템에 대한 평점 기준선을 모두 계산해 봅니다. 다음 표는 단순 기준선 추정으로 추정된 평점 기준선 데이터를 사용자는 행, 아이템은 열로 나타낸 것입니다.

단순 기준선 추정 평점 데이터

사용자/아이템 $i_1$ $i_2$ $i_3$ $i_4$ $i_5$ $i_6$ $i_7$ $i_8$ $i_9$ $i_{10}$
$u_1$ 2.0952381 3.6285714 2.3035714 1.9285714 3.9285714 2.4285714 3.7619048 3.4285714 4.2619048 1.6785714
$u_2$ 1.952381 3.4857143 2.1607143 1.7857143 3.7857143 2.2857143 3.6190476 3.2857143 4.1190476 1.5357143
$u_3$ 1.9166667 3.45 2.125 1.75 3.75 2.25 3.5833333 3.25 4.0833333 1.5
$u_4$ 2.5 4.0333333 2.7083333 2.3333333 4.3333333 2.8333333 4.1666667 3.8333333 4.6666667 2.0833333
$u_5$ 2.5416667 4.075 2.75 2.375 4.375 2.875 4.2083333 3.875 4.7083333 2.125

다음 표는 일반 기준선 추정($\lambda 2 = 0$, $\lambda 3 = 0$**)**으로 추정된 평점 기준선 데이터를 사용자는 행, 아이템은 열로 나타낸 것입니다.

일반 기준선 추정 평점 데이터

사용자/아이템 $i_1$ $i_2$ $i_3$ $i_4$ $i_5$ $i_6$ $i_7$ $i_8$ $i_9$ $i_{10}$
$u_1$ 2.1440476 3.677381 2.352381 1.977381 3.977381 2.477381 3.8107143 3.477381 4.3107143 1.727381
$u_2$ 2.1202381 3.6535714 2.3285714 1.9535714 3.9535714 2.4535714 3.7869048 3.4535714 4.2869048 1.7035714
$u_3$ 1.7652778 3.2986111 1.9736111 1.5986111 3.5986111 2.0986111 3.4319444 3.0986111 3.9319444 1.3486111
$u_4$ 2.4666667 4 2.675 2.3 4.3 2.8 4.1333333 3.8 4.6333333 2.05
$u_5$ 2.4395833 3.9729167 2.6479167 2.2729167 4.2729167 2.7729167 4.10625 3.7729167 4.60625 2.0229167

다음 표는 일반 기준선 추정($\lambda 2 = 25$, $\lambda 3 = 10$**)**으로 추정된 평점 기준선 데이터를 사용자는 행, 아이템은 열로 나타낸 것입니다.

일반 기준선 추정 평점 데이터

사용자/아이템 $i_1$ $i_2$ $i_3$ $i_4$ $i_5$ $i_6$ $i_7$ $i_8$ $i_9$ $i_{10}$
$u_1$ 2.8806108 3.0865632 2.8836896 2.8627537 3.0439706 2.900931 3.0591823 2.9891273 3.1127537 2.8773039
$u_2$ 2.8280791 3.0340315 2.8311579 2.8102219 2.9914389 2.8483993 3.0066505 2.9365956 3.0602219 2.8247722
$u_3$ 2.8125091 3.0184615 2.8155879 2.794652 2.9758689 2.8328293 2.9910806 2.9210256 3.044652 2.8092022
$u_4$ 3.0348793 3.2408316 3.0379581 3.0170221 3.198239 3.0551995 3.2134507 3.1433957 3.2670221 3.0315724
$u_5$ 3.01423 3.2201824 3.0173088 2.9963729 3.1775898 3.0345502 3.1928014 3.1227465 3.2463729 3.0109231
평점 잔차

추정된 평점 기준선을 사용하여 사용자 $u_4$ 가 아이템 $i_1$에 매긴 평점의 잔차를 계산해 봅니다. 다음 표는 사용자 $u_4$의 평점 데이터를 사용자는 행, 아이템은 열로 나타낸 것입니다.

평점 데이터

사용자/아이템 $i_1$ $i_2$ $i_3$ $i_4$ $i_5$ $i_6$ $i_7$ $i_8$ $i_9$ $i_{10}$
$u_4$ 3 5 0.5 3.5 3.5 4.5

다음 표는 사용자 $u_4$의 아이템 $i_1$에 대한 평점 기준선 데이터를 사용자는 행, 아이템은 열로 나타낸 것입니다.

시용자 아이템 평점 평점 기준선 평점 기준선($\lambda 2 = 0$, $\lambda 3 = 0$) 평점 기준선($\lambda 2 = 25$, $\lambda 3 = 10$)
$u_4$ $i_1$ 3 2.5 2.4666667 3.0348793

사용자 $u_4$가 아이템 $i_1$에 매긴 평점은 3, 단순 기준선 추정으로 추정된 평점 기준선은 2.5입니다. 사용자 $u_4$의 아이템 $i_1$에 대한 평점 잔차는 원본 평점에 평점 기준선을 뺀 0.5가 됩니다.

$$z_{u_4,i_1} = 3 - 2.5 = 0.5$$

참고로, 일반 기준선 추정을 사용하여 평점 잔차를 계산해 봅니다. 여기에서 사용자 $u_4$가 아이템 $i_1$에 매긴 평점은 3입니다. 만일 아이템 기준선과 사용자 기준선의 정규화 매개변수가 $\lambda 2 = 0$과 $\lambda 3 = 0$이면 추정된 평점 기준선은 2.4666667으로 사용자 $u_4$의 아이템 $i_1$에 대한 평점 잔차는 원본 평점에 평점 기준선을 뺀 $0.5333333$입니다.

$$z_{u_4,i_1} = 3 - 2.4666667 = 0.5333333$$

아이템 기준선과 사용자 기준선의 정규화 매개변수가 $\lambda 2 = 25$과 $\lambda 3 = 10$이면 추정된 평점 기준선은 3.0348793으로 사용자 $u_4$의 아이템 $i_1$에 대한 평점 기준선은 $-0.0348793$이 됩니다.

$$z_{u_4,i_1} = 3 - 3.0348793 = -0.0348793$$

다음 표는 직접 계산한 결괏값을 나타낸 것입니다.

계산 결과

시용자 아이템 평점 잔차 잔차($\lambda 2 = 0$, $\lambda 3 = 0$) 잔차($\lambda 2 = 25$, $\lambda 3 = 10$)
$u_4$ $i_1$ 3 0.5 0.5333333 -0.0348793

같은 방법으로 사용자가 평가한 아이템에 대한 평점 잔차를 모두 계산해 봅니다. 다음 표는 단순 기준선 추정으로 추정된 평점 기준선과의 평점 잔차 데이터를 사용자는 행, 아이템은 열로 나타낸 것입니다.

평점 잔차 데이터(단순 기준선)

사용자/아이템 $i_1$ $i_2$ $i_3$ $i_4$ $i_5$ $i_6$ $i_7$ $i_8$ $i_9$ $i_{10}$
$u_1$ -1.5952381 1.3714286 -1.3035714 0.5714286 -0.2619048 0.7380952 0.8214286
$u_2$ 1.047619 -1.4857143 1.3392857 0.2142857 0.2142857 0.3809524 -0.5357143
$u_3$ 0.05 -1.125 1.75 0.25 -1.25 -0.5833333
$u_4$ 0.5 0.9666667 -1.8333333 0.6666667 -0.3333333 -0.1666667
$u_5$ -1.075 1.25 -0.375 -0.2083333

다음 표는 일반 기준선 추정($\lambda 2 = 0$, $\lambda 3 = 0$**)**으로 추정된 평점 기준선과의 평점 잔차 데이터를 사용자는 행, 아이템은 열로 나타낸 것입니다.

평점 잔차 데이터(일반 기준선)

사용자/아이템 $i_1$ $i_2$ $i_3$ $i_4$ $i_5$ $i_6$ $i_7$ $i_8$ $i_9$ $i_{10}$
$u_1$ -1.6440476 1.322619 -1.352381 0.522619 -0.3107143 0.6892857 0.772619
$u_2$ 0.8797619 -1.6535714 1.1714286 0.0464286 0.0464286 0.2130952 -0.7035714
$u_3$ 0.2013889 -0.9736111 1.9013889 0.4013889 -1.0986111 -0.4319444
$u_4$ 0.5333333 1 -1.8 0.7 -0.3 -0.1333333
$u_5$ -0.9729167 1.3520833 -0.2729167 -0.10625

다음 표는 일반 기준선 추정($\lambda 2 = 25$, $\lambda 3 = 10$**)**으로 추정된 평점 기준선과의 평점 잔차 데이터를 사용자는 행, 아이템은 열로 나타낸 것입니다.

평점 잔차 데이터(일반 기준선)

사용자/아이템 $i_1$ $i_2$ $i_3$ $i_4$ $i_5$ $i_6$ $i_7$ $i_8$ $i_9$ $i_{10}$
$u_1$ -2.3806108 1.9134368 -1.8836896 0.099069 0.4408177 1.8872463 -0.3773039
$u_2$ 0.1719209 -1.0340315 0.6688421 -0.8102219 1.0085611 0.9933495 -1.8247722
$u_3$ 0.4815385 -1.8155879 0.705348 1.0241311 -1.8328293 0.455348
$u_4$ -0.0348793 1.7591684 -2.5170221 0.4448005 0.3566043 1.2329779
$u_5$ -0.2201824 0.9826912 -0.5345502 0.8071986

6.2.2.2 특잇값 분해

단순 기준선으로 추정된 평점 기준선과의 잔차 평점 데이터를 $m \times n$ 행렬로 변환하여 특잇값 분해를 해봅니다. 여기에서는 k-계수로 절단된 특잇값 분해(k-Truncated SVD)를 사용하고 k값(Latent Feature Count)은 계산 편의를 위해 3으로 가정합니다.

다음 표는 단순 기준선으로 추정된 평점 기준선과의 잔차 평점 데이터를 사용자는 행, 아이템은 열인 $m \times n$ 행렬로 나타낸 것입니다.

잔차 평점 행렬(단순 기준선)

열 인덱스 행 인덱스 0 1 2 3 4 5 6 7 8 9
0 -1.5952381 1.3714286 -1.3035714 0.5714286 -0.2619048 0.7380952 0.8214286
1 1.047619 -1.4857143 1.3392857 0.2142857 0.2142857 0.3809524 -0.5357143
2 0.05 -1.125 1.75 0.25 -1.25 -0.5833333
3 0.5 0.9666667 -1.8333333 0.6666667 -0.3333333 -0.1666667
4 -1.075 1.25 -0.375 -0.2083333

잔차 평점 행렬은 절단된 특잇값 분해(k-Truncated SVD)를 통해 사용자 특징 행렬과 특잇값 벡터, 아이템 특징 행렬로 분해됩니다. 다음 표는 $m \times k$인 사용자 특징 행렬 ${U_k}$를 나타낸 것입니다.

사용자 행렬

사용자 행 인덱스 0 1 2 3 4
$u_1$ 0 0.6881161 0.0103506 -0.5054723 -0.1682881 -0.4925099
$u_2$ 1 -0.6006035 -0.032809 -0.085924 -0.5644275 -0.5587824
$u_3$ 2 0.0861459 0.7639005 0.4601301 0.1909406 -0.4010697
$u_4$ 3 0.1492847 -0.6443443 0.5488453 0.2412241 -0.450682
$u_5$ 4 -0.3688695 -0.0096409 -0.4734596 0.7472974 -0.2850001

다음 표는 $k \times k$인 특잇값 벡터 ${\Sigma _k}$를 나타낸 것입니다.

특잇값 행렬

열 인덱스 행 인덱스 0 1 2 3 4
0 3.8652841 0 0 0 0
1 0 3.1063702 0 0 0
2 0 0 1.5668647 0 0
3 0 0 0 0.7462296 0
4 0 0 0 0 0.2951403

다음 표는 $n \times k$인 아이템 특징 행렬 ${V_k}$를 나타낸 것입니다.

아이템 행렬

아이템 열 인덱스 0 1 2 3 4
$i_1$ 0 -0.4274641 -0.1200936 0.6323173 -0.2710069 -0.0849138
$i_2$ 1 0.6160421 -0.1646189 0.3171719 0.0632092 0.0183338
$i_3$ 2 -0.5845338 -0.2990218 -0.3609938 0.2449104 -0.0386056
$i_4$ 3 -0.0651011 0.8083689 -0.1400255 -0.306939 0.0157193
$i_5$ 4 -0.0277248 0.0592153 0.0616647 -0.0981114 -0.7454303
$i_6$ 5 0.1354043 -0.4426093 -0.2045868 -0.6087412 0.0891887
$i_7$ 6 -0.0859379 -0.0042497 0.1265521 -0.4377091 -0.0830241
$i_8$ 7 -0.012874 0.0691422 -0.1167608 -0.1077524 0.5090032
$i_9$ 8 0.1119614 -0.1064194 -0.4677942 -0.3695895 -0.1844826
$i_{10}$ 9 0.229476 0.0083952 -0.2356162 0.2199527 -0.3564882

특잇값 분해로 분해된 사용자 특징 행렬과 특잇값 벡터, 아이템 특징 행렬로 사용자 $u_4$가 평가하지 않은 아이템 $i_3$에 대한 평점 잔차를 근사해 봅니다.

여기에서 k값이 3일 때 k-절단된 특잇값 분해로 분해된 사용자 $u_4$의 사용자 특징 벡터는 {0.1492847, -0.6443443, 0.5488453}, 특잇값 벡터는 {3.8652841, 3.1063702, 1.5668647}, 아이템 $i_3$의 아이템 특징 벡터는 {-0.5845338, -0.2990218, -0.3609938}입니다. 사용자 $u_4$가 아이템 $i_3$에 매긴 평점에 대한 근사된 평점 잔차는 사용자 특징 벡터와 특잇값 벡터를 아마다르 곱(원소별 곱, Element wise product)을 한 벡터와 아이템 특징 벡터의 내적인 $-0.0492211$입니다.

$$ \begin{flalign} {\hat z}_{u_4,i_1} & = \left( \begin{bmatrix} {0.1492847}\\ { - 0.6443443}\\ {0.5488453}\\ \end{bmatrix} \circ \begin{bmatrix} {3.8652841}\\ {3.1063702}\\ {1.5668647}\\ \end{bmatrix} \right) \bullet \begin{bmatrix} { - 0.5845338}\\ { - 0.2990218}\\ {-0.3609938}\\ \end{bmatrix} \\ & = \begin{bmatrix} {0.5770278}\\ { - 2.0015719}\\ {0.8599663} \end{bmatrix} \bullet \begin{bmatrix} { - 0.5845338}\\ { - 0.2990218}\\ {-0.3609938}\\ \end{bmatrix} \\ & = (0.5770278 \times - 0.5845338) + ( - 2.0015719 \times - 0.2990218) + (0.8599663 \times - 0.3609938) \\ & = - 0.0492211 \end{flalign} $$

같은 방법으로 특잇값 분해로 분해된 사용자 특징 행렬과 특잇값 벡터, 아이템 특징 행렬로 평점 잔차를 모두 근사해 봅니다. 다음 표는 k값이 3일 때 근사 된 평점 잔차를 사용자는 행, 아이템은 열인 $m \times n$ 행렬로 나타낸 것입니다.

근사 된 평점 잔차 행렬

열 인덱스 행 인덱스 0 1 2 3 4 5 6 7 8 9
0 -1.6416146 1.3820315 -1.2784269 -0.0362609 -0.1206764 0.5079463 -0.3289413 0.0604567 0.6648653 0.7972316
1 0.9194691 -1.4560674 1.4360733 0.0875977 0.0500262 -0.2416883 0.1829003 0.0385599 -0.1860931 -0.5018636
2 0.0285632 0.0431638 -1.164466 1.7955951 0.1757415 -1.1527058 0.0525395 0.0756048 -0.5525097 -0.0735382
3 0.5374888 0.9577271 -0.0492211 -1.7759908 -0.0814921 0.7881087 0.067748 -0.2462322 -0.1246762 -0.0870115
4 0.143986 -1.1087068 1.1101771 0.1724884 -0.0079895 -0.02803 0.028774 0.1029035 0.1905858 -0.1526438

6.2.2.3 평점 예측

예를 들어 사용자 $u_4$가 평가하지 않은 아이템 $i_3$에 대한 예측 평점을 단순 기준선으로 추정된 평점 기준선과 특잇값 분해로 근사된 잔차 평점 추정치를 사용하여 계산해 봅니다. 먼저 사용자 $u_4$가 평가하지 않은 아이템 $i_3$에 대한 평점 기준선을 계산해 봅니다.

아이템 $i_3$의 아이템 기준선

아이템 단순 기준선 추정 일반 기준선 추정($\lambda 1 = 0$) 일반 기준선 추정($\lambda 1 = 25$)
$i_3$ -0.625 -0.625 -0.0862069

사용자 $u_4$의 사용자 기준선

사용자 단순 기준선 추정 일반 기준선 추정($\lambda 2 = 0$) 일반 기준선 추정($\lambda 2 = 10$)
$u_4$ 0.3333333 0.3 0.124165

여기에서 전체 평점 평균은 3, 사용자 $u_4$의 사용자 기준선은 0.3333333, 아이템 $i_3$의 아이템 기준선은 -0.625입니다. 사용자 $u_4$의 아이템 $i_3$에 대한 평점 기준선은 전체 평점 평균에 사용자 기준선과 아이템 기준선을 더한 $2.7083333$이 됩니다.

$${b_{u_4,i_3}} = 3 + 0.3333333 - 0.625 = 2.7083333$$

여기에서 이전에 계산해본 특잇값 분해로 근사된 사용자 $u_4$가 평가하지 않은 아이템 $i_3$에 대한 평점 잔차는 -0.0492211으로 사용자 $u_4$가 평가하지 않은 아이템 $i_3$에 대한 예측 평점은 평점 기준선에 잔차 평점 추정치를 더한 $2.6591$이 됩니다.

$${\hat r_{u_4,i_3}} = 2.7083333 - 0.0492211 \approx 2.6591$$

다음 표는 직접 계산한 결괏값을 나타낸 것입니다.

계산 결과

시용자 아이템 전체 평점 평균 평점 기준선 잔차 예측 평점
$u_4$ $i_3$ 3 2.7083333 -0.0492211 2.6591

같은 방법으로 사용자 $u_4$가 평가하지 않은 아이템에 대한 예측 평점을 모두 계산해 봅니다. 다음 표는 사용자 $u_4$가 평가하지 않은 아이템 {$i_5$, $i_7$, $i_{10}$}에 대한 기준선 예측과 특잇값 분해 데이터를 나타낸 것입니다.

사용자 $u_4$의 평가하지 않은 나머지 아이템에 대한 기준선 예측과 특잇값 분해 데이터

아이템 평점 평균 기준선 예측 특잇값 분해 예측 평점
사용자 기준선 아이템 기준선 평점 기준선 k 사용자 특징 벡터 특잇값 벡터 아이템 특징 벡터 USV
$i_5$ 3 0.3333333 1 4.3333333 1 0.1492847 -0.0277248 -0.02772481 -0.0814921 4.2518412
2 -0.6443443 0.0592153 0.059215294
3 0.5488453 0.0616647 0.061664699
$i_7$ 0.8333333 4.1666667 1 0.1492847 3.8652841 -0.0859379 0.067748 4.2344147
2 -0.6443443 3.1063702 -0.0042497
3 0.5488453 1.5668647 0.1265521
$i_{10}$ -1.25 2.0833333 1 0.1492847 3.8652841 0.229476 -0.0870115 1.9963219
2 -0.6443443 3.1063702 0.0083952
3 0.5488453 1.5668647 -0.2356162

사용자 $u_4$가 평가하지 않은 아이템 {$i_3$, $i_5$, $i_7$, $i_{10}$}에 대한 예측 평점은 {2.6591122, 4.2518412, 4.2344147, 1.9963219}입니다. 예를 들어, 사용자 $u_4$에게 예측 평점이 높은 순으로 $N$개($N = 3$)의 아이템을 추천하면 추천된 아이템은 {$i_5$, $i_7$, $i_3$}이 됩니다. 다음 표는 사용자 $u_4$가 평가하지 않은 아이템을 예측 평점이 높은 순으로 나타낸 것입니다.

사용자 $u_4$가 평가하지 않은 아이템의 예측평점

아이템 평점 기준선 잔차 평점 추정값(usv) 예측 평점
$i_5$ 4.3333333 -0.0814921 4.2518
$i_7$ 4.1666667 0.067748 4.2344
$i_3$ 2.7083333 -0.0492211 2.6591
$i_{10}$ 2.0833333 -0.0870115 1.9963

6.2.3 예제 코드 실행해보기

앞서 "직접 계산하기"에서는 예제 데이터셋의 평점 데이터를 사용하여 계산해 보았습니다. 이제부터는 평점 데이터 파일과 예제 코드를 사용하여 "직접 계산하기"의 계산 결과에 대해 한번 더 확인해 볼 것입니다.

"직접 계산하기"의 결과

기준선 추정 $\lambda 2$ $\lambda 3$ k값 사용자 아이템 평점 기준선 잔차 잔차 근사 사용자 아이템 랭크 예측평점
단순 기준선 추정 - - 3 $u_4$ $i_1$ 2.5 0.5 0.5374888 $u_4$ $i_3$ 3 2.6591122
일반 기준선 추정 0 0 3 2.4666667 0.5333333 0.5590040 3 2.5964331
일반 기준선 추정 25 10 3 3.0348793 -0.0348793 -0.6658965 3 3.1906588

6.2.3.1 구현 클래스 살펴보기

먼저 예제 코드에서 사용하는 SVD 기반 협업 필터링이 구현된 클래스들을 살펴봅니다. 예제 코드에서 SVD 기반 협업 필터링은 1) 단순 또는 일반 평점 기준선 추정, 2) 특잇값 분해, 3) SVD기반 평점 예측 및 추천의 3 단계로 처리됩니다.

평점 기준선 추정

먼저 예제 코드에서 사용하는 평점 기준선 추정이 구현된 SimpleMeanRatingBaseline 클래스와 GeneralMeanRatingBaseline 클래스, 그리고 MeanRatingBaselineModel 클래스를 살펴봅니다. SimpleMeanRatingBaseline 클래스와 GeneralMeanRatingBaseline 클래스는 Apache Spark ML 패키지의 추상 클래스인 Estimator 클래스를 상속받는 CommonEstimator 클래스를 구현하고 있는 클래스로 평점 데이터(사용자/아이템/평점)를 학습하여 평점 기준선 모델인 MeanRatingBaselineModel로 변환하는 추정자(Estimator) 입니다. MeanRatingBaselineModel은 Apache Spark ML 패키지의 추상 클래스인 Model클래스를 상속받는 CommonModel 클래스를 구현하고 있는 클래스로 모델(Model)입니다.

다음 그림은 UML 클래스 다이어그램 표기법을 사용하여 SimpleMeanRatingBaseline 클래스와 GeneralMeanRatingBaseline 클래스, 그리고 MeanRatingBaselineModel 클래스를 클래스 다이어그램으로 나타낸 것입니다.

Download

[UML 클래스 다이어그램]

SimpleMeanRatingBaseline 클래스는 단순 평점 기준선 추정을 위해 필요한 매개변수의 설정이나 기본값 변경이 필요한 경우에는 필요에 따라 다음 코드와 같이 빌더 패턴을 사용하여 인스턴스를 생성할 수 있습니다.

Estimator baseline =
    new SimpleMeanRatingBaseline()
        .setVerbose(false)
        .setUserCol("user")
        .setItemCol("item")
        .setRatingCol("rating")
        .setOutputCol("score");

SimpleMeanRatingBaseline 클래스의 인스턴스에 설정 가능한 매개변수는 다음과 같습니다.

주요 매개변수

매개변수 유형 필수여부 기본값 설명
verbose boolean false 처리과정에 대한 정보를 출력할 것인지 여부 체크(기본값: false).
userCol String user 평점 데이터의 사용자 컬럼명(기본값: “user”)
itemCol String item 평점 데이터의 아이템 컬럼명(기본값: “item”)
ratingCol String rating 평점 데이터의 평점 컬럼명(기본값: “rating”)
outputCol String “similarity” 출력 컬럼명(기본값: “bias”)으로 기준선 추정된 평점

다음 코드와 같이 생성된 SimpleMeanRatingBaseline 클래스의 인스턴스를 생성한 후 fit 메서드를 사용하여 평점 기준선 모델인 MeanRatingBaselineModel 클래스를 생성하고 결과를 transform 메서드를 사용하여 Dataset으로 변환할 수 있습니다.

Dataset<Row> ratingDS = spark.read().load(path);

Estimator baseline =
    new SimpleMeanRatingBaseline()
        .setVerbose(false)
        .setUserCol("user")
        .setItemCol("item")
        .setRatingCol("rating")
        .setOutputCol("score");

MeanRatingBaselineModel baselineModel = (MeanRatingBaselineModel) baseline.fit(ratingDS);

SimpleMeanRatingBaseline 클래스의 fit 메서드에 설정 가능한 매개변수는 다음과 같습니다.

주요 매개변수

매개변수 유형 필수여부 기본값 설명
ratingDS Dataset O - Spark의 Dataset 유형인 평점 데이터셋

MeanRatingBaselineModel 클래스의 transform 메서드에 설정 가능한 매개변수는 다음과 같습니다.

주요 매개변수

매개변수 유형 필수여부 기본값 설명
ratingDS Dataset O - Spark의 Dataset 유형인 평점 데이터셋

GeneralMeanRatingBaseline 클래스는 일반 평점 기준선 추정을 위해 필요한 매개변수의 설정이나 기본값 변경이 필요한 경우에는 필요에 따라 다음 코드와 같이 빌더 패턴을 사용하여 인스턴스를 생성할 수 있습니다.

Estimator baseline =
    new GeneralMeanRatingBaseline()
        .setLambda2(25)
        .setLambda3(10)
        .setVerbose(false)
        .setUserCol("user")
        .setItemCol("item")
        .setRatingCol("rating")
        .setOutputCol("score");

GeneralMeanRatingBaseline 클래스의 인스턴스에 설정 가능한 매개변수는 다음과 같습니다.

주요 매개변수

매개변수 유형 필수여부 기본값 설명
lambda2 Integer 0 아이템 베이스라인 정규화 매개변수
Lambda3 Integer 0 유저 베이스라인 정규화 매개변수
verbose boolean false 처리과정에 대한 정보를 출력할 것인지 여부 체크(기본값: false).
userCol String user 평점 데이터의 사용자 컬럼명(기본값: “user”)
itemCol String item 평점 데이터의 아이템 컬럼명(기본값: “item”)
ratingCol String rating 평점 데이터의 평점 컬럼명(기본값: “rating”)
outputCol String “similarity” 출력 컬럼명(기본값: “bias”)으로 기준선 추정된 평점

다음 코드와 같이 생성된 GeneralMeanRatingBaseline 클래스의 인스턴스를 생성한 후 fit 메서드를 사용하여 평점 기준선 모델인 MeanRatingBaselineModel 클래스를 생성하고 결과를 transform 메서드를 사용하여 Dataset으로 변환할 수 있습니다.

Dataset<Row> ratingDS = spark.read().load(path);

Estimator baseline =
    new GeneralMeanRatingBaseline()
        .setLambda2(25)
        .setLambda3(10)
        .setVerbose(false)
        .setUserCol("user")
        .setItemCol("item")
        .setRatingCol("rating")
        .setOutputCol("score");

MeanRatingBaselineModel baselineModel = (MeanRatingBaselineModel) baseline.fit(ratingDS);

Dataset<Row> baselineRatingDS = baselineModel.transform(ratingDS);

GeneralMeanRatingBaseline 클래스의 fit 메서드에 설정 가능한 매개변수는 다음과 같습니다.

주요 매개변수

매개변수 유형 필수여부 기본값 설명
ratingDS Dataset O - Spark의 Dataset 유형인 평점 데이터셋

MeanRatingBaselineModel 클래스의 transform 메서드에 설정 가능한 매개변수는 다음과 같습니다.

주요 매개변수

매개변수 유형 필수여부 기본값 설명
ratingDS Dataset O - Spark의 Dataset 유형인 평점 데이터셋
특잇값 분해

먼저 예제 코드에서 사용하는 특잇값 분해가 구현된 SingleValueDecomposition 클래스와 SingleValueDecompositionModel 클래스를 살펴봅니다. SingleValueDecomposition 클래스는 Apache Spark ML 패키지의 추상 클래스인 Estimator 클래스를 상속받는 CommonEstimator 클래스를 구현하고 있는 클래스로 기준선 데이터(사용자/아이템/평점)를 학습하여 특잇값 분해 모델인 SingleValueDecompositionModel로 변환하는 추정자(Estimator)입니다. SingleValueDecompositionModel은 Apache Spark ML 패키지의 추상 클래스인 Model 클래스를 상속받는 CommonModel 클래스를 구현하고 있는 클래스로 모델(Model)입니다.

다음 그림은 UML 클래스 다이어그램 표기법을 사용하여 SingleValueDecomposition 클래스와 SingleValueDecompositionModel 클래스를 클래스 다이어그램으로 나타낸 것입니다.

Download

[UML 클래스 다이어그램]

SingleValueDecomposition 클래스는 특잇값 분해를 위해 필요한 매개변수의 설정이나 기본값 변경이 필요한 경우에는 필요에 따라 다음 코드와 같이 빌더 패턴을 사용하여 인스턴스를 생성할 수 있습니다.

SingleValueDecomposition svd =
    new SingleValueDecomposition()
        .setK(3)
        .setVerbose(false)
        .setUserCol("user")
        .setItemCol("item")
        .setRatingCol("residual")
        .setOutputCol("usv");

SingleValueDecomposition 클래스의 인스턴스에 설정 가능한 매개변수는 다음과 같습니다.

주요 매개변수

매개변수 유형 필수여부 기본값 설명
k Integer 0 k-계수(Rank)
verbose boolean false 처리과정에 대한 정보를 출력할 것인지 여부 체크(기본값: false).
userCol String user 평점 데이터의 사용자 컬럼명(기본값: “user”)
itemCol String item 평점 데이터의 아이템 컬럼명(기본값: “item”)
ratingCol String rating 평점 데이터의 평점 컬럼명(기본값: “rating”)
outputCol String “similarity” 출력 컬럼명(기본값: “bias”)으로 기준선 추정된 평점

다음 코드와 같이 생성된 SingleValueDecomposition 클래스의 인스턴스를 생성한 후 fit 메서드를 사용하여 평점 기준선 모델인 SingleValueDecompositionModel 클래스를 생성하고 결과를 transform 메서드를 사용하여 Dataset으로 변환할 수 있습니다.

Dataset<Row> ratingDS = spark.read().load(path);

MeanRatingBaselineModel baselineModel = (MeanRatingBaselineModel) baseline.fit(ratingDS);

Dataset<Row> baselineRatingDS = baselineModel.transform(ratingDS);

SingleValueDecomposition svd =
    new SingleValueDecomposition()
        .setK(3)
        .setVerbose(false)
        .setUserCol("user")
        .setItemCol("item")
        .setRatingCol("residual")
        .setOutputCol("usv");

SingleValueDecompositionModel svdModel = svd.fit(baselineRatingDS);

Dataset<Row> reconstructedRatingDS = svdModel.transform(baselineRatingDS);

SingleValueDecomposition 클래스의 fit 메서드에 설정 가능한 매개변수는 다음과 같습니다.

주요 매개변수

매개변수 유형 필수여부 기본값 설명
ratingDS Dataset O - Spark의 Dataset 유형인 평점 데이터셋

SingleValueDecompositionModel 클래스의 transform 메서드에 설정 가능한 매개변수는 다음과 같습니다.

주요 매개변수

매개변수 유형 필수여부 기본값 설명
ratingDS Dataset O - Spark의 Dataset 유형인 평점 데이터셋
SVD기반 평점 예측 및 추천

먼저 예제 코드에서 사용하는 특잇값 분해 기반 협업 필터링이 구현된 BaselineSingleValueDecompositionParams 클래스와 BaselineSingleValueDecomposition 클래스를 살펴봅니다. BaselineSingleValueDecompositionParams 클래스는 Apache Spark ML 패키지의 추상 클래스인 JavaParams 클래스를 상속받는 CommonParams 클래스를 구현하고 있는 클래스로 BaselineSingleValueDecomposition 클래스의 생성자에 매개변수를 전달합니다.

BaselineSingleValueDecomposition 클래스는 AbstractRecommender 클래스를 상속받아 평점 데이터(사용자/아이템/평점)를 특잇값 분해 기반의 추천 결과로 변환하는 recommend 메서드를 구현하고 있는 협업 필터링 추천을 처리하는 추천기(Recommender)입니다.

다음 그림은 UML 클래스 다이어그램 표기법을 사용하여 BaselineSingleValueDecompositionParams클래스와 BaselineSingleValueDecomposition클래스를 클래스 다이어그램으로 나타낸 것입니다.

Download

[UML 클래스 다이어그램]

BaselineSingleValueDecompositionParams 클래스는 이웃 기반 협업 필터링 추천을 위해 필요한 매개변수의 설정이나 기본값 변경이 필요한 경우에는 필요에 따라 다음 코드와 같이 빌더 패턴을 사용하여 인스턴스를 생성할 수 있습니다.

BaselineSingleValueDecompositionParams params =
        new BaselineSingleValueDecompositionParams()
        .setBaselineModel(baselineModel)
        .setSingleValueDecompositionModel(svdModel)
        .setVerbose(false)
        .setUserCol("user")
        .setItemCol("item")
        .setRatingCol("rating")
        .setOutputCol("score");

BaselineSingleValueDecompositionParams 클래스의 인스턴스에 설정 가능한 매개변수는 다음과 같습니다.

주요 매개변수

매개변수 유형 필수여부 기본값 설명
baselineModel MeanRatingBaselineModel O 평점 기준선 모델인 MeanRatingBaselineModel 객체
svdModel SingleValueDecompositionModel O 특잇값 분해 모델인 SingleValueDecompositionModel 객체
verbose boolean false 처리과정에 대한 정보를 출력할 것인지 여부 체크(기본값: false).
userCol String user 평점 데이터의 사용자 컬럼명(기본값: “user”)
itemCol String item 평점 데이터의 아이템 컬럼명(기본값: “item”)
ratingCol String rating 평점 데이터의 평점 컬럼명(기본값: “rating”)
outputCol String “score” 출력 컬럼명(기본값: “score”)으로 정규화된 평점

BaselineSingleValueDecomposition 클래스는 다음 코드와 같이 생성된 BaselineSingleValueDecompositionParams 클래스의 인스턴스를 생성자의 인자로 전달받아 인스턴스를 생성한 후 recommend 메서드를 사용하여 평점 데이터를 입력받아 예측 평점 높은 순의 Top-N 아이템 추천 데이터로 변환할 수 있습니다.

BaselineSingleValueDecompositionParams params =
    new BaselineSingleValueDecompositionParams()
        .setBaselineModel(baselineModel)
        .setSingleValueDecompositionModel(svdModel)
        .setVerbose(false)
        .setUserCol("user")
        .setItemCol("item")
        .setRatingCol("rating")
        .setOutputCol("score");

BaselineSingleValueDecomposition recommender = new BaselineSingleValueDecomposition(params);

Dataset<Row> recommendedItemDS = recommender.recommend(ratingDS, 10, “$u_4$”);

BaselineSingleValueDecomposition클래스의 recommend 메서드에 설정 가능한 매개변수는 다음과 같습니다.

주요 매개변수

매개변수 유형 필수여부 기본값 설명
ratings Dataset O - Spark의 Dataset 유형인 평점 데이터셋
topN Integer O - 추천 아이템 수
userId Object O - 추천 받을 사용자 ID

6.2.3.2 예제 코드 살펴보기

여기에서는 "직접 계산하기"의 계산 결과를 확인하기 위해 JUnit으로 작성된 예제 클래스의 소스 코드를 살펴봅니다. 다음은 r4tings-recommender 라이브러리에 포함된 SVD 기반 협업 필터링 추천을 위한 구현 클래스인 BaselineSingleValueDecomposition 클래스를 이용하여 "직접 계산하기"의 계산 결과를 확인하기 위한 BaselineSingleValueDecompositionTest 클래스의 baselineSingleValueDecompositionExamples는 테스트 메서드입니다.

BaselineSingleValueDecompositionTest.java

소스 코드에서 볼 수 있듯이 대부분 코드는 테스트를 처리하기 위한 것이지만 기본 흐름은 매우 단순합니다. 먼저 ❶ 매개변수를 바꿔가면서 실행하고 결과를 확인하기 위한 CSV 형식의 인자 목록을 설정합니다( 26~34행). 반복 실행되는 baselineSingleValueDecompositionExamples 메서드에서는 테스트 인자들을 매개변수로 받습니다. 다음으로 ❷ Parquet 유형의 평점 데이터를 읽어 들이고( 45행) ❸ 평점 기준선 추정을 위해 필요한 매개변수를 설정하여 SimpleMeanRatingBaseline 클래스 또는 GeneralMeanRatingBaseline 클래스의 인스턴스를 생성하고(47~56행) ❹ 평점 기준선 모델인 MeanRatingBaselineModel을 생성합니다(58행).

❺ 생성된 평점 기준선 모델을 Dataset으로 변환합니다(60행). ❻ "직접 계산하기"에서 계산해 본 결과(평점 기준선 추정값)에 해당하는 기댓값(Expected)과 예제 코드의 실행 결과인 실제 값(Actual)의 소수 자릿수 7자리까지 비교합니다(60~71행). ❼ "직접 계산하기"에서 계산해 본 결과(평점 잔차)에 해당하는 기댓값(Expected)과 예제 코드의 실행 결과인 실제 값(Actual)의 소수 자릿수 7자리까지 비교합니다(73~82행).

❽ 특잇값 분해를 위해 필요한 매개변수를 설정하여 SingleValueDecomposition 클래스의 인스턴스를 생성하고(84~85행) ❾ 특잇값 분해 모델인 SingleValueDecompositionModel을 생성합니다(87행). ❿ 생성된 특잇값 분해 모델을 Dataset으로 변환합니다(89행). ⑪ "직접 계산하기"에서 계산해 본 결과(근사된 평점)에 해당하는 기댓값(Expected)과 예제 코드의 실행 결과인 실제 값(Actual)의 소수 자릿수 7자리까지 비교합니다(91~98행).

⑪ "직접 계산하기"에서 계산해 본 결과(평점 잔차)에 해당하는 기댓값(Expected)과 예제 코드의 실행 결과인 실제 값(Actual)의 소수 자릿수 7자리까지 비교합니다(100행). ⑫ 이웃 기반 협업 필터링 추천을 위해 필요한 매개변수를 설정합니다(102행~106행). 다음으로 ⑬ BaselineSingleValueDecomposition 클래스의 인스턴스를 생성하고(108행) ⑭ 평점 데이터와 추천 아이템 수, 추천받을 사용자 ID를 전달하여 아이템을 추천합니다(110행). 마지막으로 ⑮ "직접 계산하기"에서 계산해 본 결과(추천 아이템)에 해당하는 기댓값(Expected)과 예제 코드의 실행 결과인 실제 값(Actual) 의 소수 자릿수 7자리까지 비교합니다(123행).

6.2.3.3 실행 결과 확인하기

여기에서는 앞서 살펴본 테스트 클래스인 BaselineSingleValueDecompositionTest 클래스의 테스트 메서드인 baselineSingleValueDecompositionExamples의 실행 결과를 살펴봅니다. 다음과 같이 명령줄 인터페이스(CLI, Command line interface)에서 빌드 도구인 Gradle Wrapper로 BaselineSingleValueDecompositionTest 클래스의 테스트 메서드인 baselineSingleValueDecompositionExamples를 실행해 봅니다.

./gradlew :recommender-examples:test --tests com.r4tings.recommender.examples.ch06.BaselineSingleValueDecompositionTest.baselineSingleValueDecompositionExamples

테스트 메서드가 실행되면 직접 계산하기에서 다룬 결과를 확인하기 위해 설정한 테스트 인자 목록을 테스트 메서드의 매개변수에 대입해가며 반복 실행되어 결과가 출력됩니다.

다음은 반복 실행 테스트를 위한 테스트 인자 목록입니다

테스트 인자 목록

구분 데이터 경로 기준선 추정 $\lambda 2$ $\lambda 3$ 사용자 아이템 아이템 평점 기준선 잔차 잔차 근사 사용자 아이템 랭크 예측평점

특잇값 분해 기반

추천

단순 기준선 추정 dataset/r4tings/ratings.parquet SIMPLE - 3 $u_4$ $i_1$ 2.5 0.5 0.5374888 $u_4$ $u_4$ $i_3$ 3 2.6591122
일반 기준선 추정 GENERAL 0 2.4666667 0.5333333 0.5590040 $u_4$ $u_4$ $i_3$ 3 2.5964331
일반 기준선 추정 25 3.0348793 -0.0348793 -0.6658965 $u_4$ $i_3$ 3 3.1906588

예제 코드의 실행 결과는 다음과 같습니다.

예제 코드 실행 결과더보기

특잇값 분해 기반 추천의 ❶ 단순 평점 기준선, ❷ 일반 기준선 추정($\lambda 2 = 0$, $\lambda 3 = 0$), ❸ 일반 기준선 추정($\lambda 2 = 25$, $\lambda 3 = 10$**)**을 사용한 특잇값 분해 기반 협업 필터링 아이템 추천에 대한 테스트 케이스가 성공적으로 종료(PASSED)되었음을 확인할 수 있습니다. 또한, 실행 결과는 "직접 계산하기"에서 계산해 본 내용을 쉽게 확인하기 위해 처리 과정에서 파생된 상세 출력 정보도 함께 보여주고 있습니다.

한글:9751 영어:10884 숫자:6610

추천 시스템: 워크북

Comments

Do you have a problem, want to share feedback, or discuss further ideas? Feel free to leave a comment here! Please follow Rust's code of conduct. This comment thread directly maps to a discussion on GitHub, so you can also comment there if you prefer.

Instead of authenticating the giscus application, you can also comment directly on GitHub.