View on GitHub

第2章 評価値行列 | recsys-python

Home

第2章 評価値行列

準備

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

import pprint
import numpy as np
np.set_printoptions(precision=3)

評価値行列

次の行列\(\boldsymbol{R}\)は評価値行列である。

\[\boldsymbol{R} = \left[ \begin{array}{rrrrrr} ? & 4 & 3 & 1 & 2 & ? \\ 5 & 5 & 4 & ? & 3 & 3 \\ 4 & ? & 5 & 3 & 2 & ? \\ ? & 3 & ? & 2 & 1 & 1 \\ 2 & 1 & 2 & 4 & ? & 3 \\ \end{array} \right]\]

\(\boldsymbol{R}\)の\(u\)行目はユーザ\(u \in U\)を表し、\(i\)列目はアイテム\(i \in I\)を表す。ここで、\(\boldsymbol{R}\)におけるユーザ数は\(\mid U \mid = 5\)、アイテム数は\(\mid I \mid = 6\)となる。\(\boldsymbol{R}\)の\((u, i)\)成分はユーザ\(u\)がアイテム\(i\)に与えた評価値\(r_{u,i}\)を表す。ただし、\(?\)は欠損値であることを表す。このとき、次の問いに答えなさい。

01 評価値行列の生成

評価値行列\(\boldsymbol{R}\)をndarrayとして生成するコードを書きなさい。得られたndarrayRとすること。

コード
    問01    
print('R = \n{}'.format(R))
結果
R = 
[[nan  4.  3.  1.  2. nan]
 [ 5.  5.  4. nan  3.  3.]
 [ 4. nan  5.  3.  2. nan]
 [nan  3. nan  2.  1.  1.]
 [ 2.  1.  2.  4. nan  3.]]

  1. numpy.array()を使う。
  2. numpy.nanを使う。

02 ユーザ集合

Rの各行のインデックスuは各ユーザ\(u\)のユーザIDに対応する。Rからユーザ集合\(U\)(ユーザIDを要素としたベクトル)をndarrayとして生成するコードを書きなさい。得られたndarrayUとすること。

コード
    問02    
print('U = {}'.format(U))
結果
U = [0 1 2 3 4]

  1. numpy.arange()を使う。
  2. ndarray.shapeを使う。

03 アイテム集合

Rの各列のインデックスiは各アイテム\(i\)のアイテムIDに対応する。Rからアイテム集合\(I\)(アイテムIDを要素としたベクトル)をndarrayとして生成するコードを書きなさい。得られたndarrayIとすること。

コード
    問03    
print('I = {}'.format(I))
結果
I = [0 1 2 3 4 5]

  1. numpy.arange()を使う。
  2. ndarray.shapeを使う。

04 ユーザ数

Uからユーザ数\(\mid U \mid\)を取得するコードを書きなさい。

コード
print('|U| = {}'.format(    問04    ))
結果
|U| = 5

  1. ndarray.sizeを使う。

05 アイテム数

Iからアイテム数\(\mid I \mid\)を取得するコードを書きなさい。

コード
print('|I| = {}'.format(    問05    ))
結果
|I| = 6

  1. ndarray.sizeを使う。

06 評価値

Rからユーザ\(u\)のアイテム\(i\)に対する評価値\(r_{u,i}\)を取得するコードを書きなさい。

コード
u = 0
i = 1
print('r{}{} = {}'.format(u, i,     問06    ))
結果
r01 = 4.0

  1. インデキシングを使う。

評価値行列の疎性

評価値行列\(\boldsymbol{R}\)の疎性\(\mathrm{sparsity}\)は次式で求められる。

\[\mathrm{sparsity} = 1 - \frac{\mid R \mid}{\mid U \mid \mid I \mid}\]

ここで、\(\mid R \mid\)は評価値が与えられた成分の数、すなわち観測値数(欠損値でない要素数)を表す。このとき、次の問いに答えなさい。

07 評価値行列の全要素数

Rの全要素数を取得するコードを書きなさい。ただし、欠損値も含む。

コード
print('Rの全要素数 = {}'.format(    問07    ))
結果
Rの全要素数 = 30

  1. ndarray.sizeを使う。

08 観測されているか否かの判定

Rにおいて、観測値の要素にはTrueを、欠損値の要素にはFalseを入れたブール値配列を生成するコードを書きなさい。

コード
print('観測値 = \n{}'.format(    問08    ))
結果
観測値 = 
[[False  True  True  True  True False]
 [ True  True  True False  True  True]
 [ True False  True  True  True False]
 [False  True False  True  True  True]
 [ True  True  True  True False  True]]

  1. numpy.isnan()を使う。
  2. ~演算子を使う。

09 評価値行列の観測値数

Rにおける観測値数\(\mid R \mid\)を取得するコードを書きなさい。

コード
print('|R| = {}'.format(    問09    ))
結果
|R| = 22

★★

  1. numpy.isnan()を使う。
  2. ~演算子を使う。
  3. numpy.count_nonzero()を使う。

★★

  1. numpy.isnan()を使う。
  2. ~演算子を使う。
  3. numpy.sizeを使う。
  4. ブール値インデキシングを使う。

10 評価値行列の疎性

評価値行列\(\boldsymbol{R}\)の疎性\(\mathrm{sparsity}\)を求めるコードを書きなさい。得られた値をsparsityとすること。

コード
    問10    
print('sparsity = {:.3f}'.format(sparsity))
結果
sparsity = 0.267

★★

  1. numpy.isnan()を使う。
  2. ~演算子を使う。
  3. numpy.count_nonzero()を使う。
  4. numpy.sizeを使う。

評価済みアイテム集合

アイテム集合\(I\)のうちユーザ\(u\)が評価済みのアイテム集合を\(I_{u} \subseteq I\)、ユーザ\(v\)が評価済みのアイテム集合を\(I_{v} \subseteq I\)とすると、ユーザ\(u\)とユーザ\(v\)の共通の評価済みアイテム集合は\(I_{u,v} = I_{u} \cap I_{v}\)と表される。また、ユーザ集合\(U\)のうちアイテム\(i\)を評価済みのユーザ集合を\(U_{i} \subseteq U\)、アイテム\(j\)を評価済みのユーザ集合を\(U_{j} \subseteq U\)とすると、アイテム\(i\)とアイテム\(j\)の両方を評価済みのユーザ集合は\(U_{i,j} = U_{i} \cap U_{j}\)と表される。このとき、次の問いに答えなさい。

11 ユーザuが評価済みのアイテム集合

Iからユーザ\(u\)が評価済みのアイテム集合\(I_{u}\)をndarrayとして生成するコードを書きなさい。

コード
u = 0
print('I{} = {}'.format(u,     問11    ))
結果
I0 = [1 2 3 4]

★★

  1. numpy.isnan()を使う。
  2. ~演算子を使う。
  3. ブール値インデキシングを使う。

12 各ユーザの評価済みアイテム集合

Iから各ユーザの評価済みのアイテム集合をndarrayのリストとしてまとめて生成するコードを書きなさい。得られたリストをIuとすること。

コード
    問12    
print('Iu = ')
pprint.pprint(Iu)
結果
Iu = 
[array([1, 2, 3, 4]),
 array([0, 1, 2, 4, 5]),
 array([0, 2, 3, 4]),
 array([1, 3, 4, 5]),
 array([0, 1, 2, 3, 5])]

★★

  1. forループを使う。
  2. numpy.isnan()を使う。
  3. ~演算子を使う。
  4. ブール値インデキシングを使う。
  5. list.append()を使う。

★★★

  1. リスト内包表記を使う。
  2. numpy.isnan()を使う。
  3. ~演算子を使う。
  4. ブール値インデキシングを使う。

13 ユーザuとユーザvの共通の評価済みアイテム集合

Iuからユーザ\(u\)とユーザ\(v\)の共通の評価済みアイテム集合\(I_{u,v}\)をndarrayとして生成するコードを書きなさい。得られたndarrayIuvとすること。

コード
u = 0
v = 1
    問13    
print('I{}{} = {}'.format(u, v, Iuv))
結果
I01 = [1 2 4]

  1. numpy.intersect1dを使う。

14 アイテムiを評価済みのユーザ集合

Uからアイテム\(i\)を評価済みのユーザ集合\(U_{i}\)をndarrayとして生成するコードを書きなさい。

コード
i = 0
print('U{} = {}'.format(i,     問14    ))
結果
U0 = [1 2 4]

★★

  1. numpy.isnan()を使う。
  2. ~演算子を使う。
  3. ブール値インデキシングを使う。

15 各アイテムの評価済みユーザ集合

Uから各アイテムの評価済みユーザ集合\(U_{i}\)をndarrayのリストとしてまとめて生成するコードを書きなさい。得られたリストをUiとすること。

コード
    問15    
print('Ui = ')
pprint.pprint(Ui)
結果
Ui = 
[array([1, 2, 4]),
 array([0, 1, 3, 4]),
 array([0, 1, 2, 4]),
 array([0, 2, 3, 4]),
 array([0, 1, 2, 3]),
 array([1, 3, 4])]

★★

  1. forループを使う。
  2. numpy.isnan()を使う。
  3. ~演算子を使う。
  4. ブール値インデキシングを使う。
  5. list.append()を使う。

★★★

  1. リスト内包表記を使う。
  2. numpy.isnan()を使う。
  3. ~演算子を使う。
  4. ブール値インデキシングを使う。

16 アイテムiとアイテムjの両方を評価済みのユーザ集合

Uiからアイテム\(i\)とアイテム\(j\)の両方を評価済みのユーザ集合\(U_{i,j}\)をndarrayとして生成するコードを書きなさい。得られたndarrayUijとすること。

コード
i = 0
j = 4
    問16    
print('U{}{} = {}'.format(i, j, Uij))
結果
U04 = [1 2]

  1. numpy.intersect1dを使う。

平均中心化評価値行列

ユーザ\(u\)の平均評価値\(\overline{r}_{u}\)は次式で求められる。

\[\overline{r}_{u} = \frac{\sum_{i \in I_{u}} r_{u,i}}{\mid I_{u} \mid}\]

ユーザ\(u\)のアイテム\(i\)に対する評価値\(r_{u,i}\)からユーザ\(u\)の平均評価値\(\overline{r}_{u}\)を引いた評価値を平均中心化評価値\(r_{u,i}^{'}\)とよび、次式で表される。

\[r_{u,i}^{'} = r_{u,i} - \overline{r}_{u}\]

評価値行列\(\boldsymbol{R}\)の評価値\(r_{u,i}\)を平均中心化評価値\(r_{u,i}^{'}\)に置き換えた評価値行列を平均中心化評価値行列\(\boldsymbol{R}^{'}\)とよび、次式のようになる。

\[\boldsymbol{R}^{'} = \left[ \begin{array}{rrrrrr} & 1.5 & 0.5 & -1.5 & -0.5 & \\ 1 & 1 & 0 & & -1 & -1 \\ 0.5 & & 1.5 & -0.5 & -1.5 & \\ & 1.25 & & 0.25 & -0.75 & -0.75 \\ -0.4 & -1.4 & -0.4 & 1.6 & & 0.6 \end{array} \right]\]

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

17 評価値行列全体の平均評価値

R全体の平均評価値を求めるコードを書きなさい。ただし、欠損値は無視する。

コード
print('R全体の平均評価値 = {:.3f}'.format(    問17    ))
結果
R全体の平均評価値 = 2.864

  1. numpy.nanmean()を使う。

18 各アイテムの平均評価値

Rにおいて各アイテムの平均評価値\(\overline{r}_{i}\)をndarrayとしてまとめて求めるコードを書きなさい。ただし、欠損値は無視する。得られたndarrayri_meanとすること。

コード
    問18    
print('ri_mean = {}'.format(ri_mean))
結果
ri_mean = [3.667 3.25  3.5   2.5   2.    2.333]

★★

  1. numpy.nanmean()を使う。

19 各ユーザの平均評価値

Rにおいて各ユーザの平均評価値\(\overline{r}_{u}\)をndarrayとしてまとめて求めるコードを書きなさい。ただし、欠損値は無視する。得られたndarrayru_meanとすること。

コード
    問19    
print('ru_mean = {}'.format(ru_mean))
結果
ru_mean = [2.5  4.   3.5  1.75 2.4 ]

★★

  1. numpy.nanmean()を使う。

★★★

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

20 評価値ベクトルの形状変換

ru_meanの形状を(5, 1)に変換するコードを書きなさい。

コード
print('ru_mean = \n{}'.format(    問20    ))
結果
ru_mean = 
[[2.5 ]
 [4.  ]
 [3.5 ]
 [1.75]
 [2.4 ]]

  1. ndarray.reshape()を使う。

21 平均中心化評価値行列

評価値行列\(\boldsymbol{R}\)の平均中心化評価値行列\(\boldsymbol{R}^{'}\)をndarrayとして生成するコードを書きなさい。得られたndarrayR2とすること。

コード
    問21    
print('R\' = \n{}'.format(R2))
結果
R' = 
[[  nan  1.5   0.5  -1.5  -0.5    nan]
 [ 1.    1.    0.     nan -1.   -1.  ]
 [ 0.5    nan  1.5  -0.5  -1.5    nan]
 [  nan  1.25   nan  0.25 -0.75 -0.75]
 [-0.4  -1.4  -0.4   1.6    nan  0.6 ]]

★★

  1. ndarray.reshape()を使う。