<jupyter_start><jupyter_text>4章 word2vec の高速化 CBOW: Continuous Bag-of-Words- 推論ベースの手法- 前後の単語（コンテキスト）から，その単語（ターゲット）を推定するNN**you (　) goodbye and I say hello**- one-hot 表現：単語数を$N$とすると，$N$次元の0-1ベクトルで単語を表現- [図１](https://www.dropbox.com/s/v1hogfasdqmqssh/fig1.jpg?dl=0)- $N$が大きくなると，学習が大変  4.1 word2vecの改良(1)- **入力層のベクトルと重み行列$W_{\rm in}$との積**- 中間層のベクトルと重み行列$W_{\rm out}$との積- softmaxの計算 4.1.1 embedding レイヤ- 入力層 $c = [0,0,1,0,0,\ldots,0]$: 横ベクトル（$N$次元）- 重み行列 $W_{\rm in}\in\mathbb{R}^{N\times M}$$$  W_{\rm in} = \begin{bmatrix}W_{\rm in}(1)\\W_{\rm in}(2)\\\vdots\\W_{\rm in}(N)\end{bmatrix}$$- $c$と$W_{\rm in}$との積$$ \begin{split} cW_{\rm in} &= 0\cdot W_{\rm in}(0) + 0\cdot W_{\rm in}(1) + 1 \cdot W_{\rm in}(2) + 0\cdot W_{\rm in}(3) + \cdots + 0\cdot W_{\rm in}(N)\\ &= W_{\rm in}(2) \end{split}$$- 一般に $i$番目の単語のone-hot表現と$W_{\rm in}$との積は，$i$行目の行ベクトル$W_{\rm in}(i)$ を抜き出す操作となる．- これを **Embedding レイヤ**（埋め込みレイヤ）と呼ぶ - Embedding レイヤ：重み行列から$i$行目を抜き出すレイヤ- Embedding（埋め込み）：単語（離散的なデータ）を$M$次元実数空間$\mathbb{R}^M$に埋め込む 4.1.2 embedding レイヤの実装- 順伝播と逆伝播 - [図２](https://www.dropbox.com/s/mw59gd27wbuzwie/fig2.jpg?dl=0)- バッチ処理のとき - [図３](https://www.dropbox.com/s/wjne7npo6arwxxw/fig3.jpg?dl=0)  4.2 word2vecの改良(2) 4.2.1 中間層以降の計算の問題点- 入力層のベクトルと重み行列$W_{\rm in}$との積- **中間層のベクトルと重み行列$W_{\rm out}$との積**- **softmaxの計算** 4.2.2 多値分類から２値分類へ（**4.2.5 Negative Sampling**と**4.2.6 Negative Samplingのサンプリング手法**の内容を含みます）- 多値分類（これまでの方法） - you (　) hello ... - you と hello からターゲットを（$N$個の単語の中から）予測- **２値分類（高速化）** - [図４](https://www.dropbox.com/s/wrd9hpfonwi1opd/fig4.jpg?dl=0) - you (　) hello ... - you と hello からターゲットが **"say" であるかどうか**を予測（２値） - この場合，"say"の教師データを**正例**と呼ぶ． - "say"以外の単語が入力したとき，出力がどうなるかは何も言えない  - **Negative sampling （負例サンプリング）**- 負例サンプリング - すべての負例（$N-1$個の単語）を用いて学習するのではなく，$N-1$個の中からいくつかをランダムサンプリングして学習する - コーパスの単語の出現頻度（出現確率）に従ってランダムサンプリングを行う（一様乱数ではなく） - よく使われる単語はより正確に分散表現したいため． - ただし，ほとんど使われない単語も学習に使用される確率を（少し）高めるため，確率分布に以下の変換を施す． $$ P'(w_i) = \frac{P(w_i)^{0.75}}{\sum_{j=1}^N P(w_j)^{0.75}} $$ - [図５](https://www.dropbox.com/s/pezn20yevsfkxj6/fig5.jpg?dl=0) 4.2.3 シグモイド関数と交差エントロピー誤差- ２値分類のNN - [図6](https://www.dropbox.com/s/bli1x3j17jtam9r/Fig6.jpg?dl=0) - **スコア**$s\in\mathbb{R}$$$s = h W_{\rm out}^{(j)} = \langle h^\top, W_{\rm out}^{(j)} \rangle$$- ２値分類の活性化関数：**シグモイド関数** $$ y = \frac{1}{1+\exp(-x)} $$ - スコア $s\in\mathbb{R}$ を $[0,1]$の範囲の数（確率）に変換 - 逆伝播 $$ \begin{split} \frac{dy}{dx} &= \frac{e^{-x}}{(1+e^{-x})^2}\\ &= \frac{1+e^{-x}-1}{(1+e^{-x})^2}\\ &= \frac{1}{1+e^{-x}} - \frac{1}{(1+e^{-x})^2}\\ &= y-y^2\\ &= y(1-y) \end{split} $$ - [図７](https://www.dropbox.com/s/9iyszgdap27z95e/fig7.jpg?dl=0)- シグモイド関数に対応した誤差関数：**交差エントロピー誤差**$$ L = - \bigr(t\log y + (1-t) \log(1-y)\bigl) $$ - 逆伝播 $$ \frac{\partial L}{\partial y} = - \left( \frac{t}{y} - \frac{1-t}{1-y} \right) $$  - これより --> [Sigm] --> [CE] --> の逆伝播は  $$ \begin{split} \frac{\partial L}{\partial y} y(1-y) &= - \left( \frac{t}{y} - \frac{1-t}{1-y} \right) y(1-y)\\  &= -t(1-y) + y(1-t)\\  &= -t + ty + y - ty\\  &= y-t  \end{split}  $$ - 出力$y\in[0,1]$と正解ラベル$t\in\{0,1\}$との誤差を逆伝播させれば良い（**誤差逆伝播**） 4.2.4 多値分類から二値分類へ（実装編）- [図８](https://www.dropbox.com/s/ysr58lu4fqopvz2/fig8.jpg?dl=0)   4.3 改良版word2vecの学習- 学習データ：PTBコーパス - Penn Tree Bank または Proposition Tree Bank の略 - ペンシルベニア大学 (University of Pennsylvania) の研究グループが開発 - 学習には非常に時間がかかるため，学習済みパラメータを使用 (cbow_params.pkl) 4.3.3 CVOWモデルの評価- 単語の分散表現 $\Rightarrow$ コサイン類似度による類似単語の表示$$ {\rm similarity}(x,y) = \frac{\langle x,y \rangle}{\|x\|\cdot\|y\|} = \cos(\theta)$$ - $\theta$ は $x$と$y$のなす角 - $\langle x,y \rangle = \|x\|\|y\|\cos\theta$- 単語の類推問題（アナロジー問題） - "king - man + woman = queen"  - king:man = woman:queen - ベクトルの加算と減算が単語の類推として意味を持つ - [図９](https://www.dropbox.com/s/57fp5l8evkfaeym/fig9.jpg?dl=0)<jupyter_code># coding: utf-8
import sys
sys.path.append('..')
from common.util import most_similar, analogy
import pickle


pkl_file = 'cbow_params.pkl'
# pkl_file = 'skipgram_params.pkl'

with open(pkl_file, 'rb') as f:
    params = pickle.load(f)
    word_vecs = params['word_vecs']
    word_to_id = params['word_to_id']
    id_to_word = params['id_to_word']

# most similar task
querys = ['you', 'year', 'car', 'toyota']
for query in querys:
    most_similar(query, word_to_id, id_to_word, word_vecs, top=5)

# analogy task
print('-'*50)
analogy('king', 'man', 'queen',  word_to_id, id_to_word, word_vecs)
analogy('take', 'took', 'go',  word_to_id, id_to_word, word_vecs)
analogy('car', 'cars', 'child',  word_to_id, id_to_word, word_vecs)
analogy('good', 'better', 'bad',  word_to_id, id_to_word, word_vecs)

most_similar('word', word_to_id, id_to_word, word_vecs, top=5)
analogy('cat', 'animal', 'human',  word_to_id, id_to_word, word_vecs)<jupyter_output>[analogy] cat:animal = human:?
 tv: 4.0078125
 damage: 3.7890625
 alto: 3.63671875
 professor: 3.51171875
 ms.: 3.498046875
{'fraction_non_alphanumeric': 0.23745819397993312, 'fraction_numerical': 0.04410535117056856, 'mean_word_length': 4.656028368794326, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 7, 'https://': 9, 'lorem ipsum': 0, 'www.': 9, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '468642', 'license': 'MIT', 'n_tokens_mistral': 3017, 'n_tokens_neox': 2970, 'n_words': 342, 'path': 'Book2_Chapter4/Chapter4資料.ipynb', 'repo_name': 'Keiso-Ken/deep-learning-from-scratch-exercise', 'size': '4784'}