# 行列計算でクロス集計をする ## 前提 ### やりたいこと - クロス分析したい - 下図参照 - その他 - 要件が決まってない - 何でもできるように作ってしまおう! ### 作戦 [[ブラウザ上で複雑な集計を行いたい]] 👉 [[Rust + WebAssembly]] を試す ## 数式 ### 生データ 3 人分の属性データ(性別、年代) $ N = 3 $ $ \begin{pmatrix} 男性 & 女性 & 20 代 & 30 代 & 40 代 \end{pmatrix} $ $ \mathrm{ATTR} = \begin{pmatrix} 1 & 0 & 1 & 0 & 0 \\ 0 & 1 & 1 & 0 & 0 \\ 0 & 1 & 0 & 1 & 0 \end{pmatrix} $ 3 人分の回答データ(10 問) $ \begin{pmatrix} 男性 \cdot 20 代 \\ 女性 \cdot 20 代 \\ 女性 \cdot 30 代 \end{pmatrix} $ $ \mathrm{DATA} = \begin{pmatrix} 1 & 2 & 3 & 4 & 5 & 6 & 1 & 2 & 3 & 4 \\ 5 & 6 & 1 & 2 & 3 & 4 & 5 & 6 & 1 & 2 \\ 3 & 4 & 5 & 6 & 1 & 2 & 3 & 4 & 5 & 6 \end{pmatrix} $ ### クロス集計 - 20 代(性別は問わない) ... 条件数 1 - 20 代女性 ... 条件数 2 集計条件 $ \begin{aligned} \mathrm{COND} &= \begin{pmatrix} 0 & 0 & 1 & 0 & 0 \\ 0 & 1 & 1 & 0 & 0 \end{pmatrix} \\ \\ \mathrm{COND\_COUNT}&= \begin{pmatrix} 1 \\ 2 \end{pmatrix} \end{aligned} $ 活性化関数 (Rectified Linear Unit) $ relu(x) = max(0, x) $ 集計 $ \begin{aligned} \mathrm{MASKBASE} &= \mathrm{COND} \times \mathrm{ATTR}^{\mathrm{T}} \\ &= \begin{pmatrix} 1 & 1 & 0 \\ 1 & 2 & 1 \end{pmatrix} \\ \\ \mathrm{MASKBASE}2 &= \mathrm{MASKBASE} - (\mathrm{COND\_COUNT} \times 1_{1 \times N}) + 1 \\ &= \mathrm{MASKBASE} - \begin{pmatrix} 1 & 1 & 1 \\ 2 & 2 & 2 \end{pmatrix} + \begin{pmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \end{pmatrix} \\ &= \begin{pmatrix} \begin{matrix} 1 & 1 & 0 \\ 0 & 1 & 0 \end{matrix} \end{pmatrix} \\ \\ \mathrm{MASK} &= relu(\mathrm{MASKBASE}2) \\ &= \begin{pmatrix} \begin{matrix} 1 & 1 & 0 \\ 0 & 1 & 0 \end{matrix} \end{pmatrix} \end{aligned} $ 該当する人数 $ 1_{1 \times N} \times \mathrm{MASK}^{\mathrm{T}} = \begin{pmatrix} 2 & 1 \end{pmatrix} $ - 20 代: 2 人 - 20 代女性: 1 人 該当する回答者のスコアの合計 $ \mathrm{MASK} \times \mathrm{DATA} = \begin{pmatrix} 6 & 8 & 4 & 6 & 8 & 10 & 6 & 8 & 4 & 6 \\ 5 & 6 & 1 & 2 & 3 & 4 & 5 & 6 & 1 & 2 \end{pmatrix} $ ### 全ての属性の集計 全属性値 - 全体 - 男性 - 女性 - 20 代 - 30 代 - 40 代 $ \mathrm{ALLATTR} = \\ \begin{pmatrix} 1 & 1 & 1 & 1 & 1 \\ 1 & 0 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 0 & 1 \end{pmatrix} $ 集計 - $\mathrm{COND\_COUNT}$ も作っておけば、クロス集計と同じ計算ロジックになる $ \begin{aligned} \mathrm{MASKBASE} &= \mathrm{ALLATTR} \times \mathrm{ATTR}^{\mathrm{T}} \\ &= \begin{pmatrix} 2 & 2 & 2 \\ 1 & 0 & 0 \\ 0 & 1 & 1 \\ 1 & 1 & 0 \\ 0 & 0 & 1 \\ 0 & 0 & 0 \end{pmatrix} \\ \mathrm{MASK} &= \begin{pmatrix} 1 & 1 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 1 \\ 1 & 1 & 0 \\ 0 & 0 & 1 \\ 0 & 0 & 0 \end{pmatrix} \mathrm{} \end{aligned} $ 該当する人数 $ 1_{1 \times 3} \times \mathrm{MASK}^{\mathrm{T}} = \begin{pmatrix} 3 & 1 & 2 & 2 & 1 & 0 \end{pmatrix} $ - 全体: 3 人 - 男性: 1 人 - 女性: 2 人 - 20 代: 2 人 - 30 代: 1 人 - 40 代: 0 人 各属性のスコアの合計 $ \mathrm{MASK} \times \mathrm{DATA} = \begin{pmatrix} 9 & 12 & 9 & 12 & 9 & 12 & 9 & 12 & 9 & 12 \\ 1 & 2 & 3 & 4 & 5 & 6 & 1 & 2 & 3 & 4 \\ 8 & 10 & 6 & 8 & 4 & 6 & 8 & 10 & 6 & 8 \\ 6 & 8 & 4 & 6 & 8 & 10 & 6 & 8 & 4 & 6 \\ 3 & 4 & 5 & 6 & 1 & 2 & 3 & 4 & 5 & 6 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \end{pmatrix} $ ### 平均 - スコア 0 を未回答とする - 平均の分母から除外する 符号関数 (sign function, sugnum function) $ sgn(x) = \begin{cases} 1 & (x > 0) \\ 0 & (x = 0) \\ -1 & (x < 0) \end{cases} $ $ \mathrm{VALID\_COUNT} = \mathrm{MASK} \times sgn(\mathrm{DATA}) $ ゼロ除算に注意して合計の各要素を $\mathrm{VALID\_COUNT}$ で割る。 ## Rust 実装 - 行列計算できれば言語は何でもよい - Rust だと環境が整っている [[行列計算でクロス集計をする (Rust)]] ## WebAssembly [[Rust + WebAssembly で行列計算]]