自然言語処理の分野では文章の表現手法としてOne-hotベクトル表現が使用されることが多いようです。One-hotベクトル表現は、データ量が増加するというデメリットもありますが、表現がシンプルであり行列計算に適していますので本サイトでもこの表現を利用します。ありますが、本サイトでは、速度の点で圧倒的に優れていることに加えて、Pythonから比較的簡単に利用できるオープンソースの形態素解析エンジンであるMeCabを使用します。PythonやMeCabもこれらの3種類の環境で動作するよう構築しておく必要があります。インストールするのが便利です。Ubuntu18.04では最初からPythonがインストールされているため、プリインストールされているPythonを最新版に更新して利用する方が簡単でしょう。Sequence)技術を使用しますので、以下Encoder-Decoderモデル用のデータを用いて解説して行きます。翻訳やチャットなどの基本モデルとなっています。チャット具体例でのEncoder-Decoderモデルを考えてみましょう。」というEncoderの入力に対して、「はい、今日は晴れていて気持ちがいいですね。Decoderモデルの入力も単語IDベクトルで与えますし、出力単語IDベクトルで得ることになります。上記の説明では「はい、今日は晴れていて気持ちがいいですね。」をDecoderの出力と記述しましたが、これはDecoderの入力でもあるのです。Decoderが単語IDを出力する度に、その単語IDをDecoderの時系列入力として与えて行って順次出力を得ることにより、新たな時系列データである文章を生み出して行きます。このように、日本語をEncoder-Decoderモデルで処理する場合には、まず形態素解析を行って単語IDベクトルで表す必要があります。本サイトでは、Encoderの入力文章をEncoderコーパス、Decoderの入出力文章をDecoderコーパスと呼ぶことにします。」→「はい、今日は晴れていて気持ちがいいですね。」というチャットの応答(「Encoderコーパス」→「Decoderコーパス」)の形態素解析例を見てみましょう。promptでPythonを起動してMeCabのインスタンス'm'を作成します。promptのプロンプト(入力を促す表示)であり、'>>>'はPythonのプロンプトです。「今日/は/晴れ/です/ね/。」→「はい/、/今日/は/晴れ/て/い/て/気持ち/が/いい/です/ね/。」Encoderコーパスは6個の形態素に、Decoderコーパスは14個の形態素に分解されることが分かります。print(m.parse("今日は晴れですね。print(m.parse("はい、今日は晴れていて気持ちがいいですね。次に、MeCabの形態素解析結果を使用してEncoder、Decoderの入出力を単語IDベクトルで表示してみましょう。Encoder入力文章→Decoderの入出力文章の順にスキャンするとして、出現した形態素ごとに単語ID(正確には形態素ID)として登録し、その単語IDベクトルを使用して文章を表示します。一般の文章の現れる形態素の単語IDは2から始めることにします。「今日(2)/は(3)/晴れ(4)/です(5)/ね(6)/。(7)」→「はい(8)/、(9)/今日(2)/は(3)/晴れ(10)/て(11)/い(12)/て(11)/気持ち(13)/が(14)/いい(15)/です(5)/ね(6)/。)中の番号が単語IDです。ここで注意して頂きたいのは、「晴れ」という単語が2回現れていますが、1回目は名詞として現れ、2回目は動詞として現れています。品詞が異なれば、文章中でその出現の仕方も異なりますので、これらは別単語として登録します。多数の文章がある場合にはスキャンする順序により単語IDが異なりますが、気にしないで新たに出現した単語と品詞を調べて、新たな形態素であれば新単語として登録して行けば良いだけです。このような処理により、EncoderコーパスおよびDecoderコーパスは(1)式および(2)式のような6次元および14次元の単語IDベクトルとして表現されます。単語IDから単語や品詞などの形態素を探し出したり、逆に、単語から単語IDを探し出したりできるよう、Pythonの辞書変数としてまとめておくと良いでしょう。15:'いい'}ここで、二回目に出て来た品詞が異なる同単語には先頭に'_'を付けて辞書登録しています。Decoderの出力を文章として表現する際には先頭の'_'を除去して表示すれば良いだけです。One-hotベクトルによるコーパスの表現EncoderコーパスおよびDecoderコーパスは、One-hotベクトル表記すると(3)式および(4)式のような6行16列および14行16列の行列として表示されます。ここで、行数はEncoderコーパスおよびDecoderコーパスの形態素数であり、(1)式および(2)式の単語IDベクトルの次元数と一致し、列数は語彙数になります。~\(T-1\)の時系列情報を扱いますが、このモデルの時間のスパン\(T\)がEncoderコーパスやDeecoderコーパスの形態素数に対応しています。\]このOne-hotベクトル(One-hot行列)はスパース(sparse:スカスカ)な行列ですが、語彙数が増えるに伴って膨大な行列になってしまいます。このような表現を使用することにより内部の演算がとても単純化されることから言語処理の分野ではOne-hotベクトルを使用することが多いようです。述べた通り、CBOWモデルを始めとするword2vec技術では単語の分散表現を行い、単語は意味を的確に表す多次元ベクトルで表現されます。w_{ij}\)で表現されます。重み行列の積が使用されます。ここでは、EncoderコーパスやDecoderコーパスなどの時系列入力のOne-hot行列\(x_{ti}\)と重み\(w_{ij}\)との積を求めるEmbedding層の処理について考えてみましょう。Embedding層の処理は次式で表されます。ここで、入力層であるコーパス行列\(x_{ti}\)は\(T\)x\(V\)の行列、\(w_{ij}\)は\(V\)x\(D\)の行列ですので、これらの積である単語ベクトル層の状態\(h_{tj}\)は\(T\)x\(D\)の行列になります。\(T\)は時系列情報の長さ、即ちEncoderコーパスやDecoderコーパスの単語IDベクトルの次元数であり、\(V\)は入力ベクトルの次元数(語彙数)、\(D\)は単語の意味表す単語ベクトルの次元数です。図1の例では、コーパス行列の\(t\)行は\(V\)列のみ1で他は0ですので、\(h_{tj}\)の\(t\)行は重み\(w_{ij}\)の\(V\)行を抽出するだけで良いことが分かります。重み\(w_{ij}\)の\(i\)行の行ベクトルを抽出するという処理に帰着されますので、コンピュータメモリーも計算時間も大幅に節約できることが分かります。この単語IDに該当する重み\(w_{ij}\)の\(i\)行を抽出すれば良いだけになるのです。Embedding層の処理なお、Embedding層を実装するためにはEmbedding層の誤差逆伝播を知る必要があります。