import joblib
import numpy as np
import pandas as pd
from gensim.models import KeyedVectors
from tqdm import tqdm


def culcSwem(row):
    global model
    swem = [model[w] if w in model.vocab else np.zeros(shape=(model.vector_size,)) for w in row['TITLE'].split()]
    swem = np.mean(np.array(swem), axis=0)
    return swem


X_train = pd.read_table('ch06/train.txt', header=None)
X_valid = pd.read_table('ch06/valid.txt', header=None)
X_test = pd.read_table('ch06/test.txt', header=None)
use_cols = ['TITLE', 'CATEGORY']
n_train = len(X_train)
n_valid = len(X_valid)
n_test = len(X_test)
X_train.columns = use_cols
X_valid.columns = use_cols
X_test.columns = use_cols

data = pd.concat([X_train, X_valid, X_test]).reset_index(drop=True)

tqdm.pandas()
model = KeyedVectors.load_word2vec_format('ch07/GoogleNews-vectors-negative300.bin', binary=True)
swemVec = data.progress_apply(culcSwem, axis=1)

X_train = np.array(list(swemVec.values)[:n_train])
X_valid = np.array(list(swemVec.values)[n_train:n_train + n_valid])
X_test = np.array(list(swemVec.values)[n_train + n_valid:])
joblib.dump(X_train, 'ch08/X_train.joblib')
joblib.dump(X_valid, 'ch08/X_valid.joblib')
joblib.dump(X_test, 'ch08/X_test.joblib')

y_data = data['CATEGORY'].map({'b': 0, 'e': 1, 't': 2, 'm': 3})

y_train = y_data.values[:n_train]
y_valid = y_data.values[n_train:n_train + n_valid]
y_test = y_data.values[n_train + n_valid:]

joblib.dump(y_train, 'ch08/y_train.joblib')
joblib.dump(y_valid, 'ch08/y_valid.joblib')
joblib.dump(y_test, 'ch08/y_test.joblib')
pythonを用いて、手持ちの学習データ、検証データ、評価データを行列・ベクトルに変換したい。例えば、学習データについて、すべての事例$$x_i$$の特徴ベクトル$$\boldsymbol{x}_i$$を並べた行列$$X$$と、正解ラベルを並べた行列（ベクトル）$$Y$$を作成したい。

$$
X = \begin{pmatrix} 
  \boldsymbol{x}_1 \\ 
  \boldsymbol{x}_2 \\ 
  \dots \\ 
  \boldsymbol{x}_n \\ 
\end{pmatrix} \in \mathbb{R}^{n \times d},
Y = \begin{pmatrix} 
  y_1 \\ 
  y_2 \\ 
  \dots \\ 
  y_n \\ 
\end{pmatrix} \in \mathbb{N}^{n}
$$

ここで、$$n$$は学習データの事例数であり、$$\boldsymbol{x}_i \in \mathbb{R}^d$$と$$y_i \in \mathbb{N}$$はそれぞれ、$$i \in \{1, \dots, n\}$$番目の事例の特徴量ベクトルと正解ラベルを表す。
なお、今回は「ビジネス」「科学技術」「エンターテイメント」「健康」の4カテゴリ分類である。$$\mathbb{N}_{<4}$$で$$4$$未満の自然数（$$0$$を含む）を表すことにすれば、任意の事例の正解ラベル$$y_i$$は$$y_i \in \mathbb{N}_{<4}$$で表現できる。
以降では、ラベルの種類数を$$L$$で表す（今回の分類タスクでは$$L=4$$である）。

$$i$$番目の事例の特徴ベクトル$$\boldsymbol{x}_i$$は、次式で求める。

$$
\boldsymbol{x}_i = \frac{1}{T_i} \sum_{t=1}^{T_i} \mathrm{emb}(w_{i,t})
$$

ここで、$$i$$番目の事例は$$T_i$$個の（記事見出しの）単語列$$(w_{i,1}, w_{i,2}, \dots, w_{i,T_i})$$から構成され、$$\mathrm{emb}(w) \in \mathbb{R}^d$$は単語$$w$$に対応する単語ベクトル（次元数は$$d$$）である。すなわち、$$i$$番目の事例の記事見出しを、その見出しに含まれる単語のベクトルの平均で表現したものが$$\boldsymbol{x}_i$$である。今回は単語ベクトルとして、問題60でダウンロードしたものを用いればよい。$$300$$次元の単語ベクトルを用いたので、$$d=300$$である。

$$i$$番目の事例のラベル$$y_i$$は、次のように定義する。

$$
y_i = \begin{cases}
0 & (\mbox{記事}x_i\mbox{が「ビジネス」カテゴリの場合}) \\
1 & (\mbox{記事}x_i\mbox{が「科学技術」カテゴリの場合}) \\
2 & (\mbox{記事}x_i\mbox{が「エンターテイメント」カテゴリの場合}) \\
3 & (\mbox{記事}x_i\mbox{が「健康」カテゴリの場合}) \\
\end{cases}
$$

なお、カテゴリ名とラベルの番号が一対一で対応付いていれば、上式の通りの対応付けでなくてもよい。

以上の仕様に基づき、以下の行列・ベクトルを作成し、ファイルに保存せよ。

+ 学習データの特徴量行列: $$X_{\rm train} \in \mathbb{R}^{N_t \times d}$$
+ 学習データのラベルベクトル: $$Y_{\rm train} \in \mathbb{N}^{N_t}$$
+ 検証データの特徴量行列: $$X_{\rm valid} \in \mathbb{R}^{N_v \times d}$$
+ 検証データのラベルベクトル: $$Y_{\rm valid} \in \mathbb{N}^{N_v}$$
+ 評価データの特徴量行列: $$X_{\rm test} \in \mathbb{R}^{N_e \times d}$$
+ 評価データのラベルベクトル: $$Y_{\rm test} \in \mathbb{N}^{N_e}$$

なお、$$N_t, N_v, N_e$$はそれぞれ、学習データの事例数、検証データの事例数、評価データの事例数である。

ここで、nは学習データの事例数であり、xi∈Rdとyi∈Nはそれぞれ、i∈{1,…,n}番目の事例の特徴量ベクトルと正解ラベルを表す。 なお、今回は「ビジネス」「科学技術」「エンターテイメント」「健康」の4カテゴリ分類である。N<4で4未満の自然数（0を含む）を表すことにすれば、任意の事例の正解ラベルyiはyi∈N<4で表現できる。 以降では、ラベルの種類数をL
で表す（今回の分類タスクではL=4である）。

i番目の事例はTi個の（記事見出しの）単語列(wi,1,wi,2,…,wi,Ti)から構成され、emb(w)∈Rd
は単語wに対応する単語ベクトル（次元数はd）である。すなわち、i番目の事例の記事見出しを、その見出しに含まれる単語のベクトルの平均で表現したものがxiである。今回は単語ベクトルとして、問題60でダウンロードしたものを用いればよい。300次元の単語ベクトルを用いたので、d=300である。

i 番目の事例のラベルyiは、次のように定義する。

0(記事xiが「ビジネス」カテゴリの場合)
1(記事xiが「科学技術」カテゴリの場合)
2(記事xiが「エンターテイメント」カテゴリの場合)
3(記事xiが「健康」カテゴリの場合)

なお、カテゴリ名とラベルの番号が一対一で対応付いていれば、上式の通りの対応付けでなくてもよい。

以下の行列・ベクトルを作成し、ファイルに保存せよ。

学習データの特徴量行列、学習データのラベルベクトル、検証データの特徴量行列、検証データのラベルベクトル、評価データの特徴量行列、評価データのラベルベクトル

+ 学習データの特徴量行列: $$X_{\rm train} \in \mathbb{R}^{N_t \times d}$$
+ 学習データのラベルベクトル: $$Y_{\rm train} \in \mathbb{N}^{N_t}$$
+ 検証データの特徴量行列: $$X_{\rm valid} \in \mathbb{R}^{N_v \times d}$$
+ 検証データのラベルベクトル: $$Y_{\rm valid} \in \mathbb{N}^{N_v}$$
+ 評価データの特徴量行列: $$X_{\rm test} \in \mathbb{R}^{N_e \times d}$$
+ 評価データのラベルベクトル: $$Y_{\rm test} \in \mathbb{N}^{N_e}$$