参考書紹介(機械学習系) 2021年版
☆機械学習の参考書(2021年版)
とりあえず機械学習を使いたい!用の本
遊び向け。
フリーソフトではじめる機械学習入門(第2版):Python/Wekaで実践する理論とアルゴリズム
- 作者: 荒木雅弘
- 出版社/メーカー: 森北出版
- 発売日: 2018/04/10
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
・Python機械学習プログラミング 達人データサイエンティストによる理論と実践
(impress top gear)
コピーアンドペーストでpythonで動く。思考停止で使いたい人向け。ただし、基本的な手法しか載ってない。
[第2版]Python 機械学習プログラミング 達人データサイエンティストによる理論と実践 (impress top gear)
- 作者: Sebastian Raschka,Vahid Mirjalili,福島真太朗,株式会社クイープ
- 出版社/メーカー: インプレス
- 発売日: 2018/03/16
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
より実践的な実装特化の本
・Kaggleで勝つデータ分析の技術
Kaggleで流行っている比較的新しい機械学習手法の実装ができる。前処理方法も詳しい。
カーネル法
・カーネル多変量解析―非線形データ解析の新しい展開 (シリーズ確率と情報の科学)
Representer定理の説明がわかりやすい。基本はコレで。
カーネル多変量解析―非線形データ解析の新しい展開 (シリーズ確率と情報の科学)
- 作者: 赤穂昭太郎
- 出版社/メーカー: 岩波書店
- 発売日: 2008/11/27
- メディア: 単行本
- 購入: 7人 クリック: 180回
- この商品を含むブログ (32件) を見る
・カーネル法入門―正定値カーネルによるデータ解析 (シリーズ 多変量データの統計科学)
上よりは応用寄りで、上級向け。
カーネル法入門―正定値カーネルによるデータ解析 (シリーズ 多変量データの統計科学)
- 作者: 福水健次
- 出版社/メーカー: 朝倉書店
- 発売日: 2010/11/01
- メディア: 単行本
- クリック: 19回
- この商品を含むブログ (11件) を見る
ベイズ統計
入門というなかれ、かなり詳しい。
機械学習スタートアップシリーズ ベイズ推論による機械学習入門 (KS情報科学専門書)
- 作者: 須山敦志,杉山将
- 出版社/メーカー: 講談社
- 発売日: 2017/10/21
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
有名すぎる本。基本的な話題は大体載っててお得だが、カーネル法は内容が薄いので、上で述べた本もぜひ参考に。
- 作者: C.M.ビショップ,元田浩,栗田多喜夫,樋口知之,松本裕治,村田昇
- 出版社/メーカー: 丸善出版
- 発売日: 2012/04/05
- メディア: 単行本(ソフトカバー)
- 購入: 6人 クリック: 33回
- この商品を含むブログ (20件) を見る
- 作者: C.M.ビショップ,元田浩,栗田多喜夫,樋口知之,松本裕治,村田昇
- 出版社/メーカー: 丸善出版
- 発売日: 2012/02/29
- メディア: 単行本
- 購入: 6人 クリック: 14回
- この商品を含むブログを見る
・ベイズ統計の理論と方法
理論ガチの本。数理統計、統計力学、代数幾何(グレブナー基底)のベースが無いと難し目。
ニューラルネット
・詳細ディープラーニング
RNNの実装に詳しい入門書。RNNはモデルが複雑なので、理論を理解しつつちょっとずつ実装していくのが一番身につく。
・画像認識
CNNベースの画像認識向けの教科書。実装に関してはググるのがベスト。
・複素ニューラルネットワーク
最適化
・しっかり学ぶ数理最適化
分厚くてお買い得。連続最適化だけでなく、離散最適化の基本もほぼ載ってる。
・メタヒューリスティクスと応用
個々の中身はうっすいが、メタヒューリスティックな手法(アニーリング、遺伝アルゴリズム、粒子群最適化など)に関する網羅的な紹介がされている。全部をまとめて紹介してるのはコレくらい。
強化学習
・強化学習
大御所の昔の名著。基本概念はほぼ全て網羅。
- 作者: Richard S.Sutton,Andrew G.Barto,三上貞芳,皆川雅章
- 出版社/メーカー: 森北出版
- 発売日: 2000/12/01
- メディア: 単行本(ソフトカバー)
- 購入: 5人 クリック: 76回
- この商品を含むブログ (29件) を見る
・強くなるロボティック・ゲームプレイヤーの作り方 プレミアムブックス版
~実践で学ぶ強化学習~
実装(C)が比較的詳しく載ってる珍しい本。
強くなるロボティック・ゲームプレイヤーの作り方 実践で学ぶ強化学習 プレミアムブックス版
- 作者: 八谷大岳,杉山将
- 出版社/メーカー: マイナビ出版
- 発売日: 2016/06/08
- メディア: Kindle版
- この商品を含むブログを見る
・これからの強化学習
ナウい手法を多く掲載。
- 作者: 牧野貴樹,澁谷長史,白川真一,浅田稔,麻生英樹,荒井幸代,飯間等,伊藤真,大倉和博,黒江康明,杉本徳和,坪井祐太,銅谷賢治,前田新一,松井藤五郎,南泰浩,宮崎和光,目黒豊美,森村哲郎,森本淳,保田俊行,吉本潤一郎
- 出版社/メーカー: 森北出版
- 発売日: 2016/10/27
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (3件) を見る
バンディット問題、ベイズ最適化
・バンディット問題の理論とアルゴリズム
バンディッド問題に特化した珍しい本。ベイズ最適化などもちゃんとのっていて、役に立つ。個人的には、数理統計をしっかり身につけてから読むべき。
バンディット問題の理論とアルゴリズム (機械学習プロフェッショナルシリーズ)
- 作者: 本多淳也,中村篤祥
- 出版社/メーカー: 講談社
- 発売日: 2016/08/25
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
今後も随時拡張していきます!
グレブナー基底は何に使えるか?
名前はよく聞くグレブナー基底、一体何に使えるんだ?ということで、具体的な応用先を並べてみた。グレブナー基底をわかりやく言うと「多項式の集合を、シンプルで性質の良いものに変えた多項式の集合」である。例えば連立方程式を解くときに1文字ずつ変数消去していくことで解を求めたと思う。つまり、x,y,zが入り混じった複雑な式から、xのみの式、yのみの式..を求めていた。これがまさにグレブナー基底の考えである。
①数式処理システム
グレブナー基底の周辺理論の利点に、文字式を残したまま解析したり、近似なしで求積できることがある。例えば(但し各係数は正)からを求めることができる。もちろん、通常の数値計算ではこういった計算は難しい。数式処理システムのソフトでは、以上の利点からグレブナー基底に関するアルゴリズムが実装されている場合がある[1]。
②整数計画問題
整数計画問題とは、整数の変数に関する多項式等で表される目的関数を、制約条件化で最大あるいは最小にするような変数の値を求める問題である。制約条件の式から生成されるトーリックイデアルのグレブナー基底を算出し、その基底の多項式で割り算を続けていくことで最適化を行うConti-Traversoのアルゴリズムがある[2]。一度グレブナー基底が得られればあとは瞬殺なのだが、その基底を求めるまでに時間がかかるため、大規模な整数計画問題を解くことは難しい。そのため、通常は内点法や分枝限定法などが使われる[3]。
③学習理論
機械学習では、予測精度が学習データのサンプル数に対してどのように振舞うかを議論したいことがよくある(学習理論)。より具体的には尤度関数のでの漸近的挙動を見たい。ただ、機械学習の場合はモデルが複雑すぎて、尤度関数をモデルパラメータの関数としてみると見通しが良くない。そこで、特異点解消定理を用いてより都合の良い変数に変換してから挙動を見る方針をとる場合がある[4]。この特異点解消定理の周辺ではグレブナー基底の理論が用いられている。
④量子アニーリング
量子アニーリングは、イジングモデルと呼ばれる二次関数のモデルの最大値や最小値を求める非ノイマン型の計算手法である[5]。これを用いれば、これまで通常の整数計画法では解けなかったような大規模な問題を拘束に解くことができるのでは、と期待されている。ただし、世の中の問題はかなり複雑なので(例えば高次の多項式)、これをどうやって二次関数に落とし込むかが重要となる。グレブナー基底を用いれば、多項式の問題をうまく二次関数に変換することができる[6]。また、現在開発されている量子アニーリング計算機の多くは、ハードウェアの制約上スピン素子同士の接続に制限があり、イジングモデルの係数を自由に設定できない。従って、量子アニーリングで問題を解くには、先ほど述べた二次関数への変換後、さらにスピン素子の接続を踏まえて埋め込む必要がある。すなわち、グラフ理論の言葉でいうMinor Embeddingである。グレブナー基底を用いれば、この埋め込みも可能である[7]。ただし、問題の変数が大規模な場合は②と同様の理由で通常の整数計画法を用いたほうが良いだろうが。
⑤実験計画法
実験計画法で得られたサンプルから、p値を算出する方法にグレブナー基底を用いることも可能である[8]。p値はサンプル数が増加すると解析的に算出することが難しくなる。そこでマルコフ連鎖モンテカルロ法を用いた数値積分が使用されるのだが、なるべく収束の早いモンテカルロサンプリングが望ましい。その指針をグレブナー基底で与えることができる。
⑥主成分分析
もう一つ最近の話題として、主成分分析へのグレブナー基底適用がある。主成分分析は変数の線形和で書けるような基底をいくつかとり、その基底で表した座標上でデータの分散が最大になるように、基底を決定する手法である。データの分散が大きいほど情報量が多いということなので、主成分分析は情報量が最も多くなるような軸(基底)を求める分析法である。ただ、一般に現実のデータは非線形であるから、必ずしも線形な基底では不十分で、より高次な多項式変換で表される基底を用いたほうが良いだろう。Vanishing Component Analysis (VCA)では、このような基底をグレブナー基底を用いて求める手法を提案している[9]。これにより、非線形なデータでも主成分分析が可能になると期待される。
このように、グレブナー基底には驚くほど広範囲な応用先がある。ただ、現時点で広く実用化されているのは①くらいだろうか。グレブナー基底を求めるアルゴリズムは、現状計算負荷の高いBuchberger'sアルゴリズムくらいしか無いためである。この計算速度が向上すれば、グレブナー基底の応用はさらに浸透していくことだろう。また、各応用先の引用を最後に載せておく。
[1] https://www.riam.kyushu-u.ac.jp/fluid/meeting/17ME-S2/papers/Article_No_13.pdf
[2] https://www.kurims.kyoto-u.ac.jp/~kyodo/kokyuroku/contents/pdf/1876-03.pdf
[3]
しっかり学ぶ数理最適化 モデルからアルゴリズムまで (KS情報科学専門書)
- 作者:梅谷 俊治
- 発売日: 2020/10/26
- メディア: 単行本
- 作者:渡辺 澄夫
- 発売日: 2006/04/27
- メディア: 単行本(ソフトカバー)
[7] https://arxiv.org/pdf/1912.08314.pdf
[8] [9] https://mlai.cs.huji.ac.il/publications/Amir_Globerson/files/Vanishing%20Component%20Analysis.pdf
ガンマ分布の様々な期待値
を母数とするのガンマ分布はと表される。この分布の様々な期待値を計算してみよう。
まずは平均である。
ここで、であること、ガンマ分布の積分が1になることを用いた。
次に、分散を求める。
これと平均の結果により、分散の表式を得る。
次に、指数関数の期待値を求めよう。
これは、いわゆるモーメント母関数のことである。
最後に、対数関数の期待値を求めよう。
と変形できる。ここで、であることを用いた(「'」はに関する微分)。
一項目は、被微分部分が定数1になるため0となる。二項目の微分を実行すると、
となる。ディガンマ関数を用いると、
を得る。これを用いるとガンマ分布のエントロピー等が計算できる。また、https://yoshidabenjiro.hatenablog.com/entry/2016/12/30/023546にもあるようにポアソン分布の変分ベイズ法での計算にも登場する。そろそろ統計検定に出題されるかも..
異なるネットワークを並列したニューラルネットの構築法
kerasでは、直列でどんどん中間層をつなげていく例はよくあるが、並列で異なるネットワークあるいは中間層をつなげる例はあまり少ないので紹介する。
まずは必要なライブラリのインポートと学習データの構築。0~1の乱数5個でできた入力ベクトルを500回分生成する。出力としては、ベクトルの成分和が5/2より大きくなるなら1、そうでないなら-1とする。
from keras.layers import Input, Dense, Concatenate, Lambda import numpy as np from keras.models import Model data = np.random.rand(500,5) labels = (np.sum(data, axis=1) > 2.5) * 2 - 1
次にモデルを構築する。入力はもちろん5個の成分のベクトルだが、それを分割して前3つと後ろ2つで異なるネットワークに接続し、その出力を統合してから全結合層を通すモデルを考える。分割はlambdaによる範囲指定、統合はconcatenateを用いるのがミソ。
inputs=Input(shape=(5,)) x1 = Lambda(lambda x:x[:,:3],output_shape=(3,))(inputs) x2 = Lambda(lambda x:x[:,3:],output_shape=(2,))(inputs) x1_1 = Dense(20, activation='tanh')(x1) x2_1 = Dense(20, activation='sigmoid')(x2) x=Concatenate(axis=-1)([x1_1,x2_1]) y=Dense(1, activation='tanh')(x)
ここで、前3つにはtanh、後ろ3つにはsigmoidを活性化関数とする別々の全結合層を指定した。また、この出力を統合し、tanhを活性化関数とする全結合層を用いた。
次にモデルの学習と、テストデータによる検証を実施する。
model = Model(inputs,y) model.compile('adam', 'hinge', metrics=['accuracy']) model.fit(data, labels, epochs=200, validation_split=0.1) test = np.random.rand(100, 5) predict = np.sign(model.predict(test).flatten()) real = (np.sum(test, axis=1) > 2.5) * 2 - 1 print(sum(predict == real) / 100.0)
テストデータは、学習データと同様に新たな100個の入力ベクトルを生成することで生成した。
最後に構築したモデルの構成図をpydotを用いて出力しよう。pydot環境は①graphvizをhttp://www.graphviz.org/download/からダウンロード→②ダウンロードされたgraphvizのbinフォルダのパスをシステム環境変数に追加→③コマンドブロンプト開きpipによりgraphvizとpydotをインストールの手順でOK。pydotが使用できるようになったら、以下のようにモデルの構成図を画像に出力する。
from keras.utils import plot_model plot_model(model,to_file="model.png")
ニューラルネットの中間層から出力層までのネットワークを取り出す
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)がルジャンドル変換である。