추천 엔진에 이용되는 데이터 마이닝 기법

반응형
추천 엔진에 이용되는 데이터 마이닝 기법

1. 이웃 기반 기법

  • 추천 시스템은 아이템이나 사용자 사이의 유사성에 대한 개념을 기반으로 동작합니다. 이러한 이웃 메소드는 두 사용자나 아이템 사이의 유효한 정보를 두 개의 벡터로 간주하며, 이 두 벡터에 간단한 수학적 계산을 적용해 둘 사이의 근접 정도를 확인합니다.

1. 1. 유클리드 거리

  • 유클리드 거리 유사도는 두 점이나 벡터 사이의 거리를 계산하는 데 사용되는 가장 일반적인 유사도 측정 방식 중 하나로, 벡터 공간에서의 두 점이나 벡터 사이의 경로에 대한 거리를 의미합니다.

    \[\text{Euclidean Distance}(x, y) =\sqrt{\sum^{n}_{i=1}(x_i - y_i)^2}\]

  • R에서는 dist() 함수에 method = "euclidean" argument를 추가하여 구할 수 있습니다.

    x <- rnorm(30, mean = 0, sd = 1)
    y <- rnorm(30, mean = 1, sd = 1)
    obj <- rbind(x, y)
    
    dist( obj, method = "euclidean" )
    ##          x
    ## y 10.06353

1. 2. 코사인 유사도

  • 코사인 유사도는 내적 공간의 두 벡터 사이각에 대한 코사인을 측정해 해당 벡터들의 유사도를 측정하며 다음과 같이 정의됩니다.

    \[\text{similarity}=\cos(\theta)=\frac{A \cdot B}{||A||||B||}\]
    • 두 벡터 사이의 코사인 각이 90도가 되면 0이 되어 전체 내적이 0이 되며, 이는 두 벡터가 서로 직교함을 의미하고 두 벡터가 서로 매우 멀리 떨어져있다는 점을 추론할 수 있습니다.
  • 아이템을 행, 사용자를 열로 하는 평가 행렬을 생각해볼 때 각 열은 사용자 벡터로 생각할 수 있으며 마찬가지로 각 행은 아이템 벡터로 생각할 수 있습니다.
  • 두 열 벡터 사이의 코사인 각으로 사용자의 유사도를 구할 수 있고 마찬가지로 행 벡터 사이의 코사인 각으로 아이템 유사도를 구할 수 있는 원리입니다.
  • R에서는 lsa 패키지에 내장되어 있는 cosine() 함수를 이용합니다.

    library(lsa)
    vec1 <- c( 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 )
    vec2 <- c( 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 )
    
    cosine(vec1, vec2)
    ##           [,1]
    ## [1,] 0.2357023

1. 3. 자카드 유사도

  • 자카드 유사도는 두 사용자와 아이템 사이의 합집합에 대한 교집합의 비율로 계산합니다.

    \[J(A, B) = \frac{|A \cap B|}{|A \cup B|}\]
  • 사용자나 아이템이 벡터뿐만 아니라 집합으로 표현될 수 있기 때문에 자카드 유사도를 적용할 수도 있습니다.
  • R에서는 clusteval 패키지 안에 내장되어 있는 cluster_similarity() 함수를 이용합니다.

    library(clusteval)
    vec1 <- c( 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 )
    vec2 <- c( 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 )
    
    cluster_similarity(vec1, vec2, similarity = "jaccard")
    ## [1] 0.3269231

1. 4. 피어슨 상관계수

  • 벡터 사이의 유사도를 거리 측정 방식이 아닌 상관관계를 이용하여 측정하는 방법입니다.
  • R에서는 cor() 함수에 method = "pearson" argument를 추가하여 수행할 수 있습니다.

    cor(x, y, method = "pearson")
    ## [1] -0.0294318


2. 수학적 모델링 기법

  • 행렬 인수 분해나 특이값 분해와 같은 수학적 모델은 유사도 계산에 대한 추천 엔진을 구축할 때 매우 정확하다고 알려져 있습니다.
  • 이 기법은 차원 축소가 쉬워서 시스템을 디자인하는 것도 매우 자연스럽습니다.

2. 1. 행렬 인수 분해

  • 행렬은 두 개의 낮은 차수로 이루어진 행렬로 분해가 가능하고, 이 분해된 행렬들끼리 다시 곱하면 원래의 행렬과 매우 유사한 단일 행렬이 되는 성질을 이용합니다.
  • 평가점수가 매겨진 행렬 \(R\)을 크기가 \(U \times M\)인 평가 행렬이라고 가정하고 이를 각각 크기가 \(U \times K\)\(M \times K\)인 행렬 \(P\)\(Q\)로 분해한다고 생각하시면 됩니다. 이때 \(K\)는 행렬의 차수라고 합니다.
  • 평가행렬 \(R\)에 평가점수가 매겨지지 않은 (NA) 빈칸이 있다고 한다면 낮은 차수 행렬인 \(P\)\(Q\)의 내적을 사용해 원본 행렬 \(R\)에서 빈칸을 계산할 수 있습니다. 그에 해당하는 식은 다음과 같습니다.

    \[\hat{r}_{ij}=p_{i}^{\text{T}}q_{j} = \sum^{K}_{k=1} p_{ik}q_{kj}\]

  • 가능한 한 원본 행렬의 값에 가까운 예측 값을 만들기 위해서는 실제 값과 예측 값의 차이(오차)를 최소화하는 것을 생각해야 합니다. 즉 다음과 같은 식을 최소화 하는 해를 구하는 것이라고 생각할 수 있습니다.

    \[\epsilon_{ij}^{2} = (r_{ij} - \hat{r}_{ij})^2 = (r_{ij} - \sum^{K}_{k=1}p_{ik}q_{kj})^2\]

    • 이러한 오차를 최소화하는 알고리즘에는 대표적으로 경사 하강법(목적함수의 최적 매개변수를 찾아서 반복적으로 함수를 최소화하는 알고리즘)이 이용됩니다.
  • 그렇다면 추천 엔진에는 행렬 인수 분해를 어떻게 적용할까? 라는 고민을 할 수 있습니다.
    • 사용자들이 영화에 대한 평가를 할 때 내용이나 배우 또는 장르에 따라 평가를 하는 것처럼, 사용자가 아이템을 평가할 때도 아이템의 특징에 따라 평가합니다.
    • 사용자 ID와 아이템 ID를 포함하고 있는 평가 행렬이 있다고 할 때도 사용자가 아이템 평가에 대한 고유한 기호를 가진다고 가정할 수 있으며, 마찬가지로 아이템은 사용자가 이를 평가하는 데 도움이 될만한 고유 특징이 있다고 가정할 수 있습니다. 이러한 사용자와 아이템의 특징을 잠재적인 feature라고 할 수 있습니다.
  • R에서도 NMF 패키지 함수를 통하여 행렬 인수 분해를 함수를 통해 할 수 있습니다. NMF 패키지는 비음수 행렬인수분해(Non-negative Matrix Factorization) 알고리즘이 포함되어 있는 패키지 입니다. recommenderlab 패키지 안에 내장되어 있는 MovieLense 데이터를 가지고 예시를 들어 설명하겠습니다.

    library(recommenderlab)
    library(NMF)
    data("MovieLense")
    MovieLense
    ## 943 x 1664 rating matrix of class 'realRatingMatrix' with 99392 ratings.
    • 943명의 사용자가 1664개의 영화에 대한 평가 자료 입니다.
  • as() 함수를 사용하여 이를 행렬의 형태로 변환시킨 다음 nmf() 함수를 적용하기 위해 NA 값을 0으로 바꿉니다. 그런 다음 feature의 갯수(본 예제에서는 2개)를 지정하고 함수를 실행시키면 됩니다.

    data1 <- as(MovieLense, "matrix")
    data1[is.na(data1)] = 0   # NA를 0으로 대체
    res = nmf(data1, 2)   # k = 2
  • 적합된 값을 확인하기 위해서 basis()coef() 함수를 이용하면 다음과 같습니다.

    p <- basis(res)
    head( p )
    ##           [,1]         [,2]
    ## 1 2.086676e+00 9.502553e+00
    ## 2 3.922733e+00 2.220446e-16
    ## 3 2.329818e+00 7.511323e-02
    ## 4 1.480206e+00 1.521805e-01
    ## 5 2.220446e-16 5.578773e+00
    ## 6 1.751255e+00 7.276862e+00
    dim(p)
    ## [1] 943   2
    q <- coef(res)
    dim(q)
    ## [1]    2 1664

2. 2. 교대 최소 제곱

  • 위에서 언급한 목적 함수인 오차를 최소화하는 과정에서 과대적합(overfitting)을 방지하기 위해 정규화를 적용해보면 다음과 같은 식으로 나타낼 수 있습니다.

    \[\min_{q^{*}, p^{*}} \sum_{(u, i) \in \kappa} (r_{ui}- q_{i}^{\text{T}}p_{u})^2 + \lambda \big(||q_i||^2 + ||p_u||^2\big)\]

  • 이러한 등식을 최적화하기 위해 사용되는 두 가지 잘알려진 알고리즘이 있습니다.
    • 확률적 경사 하강법(SGD, Stochastic Gradient Descent) : 미니 배치 최적화 기법으로 큰 규모의 데이터나 희소성이 있는 데이터에서 최적 매개변수를 찾는 것
    • 교대 최소 제곱(ALS, Alternative Least Square) : 분산 플랫폼에서 병렬화 용이
  • 교대 최소 제곱법은 반복적으로 계산을 하여 해를 구하는 방식으로 최소 제곱 함수를 사용해 하나의 특징 벡터를 계산하는 것을 수반합니다.
  • 앞에서 언급한 해를 찾는 목적함수는 두 개의 미지수가 연관되어 있기 때문에 비볼록(non-convex) 문제라고 할 수 있지만 만약 미지수 중 하나를 상수로 고정(fixed)시키면, 이 최적화 문제는 이차 방정식이 돼어 최적화된 해를 찾을 수 있을 것 입니다.
  • 따라서 최적해를 구하기 전까지 나머지 기능 벡터들은 상수로 고정시킵니다. 즉 사용자 특징 벡터를 계산하기 위해 먼저 아이템 특징 벡터를 상수로 고정시키고 최소 제곱으로 해결하는 방법을 생각할 수 있습니다.

3. 3. 특이값 분해

  • 특이값 분해(SVD, Singular Value Decomposition)는 행렬 인수 분해의 또 다른 방식입니다.
  • 간단히 말하자면, \(m \times n\) 크기의 실수 행렬을 \(U\), \(\sum\), \(V\) 세 행렬로 분해하며 분해된 행렬들은 다음 등식을 만족합니다.

\[A = U \times \sum \times V^{\text{T}}\] \(U\)\((m \times r)\) 행렬, \(V\)\((n \times r)\) 행렬, \(\sum\)\((r \times r)\) 행렬

  • 여기서 \(r\)은 행렬의 차수이고, \(A\), \(U\), \(V\)는 직교하는 행렬들이며, \(\sum\)는 행렬 \(A\)의 모든 특이값을 갖는 대각행렬입니다.
  • SVD를 적용해 얻은 행렬들은 원본 행렬의 가장 낮은 차수에 대한 근사를 제공하기 때문에 추천시스템에 매우 적합하다고 할 수 있습니다.
  • \(U\)는 사용자 잠재 특징 벡터 표현을 나타내고 \(V\)는 아이템 잠재 특징 벡터 표현을 나타내며 \(\sum\)는 사용자와 아이템의 독립적 특징 표현 \(r\)을 의미하게 됩니다.
    • 여기서 독립적 특징 표현의 값을 \(r\)보다 작은 \(k\)를 설정하는 것으로 \(k\)의 최적 잠재 feature를 선택하게 되고 이를 통해 행렬의 크기를 축소할 수 있는 것 입니다.
    • \(k\)의 값은 모델의 성능을 정의할 수 있기에 교차 검증 방식을 사용해 선택할 수 있습니다.
  • R에서는 svd() 함수를 이용해 SVD를 적용하고 있습니다. 예시는 다음과 같습니다.

    # MovieLense에서 10명의 사용자와 5개의 영화만을 가지고 matrix 생성
    data2 <- as(MovieLense[1:10, 1:5], "matrix")
    data2[is.na(data2)] = 0
    
    s <- svd(data2)
    s
    ## $d
    ## [1] 1.116643e+01 5.821058e+00 4.300848e+00 2.220102e+00 3.632773e-16
    ## 
    ## $u
    ##                [,1]          [,2]          [,3]          [,4]
    ##  [1,] -6.875575e-01 -1.834514e-02 -6.892816e-01 -2.276381e-01
    ##  [2,] -2.870306e-01  2.856661e-01  3.724094e-01 -2.837201e-01
    ##  [3,]  1.137914e-17  3.818743e-17  6.044595e-18  2.879770e-18
    ##  [4,]  0.000000e+00  0.000000e+00  0.000000e+00  0.000000e+00
    ##  [5,] -3.628483e-01  3.823476e-01  7.212908e-02  8.467283e-01
    ##  [6,] -2.870306e-01  2.856661e-01  3.724094e-01 -2.837201e-01
    ##  [7,] -1.918286e-01 -7.642904e-01  1.284750e-01  2.519735e-01
    ##  [8,]  0.000000e+00  0.000000e+00  0.000000e+00  0.000000e+00
    ##  [9,]  0.000000e+00  0.000000e+00  0.000000e+00  0.000000e+00
    ## [10,] -4.404935e-01 -3.257662e-01  4.751894e-01 -8.214132e-02
    ##                [,5]
    ##  [1,] -1.202560e-17
    ##  [2,]  7.614594e-01
    ##  [3,] -2.449248e-01
    ##  [4,]  0.000000e+00
    ##  [5,] -4.476236e-17
    ##  [6,] -4.730278e-01
    ##  [7,]  2.307453e-01
    ##  [8,]  0.000000e+00
    ##  [9,]  0.000000e+00
    ## [10,] -2.884316e-01
    ## 
    ## $v
    ##            [,1]         [,2]       [,3]       [,4]          [,5]
    ## [1,] -0.8012767  0.415719787  0.4004190 -0.1574719  0.000000e+00
    ## [2,] -0.2822046  0.187596015 -0.4304866  0.8365701 -2.166548e-16
    ## [3,] -0.2462945 -0.012606056 -0.6410658 -0.4101400 -6.000000e-01
    ## [4,] -0.4284082 -0.889795759  0.1105103  0.1118814 -3.390304e-17
    ## [5,] -0.1847209 -0.009454542 -0.4807993 -0.3076050  8.000000e-01
    # 대각원소 행렬
    D <- diag(s$d)
    D
    ##          [,1]     [,2]     [,3]     [,4]         [,5]
    ## [1,] 11.16643 0.000000 0.000000 0.000000 0.000000e+00
    ## [2,]  0.00000 5.821058 0.000000 0.000000 0.000000e+00
    ## [3,]  0.00000 0.000000 4.300848 0.000000 0.000000e+00
    ## [4,]  0.00000 0.000000 0.000000 2.220102 0.000000e+00
    ## [5,]  0.00000 0.000000 0.000000 0.000000 3.632773e-16
    s$u %*% D %*% t(s$v)
    ##                [,1]         [,2]         [,3]          [,4]          [,5]
    ##  [1,]  5.000000e+00 3.000000e+00 4.000000e+00  3.000000e+00  3.000000e+00
    ##  [2,]  4.000000e+00 1.554312e-15 1.277317e-15  3.747003e-16  1.498053e-15
    ##  [3,] -4.872603e-32 3.314368e-32 0.000000e+00 -2.486410e-16 -1.112195e-16
    ##  [4,]  0.000000e+00 0.000000e+00 0.000000e+00  0.000000e+00  0.000000e+00
    ##  [5,]  4.000000e+00 3.000000e+00 5.551115e-16  7.494005e-16  1.110223e-15
    ##  [6,]  4.000000e+00 1.110223e-15 1.435372e-15  8.187895e-16  1.000506e-15
    ##  [7,]  4.302114e-16 5.551115e-17 1.281973e-15  5.000000e+00  9.552380e-16
    ##  [8,]  0.000000e+00 0.000000e+00 0.000000e+00  0.000000e+00  0.000000e+00
    ##  [9,]  0.000000e+00 0.000000e+00 0.000000e+00  0.000000e+00  0.000000e+00
    ## [10,]  4.000000e+00 1.082467e-15 2.297192e-15  4.000000e+00  1.977027e-15
    data2
    ##    Toy Story (1995) GoldenEye (1995) Four Rooms (1995) Get Shorty (1995)
    ## 1                 5                3                 4                 3
    ## 2                 4                0                 0                 0
    ## 3                 0                0                 0                 0
    ## 4                 0                0                 0                 0
    ## 5                 4                3                 0                 0
    ## 6                 4                0                 0                 0
    ## 7                 0                0                 0                 5
    ## 8                 0                0                 0                 0
    ## 9                 0                0                 0                 0
    ## 10                4                0                 0                 4
    ##    Copycat (1995)
    ## 1               3
    ## 2               0
    ## 3               0
    ## 4               0
    ## 5               0
    ## 6               0
    ## 7               0
    ## 8               0
    ## 9               0
    ## 10              0


3. 머신 러닝 기법 : 분류 모델

  • 분류 모델은 머신 러닝에서 지도 학습(supervised learning)의 한 형태로 분류됩니다.
  • 통계학을 전공한 사람이라면 많이 들어봤듯 Logistic regression, kNN classification, Decision tree, Random forest, Bagging, Boosting, Support Vector Machine 등과 같은 분류 모형이 존재 합니다.
  • 이러한 분류 모형은 개인화 추천, 문맥적 추천, 하이브리드 추천 등에서 중요한 역할을 담당합니다. 추천에 대한 피드백 정보에 따른 분류 모형을 적용할 수 있고, 이를 확장해 사용자 특징의 가중치를 계산하는 데에도 쓰일 수 있습니다.

3. 1. 로지스틱 회귀

3. 2. kNN 분류

  • 가장 기본 개념은 특정 데이터 주변의 k개의 최접 아이템을 고려하고 이러한 데이터 점을 기반으로 한 출력 레이블 중 다수결 등의 원리로 하나로 분류하는 것 입니다.
  • 로지스틱 회귀와 달리 모수적 가정을 하고 있지 않습니다. k를 결정하는 것은 예측 오차를 최소로 하는 가장 적절한 k를 선택합니다.
  • R에서는 caret 패키지에 내장되어 있는 knn3() 함수를 이용할 수 있습니다. 예시는 다음과 같습니다.

    library(caret)
    data(iris)
    index = sample(1:nrow(iris), size = nrow(iris)*0.7)
    
    # training data
    training <- iris[index, ]
    # test data
    test <- iris[-index, ]
    
    # class variable(response variable)
    cl <- training$Species
    
    # fit
    fit <- knn3(Species ~ ., data = training, k = 3)
    
    # prediction
    pred <- predict(fit, test[, -5], type = "class")
    
    # confusion matrix
    table(pred, test$Species)
    ##             
    ## pred         setosa versicolor virginica
    ##   setosa         13          0         0
    ##   versicolor      0         16         0
    ##   virginica       0          1        15

3. 3. 서포트 벡터 머신

  • 서포트 벡터 머신은 일반적으로 분류 문제를 다루는 최적의 알고리즘을 알려져 있습니다.
  • 각 데이터의 점이 두 가지 종류 중 하나로 분류되는 학습 데이터가 있다면, 새로운 데이터 점의 종류를 구분해주는 모델을 구축하게 됩니다.
  • \(p\) 차원 데이터 세트에 적용되면, 데이터는 \(p-1\) 차원의 초평면에 매핑되고 알고리즘은 그 클래스 사이에서 충분한 마진(margin)을 갖는 경계선을 찾습니다. 이렇게 데이터 점을 분류하는 경계를 생성하는데 마진 값을 최대로 하는 경계를 선택하는 것 입니다.
  • 서포트 벡터 머신의 수학적 원리보다는 중요 포인트만 짚고 넘어가겠습니다.
    • 초평면은 무제한으로 생성될 수 있지만 마진을 최대로 하는 단 하나의 초평면만을 선택합니다.
    • 분류 기준은 오직 초평면의 마진 위에 놓인 점들에 의해 결정됩니다. 이러한 점들을 서포트 벡터라고 부릅니다.
    • 학습된 데이터로 인한 넓은 마진은 테스트 데이터에도 넓은 마진을 제공할 것이고, 결과적으로 테스트 데이터가 정확하게 분류될 수 있습니다.
    • 비선형 데이터에도 잘 동작합니다. 이 때에는 커널 함수(kernel function)를 이용합니다.
  • R에서는 e1071 패키지에 svm() 함수로 구현되어 있습니다. tune() 함수 또한 교차 검증을 수행하고 cost 매개변수에 다른 값을 적용해볼 수 있기에 함께 사용되고 있습니다.

    library(e1071)
    fit2 <- tune(method = svm,
                 Species ~ ., data = training,
                 kernel = "radial",
                 scale = FALSE,
                 ranges = list(cost = c(0.001, 0.01, 0.1, 1, 5, 10, 100)))
    fit2
    ## 
    ## Parameter tuning of 'svm':
    ## 
    ## - sampling method: 10-fold cross validation 
    ## 
    ## - best parameters:
    ##  cost
    ##   100
    ## 
    ## - best performance: 0.02727273
    fit2$best.model
    ## 
    ## Call:
    ## best.tune(method = svm, train.x = Species ~ ., data = training, 
    ##     ranges = list(cost = c(0.001, 0.01, 0.1, 1, 5, 10, 100)), 
    ##     kernel = "radial", scale = FALSE)
    ## 
    ## 
    ## Parameters:
    ##    SVM-Type:  C-classification 
    ##  SVM-Kernel:  radial 
    ##        cost:  100 
    ##       gamma:  0.25 
    ## 
    ## Number of Support Vectors:  22
    summary(fit2)
    ## 
    ## Parameter tuning of 'svm':
    ## 
    ## - sampling method: 10-fold cross validation 
    ## 
    ## - best parameters:
    ##  cost
    ##   100
    ## 
    ## - best performance: 0.02727273 
    ## 
    ## - Detailed performance results:
    ##    cost      error dispersion
    ## 1 1e-03 0.56090909 0.28290926
    ## 2 1e-02 0.56090909 0.28290926
    ## 3 1e-01 0.07727273 0.06243454
    ## 4 1e+00 0.05636364 0.04863613
    ## 5 5e+00 0.03727273 0.04819039
    ## 6 1e+01 0.03727273 0.04819039
    ## 7 1e+02 0.02727273 0.04391326
    • cost parameter가 1일 때 best model이였고 이 때 서포트벡터의 갯수는 38개 입니다.
  • 따라서 svm() 함수를 통하여 최적의 모형을 재적합시킨 후 predict() 함수를 통해 테스트 데이터에 대해 예측을 수행한 결과입니다.

    best <- svm(Species ~ ., data = training,
                kernel = "radial", cost = 1, scale = FALSE)
    predict(best, newdata = test)
    ##          5          6          8         11         12         13 
    ##     setosa     setosa     setosa     setosa     setosa     setosa 
    ##         15         16         24         26         37         38 
    ##     setosa     setosa     setosa     setosa     setosa     setosa 
    ##         47         51         52         54         55         56 
    ##     setosa versicolor versicolor versicolor versicolor versicolor 
    ##         58         63         65         66         77         80 
    ## versicolor versicolor versicolor versicolor versicolor versicolor 
    ##         84         86         87         88         95         97 
    ##  virginica versicolor versicolor versicolor versicolor versicolor 
    ##        102        103        106        112        114        116 
    ##  virginica  virginica  virginica  virginica  virginica  virginica 
    ##        119        123        125        129        137        142 
    ##  virginica  virginica  virginica  virginica  virginica  virginica 
    ##        143        148        149 
    ##  virginica  virginica  virginica 
    ## Levels: setosa versicolor virginica


4. 클러스터링 기법

  • 클러스터 분석은 한 그룹의 객체들을 다른 그룹의 객체들보다 더 비슷한 경우에 군집화하는 과정을 말합니다.
  • 클러스터 분석은 자율 학습 방식입니다. 지도 학습과 같이 설명변수와 반응변수가 같이 존재하는 것이 아니라 설명변수만 존재하고 반응 변수가 없습니다.
  • 따라서 반응 변수를 예측하는 것이 아니라 설명 변수를 적용하여 데이터 내에서 존재할 수 있는 다양한 패턴을 찾기도 합니다.
  • 유명한 클러스터링 알고리즘으로는 계층적 클러스터링(hierarchical clustering), k-means clustering, two-step clustering 등이 있습니다.
    • 여기서는 k-means clustering에 대해서만 언급하겠습니다.
  • 여기서 \(k\)는 데이터에서 형성된 클러스터의 수를 의미합니다. 클러스터링은 다음 두 단계가 반복을 통하여 이루어집니다.
    • 클러스터 할당 단계
    • 중심 이동 단계
  • R에서는 cluster 패키지에 내장되어 있는 kmeans() 함수를 이용할 수 있습니다.

    library(cluster)
    iris$Species <- as.numeric(iris$Species)
    km <- kmeans(x = iris, centers = 5)
    km
    ## K-means clustering with 5 clusters of sizes 50, 36, 28, 22, 14
    ## 
    ## Cluster means:
    ##   Sepal.Length Sepal.Width Petal.Length Petal.Width  Species
    ## 1     5.900000    2.760000     4.250000   1.3260000 2.020000
    ## 2     6.327778    2.925000     5.302778   2.0027778 2.972222
    ## 3     5.242857    3.667857     1.500000   0.2821429 1.000000
    ## 4     4.704545    3.122727     1.413636   0.2000000 1.000000
    ## 5     7.385714    3.135714     6.228571   2.0857143 3.000000
    ## 
    ## Clustering vector:
    ##   [1] 3 4 4 4 3 3 4 3 4 4 3 4 4 4 3 3 3 3 3 3 3 3 4 3 4 4 3 3 3 4 4 3 3 3 4
    ##  [36] 4 3 3 4 3 3 4 4 3 3 4 3 4 3 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
    ##  [71] 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 5 2 2
    ## [106] 5 1 5 2 5 2 2 2 2 2 2 2 5 5 2 5 2 5 2 2 5 2 2 2 5 5 5 2 2 2 5 2 2 2 2
    ## [141] 2 2 2 5 2 2 2 2 2 2
    ## 
    ## Within cluster sum of squares by cluster:
    ## [1] 31.541200 14.231389  4.630714  3.114091  5.895000
    ##  (between_SS / total_SS =  92.4 %)
    ## 
    ## Available components:
    ## 
    ## [1] "cluster"      "centers"      "totss"        "withinss"    
    ## [5] "tot.withinss" "betweenss"    "size"         "iter"        
    ## [9] "ifault"
    • Species를 수치화시켜 모든 변수에 따라 iris 데이터들이 5개의 클러스터로 구분되었습니다.
  • clusplot() 함수를 이용하여 클러스터를 시각화할 수도 있습니다.

    clusplot(iris, km$cluster, 
             color = TRUE, shade= TRUE, 
             labels = 13, lines = 0)


5. 차원축소 : 주성분 분석

  • 추천 시스템을 구축하는 과정에서 가장 일반적으로 겪는 문제는 고차원 데이터와 희소성 부분 입니다. 대게 거대한 feature 집합에 매우 작은 수의 데이터 점만을 갖는 상황을 의미하는 것 입니다.
  • 이러한 상황에서 데이터 집합을 모델에 적용하게 되면 모형의 예측 성능은 낮아지게 됩니다.
  • 따라서 일반적으로 더 많은 데이터 점을 추가하거나 feature를 축소하는 방식으로 차원을 줄여나갈 수 있는데 그 기법 중 하나인 주성분 분석(PCA, Pricipal Component Analysis)에 대해서 말씀드리겠습니다.
  • 주성분 분석은 차원을 축소하는 고전적인 통계 기법으로 차원을 축소하면서 손실되는 정보의 양을 최소로 하는 것을 목적으로 합니다. 즉, PCA로 분산이 낮은 변수나 feature들을 버릴 수 있습니다.

  • 기술적으로 말하면, PCA는 주성분이라고 불리는 선형적으로는 연관성이 없는 값의 집합에 상관관계가 높은 변수들의 정사영을 사용합니다. 주성분 수는 원 변수의 수보다 작거나 같습니다. 이러한 선형 변환은 첫 번째 주성분이 가능한 한 사가장 큰 분산을 갖는 것으로 정의됩니다.
    • 이는 높은 상관관계가 있는 feature를 고려하는 것으로 데이터에서 가장 높은 변동성을 갖는 것을 의미하고, 결과적으로 첫 번째 주성분과 직교하는 가장 상관관계가 낮은 feature를 사용하는 것으로 다음 각 요소는 높은 분산을 갖습니다.
  • R에서는 prcomp() 함수를 이용합니다. USArrests 데이터를 가지고 예시를 들어보겠습니다. 해당 데이터는 미국 내 50개 주의 10만 명당 범쥐와 관련된 통계를 보이는 데이터 입니다.

    data(USArrests)
    knitr::kable(USArrests)
    Murder Assault UrbanPop Rape
    Alabama 13.2 236 58 21.2
    Alaska 10.0 263 48 44.5
    Arizona 8.1 294 80 31.0
    Arkansas 8.8 190 50 19.5
    California 9.0 276 91 40.6
    Colorado 7.9 204 78 38.7
    Connecticut 3.3 110 77 11.1
    Delaware 5.9 238 72 15.8
    Florida 15.4 335 80 31.9
    Georgia 17.4 211 60 25.8
    Hawaii 5.3 46 83 20.2
    Idaho 2.6 120 54 14.2
    Illinois 10.4 249 83 24.0
    Indiana 7.2 113 65 21.0
    Iowa 2.2 56 57 11.3
    Kansas 6.0 115 66 18.0
    Kentucky 9.7 109 52 16.3
    Louisiana 15.4 249 66 22.2
    Maine 2.1 83 51 7.8
    Maryland 11.3 300 67 27.8
    Massachusetts 4.4 149 85 16.3
    Michigan 12.1 255 74 35.1
    Minnesota 2.7 72 66 14.9
    Mississippi 16.1 259 44 17.1
    Missouri 9.0 178 70 28.2
    Montana 6.0 109 53 16.4
    Nebraska 4.3 102 62 16.5
    Nevada 12.2 252 81 46.0
    New Hampshire 2.1 57 56 9.5
    New Jersey 7.4 159 89 18.8
    New Mexico 11.4 285 70 32.1
    New York 11.1 254 86 26.1
    North Carolina 13.0 337 45 16.1
    North Dakota 0.8 45 44 7.3
    Ohio 7.3 120 75 21.4
    Oklahoma 6.6 151 68 20.0
    Oregon 4.9 159 67 29.3
    Pennsylvania 6.3 106 72 14.9
    Rhode Island 3.4 174 87 8.3
    South Carolina 14.4 279 48 22.5
    South Dakota 3.8 86 45 12.8
    Tennessee 13.2 188 59 26.9
    Texas 12.7 201 80 25.5
    Utah 3.2 120 80 22.9
    Vermont 2.2 48 32 11.2
    Virginia 8.5 156 63 20.7
    Washington 4.0 145 73 26.2
    West Virginia 5.7 81 39 9.3
    Wisconsin 2.6 53 66 10.8
    Wyoming 6.8 161 60 15.6
  • 각 변수에서 분산을 계산하기 위해 apply() 함수를 이용해 분산을 계산하면 다음과 같습니다.

    apply(USArrests, MARGIN = 2, FUN = var)
    ##     Murder    Assault   UrbanPop       Rape 
    ##   18.97047 6945.16571  209.51878   87.72916
    • Assault 변수의 분산이 가장 큰 것을 확인할 수 있습니다.
  • 다음은 feature들의 scale을 조정한 후 PCA를 적용해보겠습니다.

    pca <- prcomp(USArrests, scale = TRUE)
    pca
    ## Standard deviations (1, .., p=4):
    ## [1] 1.5748783 0.9948694 0.5971291 0.4164494
    ## 
    ## Rotation (n x k) = (4 x 4):
    ##                 PC1        PC2        PC3         PC4
    ## Murder   -0.5358995  0.4181809 -0.3412327  0.64922780
    ## Assault  -0.5831836  0.1879856 -0.2681484 -0.74340748
    ## UrbanPop -0.2781909 -0.8728062 -0.3780158  0.13387773
    ## Rape     -0.5434321 -0.1673186  0.8177779  0.08902432
  • prcomp() 함수를 적용한 pca 객체에 대해서 살펴보면 다음과 같습니다.

    names(pca)
    ## [1] "sdev"     "rotation" "center"   "scale"    "x"
    • pca$sdev는 각 변수의 스케일이 적용된 표준편차를 의미합니다.
    • pca$rotaion은 주성분 로딩 행렬을 포함하며, 이 행렬은 각 주성분에 따른 각 변수의 비율을 설명합니다.
  • 다음은 행렬도(bi-plot)를 사용해 PCA 결과를 해석하는 방법입니다. 행렬도는 두 주성분에 따른 각 변수의 비율을 보여주는데 사용합니다. biplot() 함수를 이용 합니다.

    # 행렬도의 방향을 변경
    pca$rotation = -pca$rotation
    pca$x = -pca$x
    
    # 행렬도 출력
    biplot(pca, scale = 0)

    • 빨간색 화살표는 로딩(loading) 벡터를 의미하며 이는 feature 공간이 주성분 벡터를 따라 변화하는 정도를 의미합니다.
    pca$rotation
    ##                PC1        PC2        PC3         PC4
    ## Murder   0.5358995 -0.4181809  0.3412327 -0.64922780
    ## Assault  0.5831836 -0.1879856  0.2681484  0.74340748
    ## UrbanPop 0.2781909  0.8728062  0.3780158 -0.13387773
    ## Rape     0.5434321  0.1673186 -0.8177779 -0.08902432
    • 첫 번째 주성분 PC1을 보면 Murder과 Assault, Rape가 거의 비슷한 가중치를 두고 있습니다. 이는 이들 세 가지 feature가 UrbanPop에 비해 높은 상관관계가 있다는 것을 의미합니다. 반대로 PC2는 UrbanPop이 더 높은 가중치를 갖고 있습니다.


6. 벡터 공간 모델

  • 벡터 공간 모델은 단어를 벡터로 사용해 텍스트 문서를 나타내는 방식의 word 분석에 주로 사용되는 대수적 모형입니다. 이러한 방식은 정보 검색 앱에 널리 사용됩니다.
  • 텍스트 분석 과정에서는 두 문장 사이의 유사성을 찾아야 합니다. 이도 마찬가지로 유사도 측정 메트릭을 계산하기 위하여 데이터를 모두 수치화 시켜야 합니다.
  • 하지만 문장으로 주어지는 텍스트는 숫자 대신 단어들이 들어있습니다. 벡터 공간 모델은 문장의 단어들을 숫자 형태로 나타내어줍니다. 따라서 코사인 유사도와 같은 유사도 계산 메트릭을 적용할 수 있습니다.
  • 문장 내의 단어를 수치로 표현하기 위한 방법으로 잘 알려진 것은 크게 두 가지가 있습니다.
    • 단어 빈도(TF, Term Frequency)
    • 단어 빈도-역문서 빈도(TF-IDF, Term Frequency-Inverse Term Docuument Frequency)
  • 다음 예제 문장을 가지고 설명하겠습니다.

    • 문장1 : THE CAT CHASES RAT.
    • 문장2 : THE DOG CHASES CAT.
    • 문장3 : THE MAN WALKS On MAT.

6. 1. 단어 빈도

  • 간단히 말해, 단어 빈도는 문서에서 단어가 출현하는 빈도를 의미합니다. 빈도를 구하는 단계는 다음과 같습니다.
  1. 문서 전체에서 유일한 키워드를 찾기 (V로 표기)

V = {THE, CAT, CHASES, RAT, DOG, MAN, WALKS, ON, MAT}

  1. 문서의 벡터를 생성

D1 = {THE, CAT, CHASES, RAT}
D2 = {THE, DOG, CHASES, CAT}
D3 = {THE, MAN, WALKS, ON, MAT}

  1. 각 문서에서 모든 단어의 빈도수를 카운트

D1 = {(THE, 1), (CAT, 1), (CHASES, 1), (RAT, 1)} D2 = {(THE, 1), (DOG, 1), (CHASES, 1), (CAT, 1)} D3 = {(THE, 1), (MAN, 1), (WALKS, 1), (ON, 1), (MAT, 1)}

  1. 단어-문서 행렬(TDM)을 생성. 문서 ID를 행(row), 단어들로 열(column)을 구성하고 각 셀은 문서 빈도로 채워집니다.
```r
TDM <- matrix(c(1, 1, 1, 1, 0, 0, 0, 0, 0,
                1, 1, 1, 0, 1, 0, 0, 0, 0,
                1, 0, 0, 0, 0, 1, 1, 1, 1), 
              nrow = 3, ncol = 9, byrow = TRUE)
rownames(TDM) <- c("D1", "D2", "D3")
colnames(TDM) <- c("THE", "CAT", "CHASES", "RAT", "DOG", "MAN", "WALKS", "ON", "MAT")

# TDM
TDM
```

```
##    THE CAT CHASES RAT DOG MAN WALKS ON MAT
## D1   1   1      1   1   0   0     0  0   0
## D2   1   1      1   0   1   0     0  0   0
## D3   1   0      0   0   0   1     1  1   1
```

6. 2. 단어 빈도-역문서 빈도

  • 단어-문서 행렬(TDM, Term Document Matrix)에서는 근본적인 결함이 존재합니다. 드물게 발견되는 단어보다 더 자주 발견되는 단어에 가중치와 중요도를 더 많이 부여해야 합니다. 대부분의 문서 모음에서 발견되는 단어는 문서를 식별하는 차별화 요소로 기여하지 못한다는 것을 이해하셔야 합니다.
  • 비슷하게, 한 문서에서 더 자주 발생하는 단어와 문서 모음 전체에서 덜 발생하는 단어들이 특정 문서를 식별하는 차별화 요소로 기여하게 됩니다. 즉, 문서 모음에서 더 자주 발견되는 단어의 가중치를 낮게 조절하고, 문서에서는 자주 발견되는 단어지만 문서 모음 전체에서 자주 발견되지 않은 단어의 가중치를 높이려면 단어 빈도-역문서 빈도(TF-IDF)를 이용합니다.
  • TF-IDF는 단어 빈도와 단어의 역문서 빈도의 내적으로 계산합니다.

\[TF-IDF = TF \cdot IDF\] - 여기서 IDF는 \(IDF = \log(\frac{D}{1 + n(d, t)})\)로 정의되며 \(D\)는 문서 모음의 전체 수를 말하고, \(n(d, t)\)는 전체 문서에서 단어 \(t\)가 발생한 횟수를 말합니다.

  • 앞의 문서 집합 (D1, D2, D3)를 가지고 계산 해보겠습니다.
  1. TDM을 계산
```r
TDM
```

```
##    THE CAT CHASES RAT DOG MAN WALKS ON MAT
## D1   1   1      1   1   0   0     0  0   0
## D2   1   1      1   0   1   0     0  0   0
## D3   1   0      0   0   0   1     1  1   1
```
  1. 문서 빈도(DF) 계산
```r
DF <- colSums(TDM)
DF
```

```
##    THE    CAT CHASES    RAT    DOG    MAN  WALKS     ON    MAT 
##      3      2      2      1      1      1      1      1      1
```
  1. IDF 계산
```r
IDF <- log10(nrow(TDM) / (1 + DF))
```
  1. TF-IDF 계산
```r
TF_IDF <- rbind( TDM[1, ] * IDF,
                 TDM[2, ] * IDF,
                 TDM[3, ] * IDF )
TF_IDF
```

```
##             THE CAT CHASES       RAT       DOG       MAN     WALKS
## [1,] -0.1249387   0      0 0.1760913 0.0000000 0.0000000 0.0000000
## [2,] -0.1249387   0      0 0.0000000 0.1760913 0.0000000 0.0000000
## [3,] -0.1249387   0      0 0.0000000 0.0000000 0.1760913 0.1760913
##             ON       MAT
## [1,] 0.0000000 0.0000000
## [2,] 0.0000000 0.0000000
## [3,] 0.1760913 0.1760913
```
  • 지금까지 설명해왔던 것들은 R에서 tm 패키지 안에 함수로 내장되어 있습니다. TermDocumentMatrix() 함수와 weightTfIdf() 함수는 단어 문서 행렬과 TF-IDF를 계싼하기 위해 사용하는 함수 입니다.

    library(tm)
    data(crude)
    tdm <- TermDocumentMatrix(crude, 
                              control = list(weighting = function(x) weightTfIdf(x, normalize = TRUE), 
                                             stopwords = TRUE))
    tdm
    ## <<TermDocumentMatrix (terms: 1200, documents: 20)>>
    ## Non-/sparse entries: 1890/22110
    ## Sparsity           : 92%
    ## Maximal term length: 17
    ## Weighting          : term frequency - inverse document frequency (normalized) (tf-idf)
    inspect(tdm)
    ## <<TermDocumentMatrix (terms: 1200, documents: 20)>>
    ## Non-/sparse entries: 1890/22110
    ## Sparsity           : 92%
    ## Maximal term length: 17
    ## Weighting          : term frequency - inverse document frequency (normalized) (tf-idf)
    ## Sample             :
    ##          Docs
    ## Terms            144        211         236         237        242
    ##   1.50    0.00000000 0.00000000 0.000000000 0.000000000 0.00000000
    ##   billion 0.00000000 0.00000000 0.000000000 0.000000000 0.00000000
    ##   crude   0.00000000 0.00000000 0.004250934 0.000000000 0.00000000
    ##   january 0.00000000 0.00000000 0.000000000 0.000000000 0.00000000
    ##   mln     0.01694122 0.04189102 0.017003736 0.004250934 0.00000000
    ##   opec    0.03676471 0.00000000 0.022140221 0.003690037 0.02061856
    ##   posted  0.00000000 0.00000000 0.000000000 0.000000000 0.00000000
    ##   power   0.00000000 0.00000000 0.000000000 0.000000000 0.00000000
    ##   saudi   0.00000000 0.00000000 0.000000000 0.000000000 0.02061856
    ##   west    0.00000000 0.00000000 0.000000000 0.000000000 0.00000000
    ##          Docs
    ## Terms             246        349      368 704        708
    ##   1.50    0.000000000 0.00000000 0.000000   0 0.00000000
    ##   billion 0.097227164 0.00000000 0.000000   0 0.14764125
    ##   crude   0.000000000 0.03490918 0.000000   0 0.02560007
    ##   january 0.000000000 0.00000000 0.000000   0 0.29528250
    ##   mln     0.000000000 0.00000000 0.000000   0 0.05120014
    ##   opec    0.004878049 0.01515152 0.000000   0 0.00000000
    ##   posted  0.000000000 0.00000000 0.000000   0 0.00000000
    ##   power   0.000000000 0.00000000 0.261935   0 0.00000000
    ##   saudi   0.000000000 0.03030303 0.000000   0 0.00000000
    ##   west    0.000000000 0.00000000 0.000000   0 0.00000000


7. 평가 기법

  • 모형을 평가하는 과정에서 가장 중요하게 고려돼야할 사항은 다음과 같습니다.

    • 모형이 과대적합이나 과소적합은 아닌가?
    • 새로운 테스트 데이터에 대해 잘 예측할 수 있는가?
  • k-fold Cross-Validation과 같이 교차검증을 통하여 모형의 정확도를 일반화시키는게 바람직하며 오차를 평가하는 기준은 평균 제곱근 오차(RMSE)나 평균 절대 오차(MAE)가 주로 쓰입니다.
  • 또한 정확도와 재현율 매트릭도 주로 쓰입니다.

반응형
TAGS.

Comments