きっと続かんブログ

勉強したことや人に言いたいことを書く。

SVMに渡すデータの形に注意

scikit-learnのSVMで2値分類を行う簡単なテストとして、以下のような学習データとラベルをclf.fitに渡すと

rain_text = np.array([0,1])  
train_label = np.array(['a','b'])  
ValueError: Found input variables with inconsistent numbers of samples: [1, 2]

こんなエラーが出る。

調べるとどうやら、学習データは、1行に一つのデータがあるような構成でなければならないらしい。
np.arrayや多重リストでは、[]で一つの行とみなす。
つまり「0」「1」と2つのデータを用意したつもりが、「0,1」という一つのデータしか与えられていなかった。

対してラベルは、「a」「b」2つあるので、数が合いませんよ、という訳だ。

train_text = np.array([[0],[1]])  
train_label = np.array(['a','b'])  

こうすることでエラーは消えた。

ちなみに、

train_text = np.array([[[0,1],[0,1]],[[1,1],[1,1]]])  
train_label = np.array(['a','b'])  
ValueError: Found array with dim 3. Estimator expected <= 2.  

SVMでは3次元配列を扱えない。画像を扱うなら、2次元から1次元ベクトルに変換する必要がある。

【tensorflowメモ】tf.app.flags

python実行ファイルにコマンドラインオプションを設定するためのモジュール。

#tf_app_flags.py

import tensorflow as tf

#定義
myflags = tf.app.flags.FLAGS

#tf.app.flags.FLAGS.'型'('引数名', '初期値', '説明')
tf.app.flags.DEFINE_integer("int", 0, "int value")
tf.app.flags.DEFINE_string("str", "test", "string value")
tf.app.flags.DEFINE_boolean("bool", True, "bool value")

def main(argv):
  print(myflags.int, myflags.str, myflags.bool)

if __name__ == '__main__':
  tf.app.run()
#実行
$ python tf_app_flags.py --str="Hello, World!" --bool=False

#結果
0 Hello, World! False

tf.app.flagstf.flagsを見かけるがどっちでも同じようだ。

単純パーセプトロンとロジスティック回帰

両方とも、2値分類に用いられるニューラルネットワーク

単純パーセプトロン

出力が0か1
活性化関数にステップ関数を用いる

0か1やと極端やなあ…確率出力すればえーんやない?
↓↓↓↓↓↓↓↓↓↓

ロジスティック回帰

出力が0~1の確率
活性化関数にシグモイド関数を用いる

2クラスだけじゃなしに多クラス分類解けるようにできんかな
↓↓↓↓↓↓↓↓↓↓

(ついでに)多クラスロジスティック回帰

出力が各クラスの発火確率
活性化関数にソフトマックス関数を用いる

鳥頭すぎて久々に見ると頭から消えてるシリーズ。
なんでも吸収する頭になりたい。

スケーリング

意味

数値を特定の範囲内におさめるために施す処理。 またそのための定数をスケール因子(スケーリング因子)と呼ぶ。

0~1000の値Aを0~50の値Bにスケーリングする。
B = \frac{A}{20}
20がスケール因子に相当する。
上のように、単純に大きすぎる値を小さい範囲に収めたいとき、逆に値を大きくしたいとき、範囲をずらしたい(0~10から10~20など)とき、数値を掛けたり割ったり足したり引いたりする操作をスケーリングと呼ぶ。

登場文献

論文解説 Attention Is All You Need (Transformer) - ディープラーニングブログ

TransformerのAttention機構はScaled Dot-Product Attention(縮小付き内積アテンション)と呼ばれる。数式は以下である。
Attention(Q,K,V) =softmax(\frac{QK^{T}}{\sqrt{d_{k}}})V
通常の内積アテンションと異なるのは、スケール因子\sqrt{d_k}によってスケーリングしている点である。
例と同様、大きすぎる値を小さくする狙いがある。d_kQueryKeyの次元数を意味する。

加重和

意味

ベクトルVと重み付けベクトルWにおいてVとWの内積をとること。

登場文献

論文解説 Attention Is All You Need (Transformer) - ディープラーニングブログ

Dot-Product Attention(内積アテンション)においては、 softmax(QKT)が重みに相当し、これにvalueを掛けることで加重和を取り出す。

Attention is all you need(Transformer)のお勉強

deeplearning.hatenablog.com

りょぼっと様が解説記事を書いてくださってるのでそれで勉強。
ここには読んでいて難しかったところ(ほぼ全て)の解説(個人的解釈)を記事に沿って示します。
浅学なもんで厳密には間違ってるってところがたくさんあると思います。自信無い、間違ってるだろうとこは青字にしてる。

注意は辞書オブジェクト

大前提として、Attention機構はターゲット文の対象単語に対し、「注意すべき」単語をソース文から一つ選ぶ*1んだけど、そのAttentionの内部動作の説明。

Query→ターゲット文の対象単語の特徴を持ったナニカ
Key,Value→ソース文の単語行列の特徴を持ったナニカ

なんでソースの単語行列が2つあるんじゃ、と。同じもの2ついるんかと。
そこはまず、置いておいておこう。

Attention機構が「注意すべき」単語を選ぶまでの流れを見てみよう。
①まずsoftmax(QKT)で、「どの単語に注意すべきか」明らかにする。
ここで[0.01 0.9 0.02 ...]みたいな、「各単語の選ばれる確率」ができる。
②次に、①にValueを掛けて、「注意すべき」単語を取り出す。

流れはこれだけ。 結局なんでKeyとValueが2つあるのか。その答えは次節にあった。

MemoryをKeyとValueに分離する意味

分からん次。
ちょっと思ったのは、KeyとValueって転置関係にあるだけの全く同じ行列では無いっぽい。
それじゃホントに分離する意味ないかそりゃそうか。

加法注意と内積注意

上で動作を説明したAttention、これが内積注意(Dot-Product Attention)。
動作追いながら、あれAttentionて重みって無いのかなとかぼんやり思った。 無いんです。それがいいんです。Transformerはこっちの方式を使う。
ちなみに僕らが普通に思い描く一般的なニューラルネットワーク(レイヤー間の重みを更新していくあれ)、あれを使った方式を加法注意(Additive Attention)という。

ソースターゲット注意と自己注意

  1. Source-Target-Attention
    Queryと、Key,Valueが別の場所からくるやつ。要は普通の(RNNで使われる)Attention。
    Queryはデコーダ側から、Key,Valueはエンコーダ側から来る。

  2. Self-Attention
    入力を全部同じ場所(エンコーダならエンコーダ、デコーダならデコーダ)から引っ張ってくる。

Self-Attentionの利点として、従来のRNNモデル(に使われるSource-Target-Attention)は1度に1つのquery(ターゲット単語)しか与えられない(時系列処理だから)。Transformerは文をガサっとエンコーダorデコーダに投げるから一度に全ての単語をqueryとして与えられる。*2

Self-Attentionが何のためにあるのか分からない…
普通のRNN翻訳モデル(に使われるSource-Target-Attention)ならターゲット文を生成するとき、ソース文のどの単語に「注意」するかを教えてあげる役割がある。Self-Attentionは?

縮小付き内積注意

従来の内積アテンションだと値が大きすぎることがあるらしく、小さくする方向でスケーリングしている様子。
*注釈 スケーリング - きっと続かんブログ

複数ヘッドの注意(Multi-Head Attention)

Transformerは縮小付き内積アテンションを複数並列化した構造を持っておりこれをMulti-Head Attentionと呼ぶ。
Multi-Head Attentionの一連の動作としては、各ヘッダ(縮小付き内積アテンション)でアテンションを計算したのち、それらを結合(concat)、線形変換(linear)する。
並列化するのはそのほうが単一で用いるより性能が高くなるためである。この理由として
「Multi-Head Attentionは各ヘッドが異なる位置の異なる部分空間を処理すると解釈でき、単一のアテンションでは加算がこれを妨げてしまう」
とあるがよくわからない。

感想

まだ読み終えてないけど、分からないことが多すぎる。明らかに知識不足!

*1:これをハードアテンションという。複数ベクトルの重み付き平均を用いる手法もあり、そちらはソフトアテンションと呼ばれる。内積アテンションは加重和だからソフトアテンションかな

*2:超自信ない。

Quick-Thought使ってみたい

Quick-Thoughtとは

2018年に登場した文の分散表現獲得手法の一つ。
Skip-Thought(2015)が「前後の文を予測して生成する」モデルなのに対し、
Quick-Thoughtは「次の文を文グループから選んで当てる」モデル。
「生成する」タスクより「選択する」タスクの方が簡単。従ってシンプルな構造・高速な計算が実現できる。
さらに、構文のような本来不要な特徴を省いて「文の意味」だけに的を絞った特徴抽出が可能(ほんとかな)。

実装はここに。

github.com

GitHub解説

英語苦手だからメモっとく。TensorflowによるQuick-Thoughtの実装。Chris ShallueさんがTensorflowで実装したSkip-Thoughtをベースにしている。

Model configuration files(設定ファイル)

モデルの設定をjson形式でまとめる。見やすい。model_configs にサンプルがある。
例えば"mode"は、どんな単語embeddingを使うか(fixed,trained,expand)。

Pretrained Models(サンプルモデル)

データセット"BookCorpus","UMBC"で学習したMC-QT(MultiChannel Quick Thought)モデルがここにおいてるよ。
モデルと共に辞書も置いてるみたいですね。

Training a Model(モデルの学習)

Prepare the Training Data(データの準備)

データのフォーマットとしてTFRecordを採用。
scripts/data_prep.shは、辞書ファイル(VOCAB_FILE)とトークンファイル(TOKENIZED_FILES)からTFRecord形式のデータを生成するスクリプト
・辞書ファイルは、各行に1単語を記述(ただし、最初の行はとする)
トークンファイルは、各行にトークン化された文を記述(ソース文書の順序を保つこと)

Run the Training Script(学習の実行)

モデルの学習はrun.shを実行することで行う。

DATA_DIR #上で準備したTFRecordファイルのパス
RESULTS_HOME #結果を出力するディレクトリ
CFG #設定ファイルの上位ディレクトリ
MDL_CFGS #CFGのパス
GLOVE_PATH #GloVeで獲得した単語embeddingへのパス

レーニングを実行すると、設定ファイルは$RESULTS_HOME/$CFGに出力される。

Evaluating a Model(モデルの評価)

Expanding the Vocablary(オプション:語彙の拡張)

Skip-Thoughtの論文で提案された手法を用いて、学習に使用する語彙を拡張することが可能である。
Skip-Thoughtは単語の分散表現化にword2vecを用いていたので多分それのこと。
voc_exp.shで実行。あらかじめ学習済みのword2vecモデルが必要。

Evaluation on downstream tasks(学習タスクの評価)

語彙辞書の作成やトークン化など”上流”タスクに対し、ニューラルネットワークを用いたモデル学習のことを”下流(downstream)”タスクと呼んでいるみたい。
評価にはscripts/eval.shを実行する。 Skip-Thoughtモデルの作成者が用いた評価スクリプトも必要なため、RyanさんのGitHubリポジトリ※をクローンする必要がある。

※Skip-Thoughtの実装は2つあり、著者のRyanさんがTheanoで、ChrisさんがTensorflowで実装している。

今後の予定

とりあえず動くように頑張る。cloneしてスクリプトファイル実行すれば即動くってわけにはいかなそうだ。先週RyanさんのSkip-Thoughtを試したんだけど、Chrisさんのほう使ってれば楽だったかなあ。。