#3. Collaborative Filtering
▶️ Making Recommendation
예시
- nu = 사용자 수
- nm = 작품 수
- rij : 사용자 j가 작품 i를 평가했는지 여부 (0,1)
- yij : j가 i를 평가한 점수
▶️ Using per-item features
각 작품에 대한 Featurer가 있을 때 어떻게 사용 할 수 있을까
- r(i,j) = user j 가 작품 i에 대해 점수를 매겼는지 여부 (1,0)
- y(i,j) = j가 i에 매긴 점수
- wj, bj = j에 대한 파라미터들
- xi = 작품 i에 대한 feature 벡터
- wj * xi + bj = j의 i에 대한 점수를 예측하는 식
- mj = j가 점수를 매긴 작품의 수
Cost function
- r(i,j)=1 일때만 i개의 작품에 대해 제곱합을 진행
- regularization은 n(number of features)까지 합 진행
- 한 사람에 대한 cost function은 다음처럼 구함
- 파라미터 계산을 위해서는 다음 식을 사용하여 최소 파라미터를 학습
- nu = 사람 수
▶️ Collaborative Filtering Algorithm
무비에 대한 feature가 없으면 어떻게 해야할까
파라미터들이 주어졌다고 가정한 다음
- feature xi에 대한 cost를 계산하여 사용자 j가 본 영화들에 대해 제곱합 및 정규화 진행 (n=feature의 수)
- 각 feature에 대한 cost를 위해서는, 모든 무비 수 만큼 해당 식을 합함
그렇다면 파라미터 w,b는 어디서 구함?
- 위에서 구한 파라미터, 작품의 feature에 대한 cost 식을 보면 시그마 부분이 같음을 확인할 수 있음
- 해당 시그마 부분을 합하고 정규식을 각각 더하면 J(w,b,x)에 대한 cost function을 도출할 수 있음
이에 해당 cost function을 최소화 하기 위해 gradient descent를 수행
- CF에서는 x도 이제 파라미터로 간주하고 구한다
▶️ Binary labels : favs, likes and clicks
- 결과는 binary이기 때문에 f(x)에 대해 시그모이드를 사용하고 cost function도 이에 해당하는 loss식의 합인 cost function을 사용한다
▶️ Mean Normalization (전처리)
신규 유저가 인입되었을때, 이 유저의 각 작품에 대한 예측된 선호도를 구해보고자 함
1. 각 작품에 대한 선호도 평균을 구하고 이를 새로운 벡터 mu로 세팅한다
2. 그리고 기존 작품에 대한 선호도 벡터에서 선호도 평균을 뺀 것으로 새로운 벡터를 만든다→각 row의 합과 평균이 0이 됨
3. 해당 값들을 이용하여 사용자 J에 대한 작품 i에 대한 선호도를 wj * xi + bj + mui(xi가 음수인것 방지) 로 세팅
4. 이 때 새로운 유저의 w,b파라미터는 0 이므로, 결국 새로운 유저의 작품 i에 대한 선호도는 선호도 평균으로 도출된다.
▶️ Tensorflow implementation of C.F
Derivatives in ML
tensorflow의 autodiff를 사용하면 쉽게 미분값 구해서 경사하강법 수행할 수 있음
▶️ Finding related items
특정 작품의 feature들인 xi가 있을때, 새로운 작품 K와 유사한 feature를 가진 작품을 찾기 위해선, xk와 xi 간의 유사도를 계산하여 가장 가까운 (=작은) 유사도를 가진 작품을 찾아야 한다. 이 때 squared distance를 사용한다.
Limitations of C.F
1. Cold start problem
새로운 아이템 랭킹 문제
새로운 유저에게 어떤 작품을 추천해줄 것인가 (아무리 평균정규화를 해도...)
2. Use side information (item/user)
추가 정보가 결국 필요함
# C.F에서 Cost function 구현해보기
# GRADED FUNCTION: cofi_cost_func
# UNQ_C1
def cofi_cost_func(X, W, b, Y, R, lambda_):
"""
Returns the cost for the content-based filtering
Args:
X (ndarray (num_movies,num_features)): matrix of item features
W (ndarray (num_users,num_features)) : matrix of user parameters
b (ndarray (1, num_users) : vector of user parameters
Y (ndarray (num_movies,num_users) : matrix of user ratings of movies
R (ndarray (num_movies,num_users) : matrix, where R(i, j) = 1 if the i-th movies was rated by the j-th user
lambda_ (float): regularization parameter
Returns:
J (float) : Cost
"""
nm, nu = Y.shape
J = 0
### START CODE HERE ###
for j in range(nu):
w= W[j,:]
b_j = b[0,j]
for i in range(nm):
x = X[i,:]
y = Y[i,j]
r = R[i,j]
J += np.square(r * (np.dot(w,x) + b_j - y ) )
J = J / 2
#regularization
#J = J + (lambda_*(1/2)) * np.sum(np.square(W)) + np.sum(np.square(X))
J += (lambda_/2) * (np.sum(np.square(W)) + np.sum(np.square(X)))
### END CODE HERE ###
return J
# Reduce the data set size so that this runs faster
num_users_r = 4
num_movies_r = 5
num_features_r = 3
X_r = X[:num_movies_r, :num_features_r]
W_r = W[:num_users_r, :num_features_r]
b_r = b[0, :num_users_r].reshape(1,-1)
Y_r = Y[:num_movies_r, :num_users_r]
R_r = R[:num_movies_r, :num_users_r]
# Evaluate cost function
J = cofi_cost_func(X_r, W_r, b_r, Y_r, R_r, 0);
print(f"Cost: {J:0.2f}")