ニューラルネットの中間層から出力層までのネットワークを取り出す
kerasでニューラルネットの入力層から中間層までのネットワークを取り出すのはよくあるけど、中間層から最終層(出力層)までのネットワークを取り出してる例はあまり少ないので紹介する。例として、MNISTの数字画像のデータに対するオートエンコーダーのネットワークを考える。
まずは必要なライブラリのインポートとデータの取得&整形。訓練データとテストデータを定義する。
from keras.layers import Input, Dense from keras.models import Model from keras.datasets import mnist import numpy as np (x_train, y_train), (x_test, y_test) = mnist.load_data() image_size = x_train.shape[1] # = 784 original_dim = image_size * image_size x_train = np.reshape(x_train, [-1, original_dim]) x_test = np.reshape(x_test, [-1, original_dim]) x_train = x_train.astype('float32') / 255 x_test = x_test.astype('float32') / 255
次にモデルを構築する。一気に入力層から最終層までのネットワークを実装せずに、入力層から中間層までのネットワーク(=前半のネットワーク)と、中間層から最終層までのネットワーク(=後半のネットワーク)を分けてモデル化するのがミソ。もたらん分け方を変えれば、任意の部分ネットワークを引っ張ってこれる。
# 前半のネットワーク構築 encoding_dim = 32#中間層のノード数。これが小さいほど特徴量が圧縮される。 input_img = Input(shape=(784,)) x1 = Dense(256, activation='relu')(input_img) x2 = Dense(64, activation='relu')(x1) encoded = Dense(encoding_dim, activation='relu')(x2) encoder = Model(input_img, encoded) encoder.summary() # 後半のネットワーク構築 input_hidden=Input(shape=(encoding_dim),) x3 = Dense(64, activation='relu')(input_hidden) x4 = Dense(256, activation='relu')(x3) decoded = Dense(784, activation='sigmoid')(x4) decoder=Model(input_hidden,decoded) decoder.summary() # 全体のネットワーク構築 z_output = encoder(input_img)#前半のネットワークの出力=中間層の出力のこと outputs = decoder(z_output)#前半のネットワークの出力を新たな入力として、後半のネットワークの出力を求める autoencoder = Model(input_img, outputs)#全体のネットワーク。次で最適化方法や損失関数を定義する。 autoencoder.compile(optimizer='Adam', loss='binary_crossentropy')#optimizerには色々あるが、デフォルト値ではadamがベストだった autoencoder.summary()
次に全体のネットワークを学習する。これにより前半のネットワークや後半のネットワークもフィッティングされる。普通の教師ありの場合には、x_train→y_trainやx_test→y_testなどのように教師データに適宜変更してください(今回はオートエンコーダーなので、入力データと教師データが同じになってます)。
autoencoder.fit(x_train, x_train, epochs=50, batch_size=256, shuffle=True, validation_data=(x_test, x_test))
学習が完了したので、あとは「decoder.predict(中間層に入力したいデータ)」などのコマンドにより、後半のネットワークの予測値を引っ張ってこれる。
確認のため、テストデータを前半のネットワーク(encoder)に入力して得られた中間層の出力値を、後半のネットワーク(decoder)に入力してみよう。当然、これは全体のネットワーク(autoencoder)にテストデータを放り込んだ値に一致するはずである。printでそれぞれの値を出力して一致するか確認してみよう。
encoded_x_test=encoder.predict(x_test) print(decoder.predict(encoded_x_test)) print(autoencoder.predict(x_test))
xlearnでFFMを動かす(備忘録)
FM(Factorization Machines)はRendleが2010年に提案したレコメンダ向けアルゴリズムである(https://www.csie.ntu.edu.tw/~b97053/paper/Rendle2010FM.pdf)。
これの表現力をさらに向上させたFFM(Field-aware Factorization Machines)が2017年にYuchin Juanらにより提案された。
その名の通り,カテゴリごとに異なる潜在ベクトルを用意して使い分けるFMアルゴリズムである。同著者のlibFFMなどでCのソースコードが公開されているが,Pythonで動かしたかったため,xlearn(https://xlearn-doc.readthedocs.io/en/latest/index.html)を導入することにした。xlearnではFFMだけでなく通常のFMなども使用でき,FM関係の計算環境構築に便利。以下,導入手順をまとめておく(Windows/anaconda/pythonを想定)。
①WSL構築,VScode,anaconda導入
https://penyoo.hatenablog.com/entry/2019/11/30/002503の手順でOK。
②xlearn導入
2-1 cmakeインストール
Ubuntuのterminalを開き,sudo apt install cmake
2-2 xlearnのインストール
git clone https://github.com/aksnzhy/xlearn.git
cd xlearn
mkdir build
cd build
cmake ../
make
2-3 インストール状況が100%になったら,初期動作確認。
./run_example.shを実行。xlearnのAAが表示されればOK。
③FFMデモコード動作確認
3-1 python開く
cd python-package
3-2 デモ実行
import xlearn as xl
ffm_model = xl.create_ffm()
ffm_model.setTrain("/home/user/xlearn/demo/classification/criteo_ctr/small_train.txt") ffm_model.setValidate("/home/user/xlearn/demo/classification/criteo_ctr/small_test.txt")
param = {'task':'binary', 'lr':0.2, 'lambda':0.002, 'metric':'acc'}
ffm_model.fit(param, './model.out')
*「user」はひとそれぞれ。上記のアドレスは訓練データとテストデータのデフォルトの保存場所にしましたが,人によっては異なるかも。その場合は,windows側から保存場所を確認したいなら,適当なフォルダを開いて「\\wsl$\Ubuntu\」のおまじないを入力し,xlearnのフォルダ場所を地道に探してみてください。
ルジャンドル変換を高校数学で理解する
ルジャンドル変換(Legendre変換)は,熱力学における特性関数の解析や,最適化問題における双対問題など,様々な分野で現れる重要な理論である。本稿では高校数学のみを用いてルジャンドル変換の導出を図る。
ルジャンドル変換は平たく言えば,凸関数における接線の切片を求める理論である。ここで凸関数はのように下に凸な関数の総称である。
具体的には接線の傾きをとしたときの切片を,の関数として求めるものである。高校数学では,「接線はまず接点の座標をおけ!」というのがスローガンであろう。そういう意味では,傾きを変数で置くところから始まるルジャンドル変換は多少とっつきにくいかもしれない。なので,「接線はまず接点の座標をおけ!」という高校数学のセオリーにのっとってルジャンドル変換を導出してみよう。
このとき,接線の方程式はと書けるから,と比較することで,
を得る。これらの式からを消去すればを求めることができそうだが,式(1)はが与えられていないと陽に解くことができない...そこで,を別の方法で求めてみよう。は凸関数であるから,任意の接線はこれより下に来る。すなわちである。特に,接するとき等号が成り立つので,
となる。ここでは最小値を与える座標を示す。はに依らないため,(3)の第二式が得られる。式(1),(2)よりとなるが,式(3)の結果からはで最小となるため,
を得る。こうして,接点の座標を用いずに傾きのみを用いて,切片の表式を表すことができた。式(4)がルジャンドル変換である。
ルベーグ積分の公式集8:有界変分関数の微分可能性
ルベーグ積分には様々な定理や公式が出てきて理解が追い付かなくなることがよくある。本ブログでは,理解の一助として,基本的な公式をまとめた。内容は随時追加していく予定。
・単調関数の連続性と有界性
・有界変分関数は単調非減少関数の差
有界変分関数は,2つの単調非減少関数の差として表される。一例がである。
・ヴィタリの被覆定理
かつ,がは区間の集合とする。任意のに対して
(1) かつ
を満たす区間が存在するとき,はをヴィタリの意味で被覆するという。ここではルベーグ測度を表す。
また,から構成される外測度に対して-測度有限な集合を,区間の集合が被覆するとする。このとき,
(2)
なる有限個の区間列が存在する。
ルベーグ積分の公式集7:ラドン-ニコディムの定理
ルベーグ積分には様々な定理や公式が出てきて理解が追い付かなくなることがよくある。本ブログでは,理解の一助として,基本的な公式をまとめた。内容は随時追加していく予定。
★ラドン-ニコディムの定理
・変動の定義
可測空間が与えられ,任意のに対して有限の実数値をとる集合関数が完全加法性を満たすとき,上の加法的集合関数と呼ぶ。ただし,測度とは違い負値も取りうる。なお測度と同じように,公式集1の連続性の各性質を満たす。このとき,
をそれぞれ上変動,下変動,全変動と定義する。なお,が成り立つ。
・ジョルダン分解とハーン分解
・絶対連続の定義
測度空間に対する加法的集合関数を考える。これが測度に対して絶対連続であるとは,なるすべてのに対してとなることである。
がある
また特異であるとは,なるある集合が存在し,に対してとなることをいう。
・ラドン-ニコディムの定理
ルベーグ積分の公式集6:積分(フビニの定理)
ルベーグ積分には様々な定理や公式が出てきて理解が追い付かなくなることがよくある。本ブログでは,理解の一助として,基本的な公式をまとめた。内容は随時追加していく予定。
★フビニの定理
・直積測度空間
2つの測度空間に対し,任意のの直積を長方形と呼ぶ。互いに素な長方形の合併
で表される集合全体の族をとする。に対する集合関数を
で定義すると,は上の測度となる。公式集2の測度の拡大の手続きにより,はの生成する-加法族の測度に拡大できる。こうして得られる測度空間を直積測度空間と呼ぶ。
・切り口
2つの可測空間,直積空間上の可測関数があるとする。このとき,任意のに対し関数はの関数として可測関数となる。
また,が-有限な測度空間で,直積空間上の非負可測関数をとするとき,関数は可測関数となる。
・フビニの定理