View on GitHub

第7章 評価履歴の次元削減 | recsys-python

Home

第7章 評価履歴の次元削減

準備

次のコードを書きなさい。

import numpy as np
import numpy.linalg as LA
np.set_printoptions(precision=3)

# 縮約後の次元数
DIM = 2

Du = np.array([
               [5, 3, 3, +1],
               [6, 2, 5, +1],
               [4, 1, 5, +1],
               [8, 5, 9, -1],
               [2, 4, 2, -1],
               [3, 6, 5, -1],
               [7, 6, 8, -1],
               [4, 2, 3, np.nan],
               [5, 1, 8, np.nan],
               [8, 6, 6, np.nan],
               [3, 4, 2, np.nan],
               [4, 7, 5, np.nan],
               [4, 4, 4, np.nan],
])
I = np.arange(Du.shape[0])
x = Du[:,:-1]
ru = Du[:,-1]

分散共分散行列

特徴量\(k\)の分散\(s_{k}^{2}\)は次式で求められる。

\[s_{k}^{2} = \frac{1}{\mid I \mid} \sum_{i \in I} (x_{i,k} - \overline{x}_{k})^{2}\]

ここで、\(\overline{x}_{k}\)は特徴量\(k\)の平均値である。

特徴量\(x_{i,k}\)を標準化した値\(x_{i,k}^{'}\)は次式で求められる。

\[x_{i,k}^{'} = \frac{x_{i,k} - \overline{x}_{k}}{s_{k}}\]

標準化された特徴量\(k\)と特徴量\(l\)の共分散\(s_{k,l}\)は次式で求められる。

\[s_{k,l} = \frac{1}{\mid I \mid} \sum_{i \in I} x_{i,k}^{'} x_{i,l}^{'}\]

各特徴量について求めた分散、共分散をまとめると、次式のように分散共分散行列\(\boldsymbol{S}\)が得られる。

\[\boldsymbol{S} = \left[ \begin{array}{rrrrrr} 1.000 & 0.191 & 0.749 \\ 0.191 & 1.000 & 0.163 \\ 0.749 & 0.163 & 1.000 \end{array} \right]\]

このとき、次の問いに答えなさい。

01 各特徴量の平均値

xにおいて各特徴量の平均値\(\overline{x}_{k}\)をndarrayとしてまとめて求めるコードを書きなさい。得られたndarrayxk_meanとすること。

コード
    問01    
print('xk_mean = {}'.format(xk_mean))
結果
xk_mean = [4.846 3.923 5.   ]

  1. numpy.mean()を使う。

02 各特徴量の分散

xにおいて各特徴量の分散\(s_{k}^{2}\)をndarrayとしてまとめて求めるコードを書きなさい。得られたndarrays2とすること。

コード
    問02    
print('s^2 = {}'.format(s2))
結果
s^2 = [3.361 3.763 4.769]

  1. numpy.var()を使う。

★★★

  1. 二重のリスト内包表記を使う。
  2. numpy.sum()を使う。
  3. numpy.array()を使う。

★★★

  1. リスト内包表記を使う。
  2. numpy.sum()を使う。
  3. numpy.array()を使う。
  4. 二重のリスト内包表記を使わない。

★★★

  1. numpy.sum()を使う。
  2. リスト内包表記を使わない。

03 各特徴量の標準化

xにおいて各特徴量をndarrayとしてまとめて標準化するコードを書きなさい。得られたndarrayx2とすること。

コード
    問03    
print('x\' = \n{}'.format(x2))
結果
x' = 
[[ 0.084 -0.476 -0.916]
 [ 0.629 -0.991  0.   ]
 [-0.462 -1.507  0.   ]
 [ 1.72   0.555  1.832]
 [-1.552  0.04  -1.374]
 [-1.007  1.071  0.   ]
 [ 1.175  1.071  1.374]
 [-0.462 -0.991 -0.916]
 [ 0.084 -1.507  1.374]
 [ 1.72   1.071  0.458]
 [-1.007  0.04  -1.374]
 [-0.462  1.586  0.   ]
 [-0.462  0.04  -0.458]]

★★★

  1. 二重のリスト内包表記を使う。
  2. numpy.sqrt()を使う。
  3. numpy.array()を使う。

★★★

  1. リスト内包表記を使う。
  2. numpy.sqrt()を使う。
  3. numpy.array()を使う。
  4. 二重のリスト内包表記を使わない。

★★★

  1. numpy.sqrt()を使う。
  2. リスト内包表記を使わない。

04 標準化された特徴量kと特徴量lの共分散

標準化された特徴量\(k\)と特徴量\(l\)の共分散\(s_{k,l}\)を求めるコードを書きなさい。得られた値をsklとすること。

コード
k = 0
l = 1
    問04    
print('s{}{} = {:.3f}'.format(k, l, skl))
結果
s01 = 0.191

  1. numpy.cov()を使う。
  2. numpy.cov()においてbias=Trueを指定する。

★★

  1. リスト内包表記を使う。
  2. numpy.sum()を使う。

★★

  1. numpy.sum()を使う。
  2. リスト内包表記を使わない。

05 分散共分散行列

分散共分散行列\(\boldsymbol{S}\)をndarrayとして求めるコードを書きなさい。得られたndarraySとすること。

コード
    問05    
print('S = \n{}'.format(S))
結果
S = 
[[1.    0.191 0.749]
 [0.191 1.    0.163]
 [0.749 0.163 1.   ]]

  1. numpy.cov()を使う。
  2. numpy.cov()においてbias=Trueを指定する。

★★

  1. numpy.zeros()を使う。
  2. 二重のforループを使う。
  3. リスト内包表記を使う。
  4. numpy.sum()を使う。

★★★

  1. 三重のリスト内包表記を使う。
  2. numpy.sum()を使う。
  3. numpy.array()を使う。

固有値・固有ベクトル

分散共分散行列\(\boldsymbol{S}\)に対して、

\[\boldsymbol{S} \boldsymbol{v} = \lambda \boldsymbol{v} \;\;\;\; (\boldsymbol{x} \neq \boldsymbol{0})\]

を満たす$d$次元ベクトル\(\boldsymbol{v}\)と実数\(\lambda\)が存在するとき、\(\lambda\)を行列$\boldsymbol{S}$の固有値,\(\boldsymbol{v}\)を\(\lambda\)に関する行列\(\boldsymbol{S}\)の固有ベクトルという。このとき、次の問いに答えなさい。

06 固有値・固有ベクトル

分散共分散行列\(\boldsymbol{S}\)の固有値\(\lambda\)、固有ベクトル\(\boldsymbol{v}\)を求めるコードを書きなさい。ndarrayとして得られた固有値、固有ベクトルを、それぞれlmdvとすること。

コード
    問06    
print('λ = {}'.format(lmd))
print('v = \n{}'.format(v))
結果
λ = [1.826 0.25  0.924]
v = 
[[-0.679 -0.71   0.186]
 [-0.291  0.028 -0.956]
 [-0.674  0.704  0.225]]

  1. numpy.linalg.eig()を使う。

07 固有値の降順にソートしたインデックス配列

固有値lmdについて、降順にソートしたインデックスの配列をndarrayとして生成するコードを書きなさい。得られたndarrayindicesとすること。

コード
    問07    
print('indices = {}'.format(indices))
結果
indices = [0 2 1]

★★

  1. numpy.argsort()を使う。

08 固有値の降順に固有値配列をソート

固有値の降順にソートした固有値配列をndarrayとして生成するコードを書きなさい。得られたndarraylmdとすること。

コード
    問08    
print('λ = {}'.format(lmd))
結果
λ = [1.826 0.924 0.25 ]

  1. 整数配列インデキシングを使う。

09 固有値の降順に固有ベクトル配列をソート

固有値の降順にソートした固有ベクトル配列をndarrayとして生成するコードを書きなさい。得られたndarrayvとすること。

コード
    問09    
print('v = \n{}'.format(v))
結果
v = 
[[-0.679  0.186 -0.71 ]
 [-0.291 -0.956  0.028]
 [-0.674  0.225  0.704]]

  1. 整数配列インデキシングを使う。

10 第d主成分までの固有ベクトル

DIM主成分までの対応する固有ベクトルを列ベクトルとして並べた行列\(\boldsymbol{V}\)をndarrayとして生成するコードを書きなさい。得られたndarrayVとすること。

コード
    問10    
print('V = \n{}'.format(V))
結果
V = 
[[-0.679  0.186]
 [-0.291 -0.956]
 [-0.674  0.225]]

  1. スライシングを使う。

主成分得点

アイテム\(i\)の第\(k\)主成分得点\(x_{i,k}^{''}\)は次式で求められる。

\[x_{i,k}^{''} = \sum_{l = 1}^{d} x_{i,l}^{'} v_{k,l}\]

アイテム\(i\)の次元削減後の特徴ベクトル\(\boldsymbol{x}_{i}^{''}\)は次式で求められる。

\[\boldsymbol{x}_{i}^{''\mathsf{T}} = \boldsymbol{x}_{i}^{'\mathsf{T}} \boldsymbol{V}\]

このとき、次の問いに答えなさい。

11 アイテムiの第k主成分得点

アイテム\(i\)の第\(k\)主成分得点\(x_{i,k}^{''}\)を求めるコードを書きなさい。得られた値をxik3とすること。

コード
i = 0
k = 0
    問11    
print('x{}{}\'\' = {:.3f}'.format(i, k, xik3))
結果
x00'' = 0.699

★★

  1. リスト内包表記を使う。
  2. numpy.sum()を使う。

12 各アイテムの次元削減後の特徴ベクトル

各アイテムの次元削減後の特徴ベクトルをndarrayとしてまとめて求めるコードを書きなさい。得られたndarrayx3とすること。

コード
    問12    
print('x\'\' = \n{}'.format(x3))
結果
x'' = 
[[ 0.699  0.264]
 [-0.139  1.065]
 [ 0.752  1.355]
 [-2.564  0.202]
 [ 1.969 -0.636]
 [ 0.373 -1.211]
 [-2.035 -0.496]
 [ 1.219  0.656]
 [-0.545  1.766]
 [-1.788 -0.601]
 [ 1.598 -0.535]
 [-0.148 -1.603]
 [ 0.611 -0.227]]

  1. @演算子を使う。

寄与率

第\(k\)主成分の寄与率は次式で求められる。

\[\frac{\lambda_{k}}{\sum_{l=1}^{d} \lambda_{l}}\]

第\(k\)主成分までの累積寄与率は次式で求められる。

\[\frac{\sum_{l=1}^{k} \lambda_{l}}{\sum_{l=1}^{d} \lambda_{l}}\]

このとき、次の問いに答えなさい。

13 第k主成分の寄与率

第\(k\)主成分の寄与率を求めるコードを書きなさい。得られた値をpkとすること。

コード
k = 0
    問13    
print('第{}主成分の寄与率 = {:.3f}'.format(k+1, pk))
結果
第1主成分の寄与率 = 0.609

★★

  1. リスト内包表記を使う。
  2. numpy.sum()を使う。

14 第k主成分までの累積寄与率

第\(k\)主成分までの累積寄与率を求めるコードを書きなさい。得られた値をckとすること。

コード
k = 2
    問14    
print('第{}主成分までの累積寄与率 = {:.3f}'.format(k, ck))
結果
第2主成分までの累積寄与率 = 0.917

★★

  1. リスト内包表記を使う。
  2. numpy.sum()を使う。

推薦

次元削減後の評価履歴\(D_{u}^{'}\)は、次式のとおり、次元削減後の特徴ベクトル\(\boldsymbol{x}_{i}^{''}\)と元の評価値\(r_{u,i}\)を結合することで得られる。

\[D_{u}^{'} = \left[ \begin{array}{rrr} 0.699 & 0.264 & +1 \\ -0.139 & 1.065 & +1 \\ 0.752 & 1.355 & +1 \\ -2.564 & 0.202 & -1 \\ 1.969 & -0.636 & -1 \\ 0.373 & -1.211 & -1 \\ -2.035 & -0.496 & -1 \\ 1.219 & 0.656 & ? \\ -0.545 & 1.766 & ? \\ -1.788 & -0.601 & ? \\ 1.598 & -0.535 & ? \\ -0.148 & -1.603 & ? \\ 0.611 & -0.227 & ? \end{array} \right]\]

このとき、次の問いに答えなさい。

15 次元削減後の評価履歴

次元削減後の評価履歴\(D_{u}^{'}\)をndarrayとして生成するコードを書きなさい。得られたndarrayDu2とすること。

コード
    問15    
print('R\' = \n{}'.format(Du2))
結果
Du' = 
[[ 0.699  0.264  1.   ]
 [-0.139  1.065  1.   ]
 [ 0.752  1.355  1.   ]
 [-2.564  0.202 -1.   ]
 [ 1.969 -0.636 -1.   ]
 [ 0.373 -1.211 -1.   ]
 [-2.035 -0.496 -1.   ]
 [ 1.219  0.656    nan]
 [-0.545  1.766    nan]
 [-1.788 -0.601    nan]
 [ 1.598 -0.535    nan]
 [-0.148 -1.603    nan]
 [ 0.611 -0.227    nan]]

★★

  1. numpy.hstack()を使う。
  2. ndarray.reshape()を使う。

★★

  1. numpy.append()を使う。
  2. ndarray.reshape()を使う。

★★

  1. numpy.concatenate()を使う。
  2. ndarray.reshape()を使う。