【論文】Graph Convolutional Networks for Classification with a Structured Lebal Space
今回はGraph conv層を持つネットワークを使って、分類問題におけるラベルがグラフ構造を持っている場合に有用であろうという分類器についての話。
[1710.04908] Graph Convolutional Networks for Classification with a Structured Label Space
【感想】
・Graph conv層はConv層の一般化。Convの気持ちが分かった気になった
・Graph convは応用例は色々ありそうだが、まだまだ発展途上な印象
・データもin-houseで、他手法との比較ってとこまではいけてないように見受けた
・Graph Fourier変換あたりの数式ちゃんと追えてない
【Abstruct】
- 多値分類問題においてクラス間の関係性を無視することが多い
- ラベル間の明確なグラフ構造を活用したGraph Convolutional Networkを提案
- Document classification と Object recognitionで実験して、モデル構造無視のモデルよりも結果良かったよ
【slideshareにスライド上げた】
https://www.slideshare.net/KazusaTaketoshi/edit_my_uploads
【論文】Squeeze-and-Excitation Networks
読んだ論文をアウトプットしていく。
[1709.01507] Squeeze-and-Excitation Networks
・Feed-Foward なネットワークでAttention機構を持たせる
・チャネル間の相互関係性を考慮
・Channel-wiseな非線形な相互関係性を学習するために、小さいNNを挟んでるイメージ
・Excitationの2つめの制約である下記でなんでシグモイド採用されてるかわからん。
" second, it must learn a non-mutually-exclusive relationship as multiple
channels are allowed to be emphasised opposed to onehot
activation"
KerasでCifar10分類、とりあえずCNNのAlexModelで
GPUマシンが使えるようになったので、Kerasで用意されているデータセットの中にcifar10があったので学習・分類してみた。
モデルはcifar10の作成者でもあり、ILSVRC2012優勝者でもあるAlex Krinzhvskyさんの優勝時のモデルがベース。
モデルの構成について深層学習 (機械学習プロフェッショナルシリーズ)にあった表を参考にした。
モデル作成してて感じたのはやっぱりKerasの自由度の低さ。
レイヤーに差し込む層のタイプによってはストライドが設定できないなど、完全な再現は無理だった。
この辺はKerasでオリジナルのレイヤーを作成して対応していく必要があるのかも。
もう少し調べてから改めて実装したい。
とりあえず、モデル学習のためのスクリプトが下記。
from keras.datasets import cifar10 from keras.models import Model from keras.layers import Flatten, Dense, Input, Dropout from keras.layers import Convolution2D, MaxPooling2D, BatchNormalization from keras.optimizers import Adam from keras.utils import np_utils def make_network(): input_shape = (3,32, 32) img_input = Input(shape=input_shape) # Block 1 x = Convolution2D(96, 11, 11, activation='relu', border_mode='same', name='conv1')(img_input) x = MaxPooling2D((3, 3), strides=(2, 2), name='pool1')(x) # Block 2 x = BatchNormalization(name='norm1_')(x) x = Convolution2D(256, 5, 5, activation='relu', border_mode='same', name='conv2')(x) x = MaxPooling2D((3, 3), strides=(2, 2), name='pool2')(x) # Block 3 x = BatchNormalization(name='norm2_')(x) x = Convolution2D(384, 3, 3, activation='relu', border_mode='same', name='conv3')(x) x = Convolution2D(384, 3, 3, activation='relu', border_mode='same', name='conv4')(x) x = Convolution2D(256, 3, 3, activation='relu', border_mode='same', name='conv5')(x) x = MaxPooling2D((3, 3), strides=(2, 2), name='pool5')(x) #Classification block x = Flatten(name='flatten')(x) x = Dense(1024, activation='relu', name='fc6')(x) x = Dropout(p = 0.5)(x) x = Dense(1024, activation='relu', name='fc7')(x) x = Dropout(p = 0.5)(x) x = Dense(10, activation='softmax', name='fc8')(x) model = Model(img_input, x) return model def train_model(model, X_train, Y_train, nb_epoch, batch_size): adam = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08) model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy']) model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch, validation_split=0.1, verbose=1) if __name__ == '__main__': (X_train, y_train), (X_test, y_test) = cifar10.load_data() batch_size = 32 nb_classes = 10 nb_epoch = 200 data_augmentation = True # convert class vectors to binary class matrices nb_classes = 10 #きっとone-hotエンコーディング Y_train = np_utils.to_categorical(y_train, nb_classes) Y_test = np_utils.to_categorical(y_test, nb_classes) X_train = X_train.astype('float32') X_test = X_test.astype('float32') X_train /= 255 X_test /= 255 model = make_network() %time train_model(model, X_train, Y_train, nb_epoch = nb_epoch, batch_size = batch_size) #モデルのセーブ model.save('CNN_Trained_for_cifar10.h5')
データサイズが50,000で45,000を学習用、残りを評価用に使い、GPUがGeForce GTX 960、メモリ容量が2GBのマシンでEpoch数を200回にして学習。
かかった時間が13時間半と、自分の予想より結構長かった。
最後にモデルをセーブしておいたので、とりあえずこのモデルの評価はまた次回。
参考
- 作者: 岡谷貴之
- 出版社/メーカー: 講談社
- 発売日: 2015/04/08
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (12件) を見る
確率的勾配法あれこれまとめ
Kerasで選択できる最適化アルゴリズムそれぞれの違いと使い所がいまいちわからんかったので調べてみた。
Incorporating Nesterov Momentum into Adamがアルゴリズムを整理してくれているので理解しやすかった。
とりあえずざっくりと俯瞰した感じだと、いかに効率良く傾斜を降下していくかという課題を解決するっていう大枠からはみ出るものはない。そんで、構築しているモデルの種類やサイズによってベストなアルゴリズムは変わってくるので、突き詰めるのであれば要実験。ただ、上記論文は、NadamかRSMProp使っときゃいいんじゃないっすか、みたいなこと言ってる。なんにしろ2000年代後半以降で進化が進んでいる分野であり、今後もアップデートがあるだろうから追っていきたい。
SGD
まずはオーソドックスな勾配法。
後述するMomentum法や、NAGもKerasの中ではSGDメソッドの中でサポートされている。
Mpomentum
勾配に加えてMomentumベクトルを加えてパラメータを更新する。
Nesterov's accelerated gradient(NAG)
Momuentum法に対して、勾配計算の段階ですでにMomentumを考慮することで、現在のパラメータではなく、次のパラメーターの推定値について計算することで効率よく予測するアルゴリズム。
AdaGrad
それぞれ個別のパラメータに対して異なる学習率を適用するアルゴリズム。
学習率の補正にそれまでのパラメータ[\theta_i]の勾配の二乗和を用いるのでL2ノルムベースのアルゴリズムと分類される。
ここではさきのそれぞれのパラメータの勾配の二乗和のタイムステップまでのベクトル
RSMProp
これもL2ノルムベース。前述の[n]に対して、勾配の二乗の減衰平均_t]を用いる。AdaGradで大きくなりすぎる[n]ことが問題だったがこれで解消。
Adam
Momentum法とRMSPropを組み合わせたもの。
勾配の1乗と勾配の2乗、両方使えばいいじゃん的な。
AdaMax
AdamのL2ノルムを拡張し無限にするとよりシンプルなアルゴリズムとなる、らしい。
Nadam
Adamと違ってNAGとRMSPropを組み合わせたもの。
参考
- 作者: 海野裕也,岡野原大輔,得居誠也,徳永拓之
- 出版社/メーカー: 講談社
- 発売日: 2015/04/08
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (5件) を見る
勾配降下法の最適化アルゴリズム
CODE COMPLETE 第2版 を読んで
『CODE COMPLETE 第2版 上』、『CODE COMPLETE 第2版 下』を読み終えました。
CODE COMPLETE 第2版 上 完全なプログラミングを目指して
- 作者: スティーブマコネル,Steve McConnell,クイープ
- 出版社/メーカー: 日経BP社
- 発売日: 2005/03/26
- メディア: 単行本
- 購入: 44人 クリック: 1,166回
- この商品を含むブログ (288件) を見る
CODE COMPLETE 第2版 下 完全なプログラミングを目指して
- 作者: スティーブマコネル,Steve McConnell,クイープ
- 出版社/メーカー: 日経BP社
- 発売日: 2005/03/26
- メディア: 単行本
- 購入: 16人 クリック: 193回
- この商品を含むブログ (164件) を見る
正直、自分は大規模開発に携わったこともないし、もしかしたらこれから携わることもないかもしれない。そもそも、職業プログラマですらないかもしれない。けどプログラミングを道具として使う立場として、読んで理解できる部分は多かったです。
特に第7部の”ソフトウェア職人気質とは”では情報工学を学ばず、独学でやってきた自分がチームでプログラミングを行う際に注意すべきだろうなと思っていた、レイアウトやステートメントの仕方、変数の名付け方などが体型だって書いてあり、迷った際に帰ってくる部分ができたのがありがたかったです。
次の職務でどの程度コンストラクションに気をつけなければいけないかまだ検討が付かない段階ですので、他の多くの読者の方々とは得られたものが違ったかも知れません。
自分の業務の中でのプログラミングとの付き合い方がわかってくるであろう、半年後、一年後にもう一度読み直してみようと思います。
CodingBatでアルゴリズム100本ノック
これまでの自分のプログラミングは機械学習周辺に偏っていて、コンピューターサイエンスやったことある人間が通ってくる基本的なアルゴリズムについての知識が足りていないとの指摘を受けたので、その部分を埋めるためにCodingBatにチャレンジしてみた。
Coding Bat
http://codingbat.com/
簡単なアルゴリズムをひたすら書かせるプログラミングサイトで、初めの一歩として楽しくできた。
自分のコードはGitHubに載せておくことにする。
次はもう少し難しいアルゴリズムを練習するために、積読になっているこの本を練習する予定。
世界で闘うプログラミング力を鍛える150問 トップIT企業のプログラマになるための本
- 作者: Gayle Laakmann McDowell
- 出版社/メーカー: マイナビ出版
- 発売日: 2012/11/13
- メディア: Kindle版
- この商品を含むブログ (3件) を見る
Scikit-learnのpipeleine.Pipelineが便利
分析する際に、次元圧縮→分類のような流れで行う場合には、scikit-learnのPipelineが便利。特にハイパーパラメーターを探すときには手続が煩雑になることもありますが、まとめて分類器としててGridSearchCVに突っ込むだけで良いのでめんどくさいこと考えずに済みますね。
今回はScikit-learnのサンプルデータの中から、the digits datasetのデータをロードし、PCAでの次元圧縮からSVMでの分類をPipelineでまとめて実行する手順を確認してみました。
コード
まずはデータを読み込み、訓練データとテストデータに分割。
また手書き文字のデータがどんなものかを描き出します。
import numpy as np from sklearn import svm from sklearn.decomposition import PCA from sklearn import datasets from sklearn.grid_search import GridSearchCV from sklearn.pipeline import Pipeline from sklearn.cross_validation import train_test_split from sklearn import metrics from matplotlib import pyplot as plt from matplotlib import cm %matplotlib inline digits = datasets.load_digits() X = digits.data y = digits.target print 'Number of data = {0}, Dimension = {1}'.format(X.shape[0],X.shape[1]) p = np.random.random_integers(0, len(digits.data), 25) for index, (data, label) in enumerate(np.array(zip(digits.data, digits.target))[p]): plt.subplot(5, 5, index + 1) plt.axis('off') plt.imshow(data.reshape(8, 8), cmap=plt.cm.gray_r, interpolation='nearest') plt.title('%i' % label) plt.show() #Split the data X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) Number of data = 1797, Dimension = 64
続いて、PCAで次元削減、SVMでの分類という2つの手順を一つのPipelineで分類器としてまとめます。
今回グリッドサーチでパラメータ探索するためにリスト形式で候補を入れてます。
複数の関数にまたがってパラメーターを指定することになるため、ハイフン二つの後にパラメーター名を指定することで、コントラクタに渡すようになってます。
estimators = [('pca', PCA()), ('svm', svm.SVC())] parameters = {"pca__n_components" : range(2, 6), "svm__kernel" : ["linear", "poly", "rbf", "sigmoid"], 'svm__C': np.logspace(0, 2, 10).tolist(), "svm__gamma": np.logspace(-3, 0, 10).tolist()} pl = Pipeline(estimators)
最後にplを一つの分類器としてみなし、そのままGridSearchCVに突っ込みます。
clf = GridSearchCV(pl, parameters, n_jobs=-1) clf.fit(X_train, y_train) print 'Best_estimator = {0}'.format(clf.best_estimator_.get_params()) #予測 Predict = clf.predict(X_test) n_samples = len(digits.data) expected = digits.target[n_samples * -4 / 10:] predicted = clf.predict(digits.data[n_samples * -4 / 10:]) print("Classification report for classifier %s:\n%s\n" % (clf, metrics.classification_report(expected, predicted))) print("Confusion matrix:\n%s" % metrics.confusion_matrix(expected, predicted)) Best_estimator = {'svm__max_iter': -1, 'svm__coef0': 0.0, 'svm': SVC(C=1.6681005372, cache_size=200, class_weight=None, coef0=0.0, decision_function_shape=None, degree=3, gamma=0.01, kernel='rbf', max_iter=-1, probability=False, random_state=None, shrinking=True, tol=0.001, verbose=False), 'svm__random_state': None, 'pca__copy': True, 'svm__degree': 3, 'pca__n_components': 5, 'svm__gamma': 0.01, 'svm__shrinking': True, 'pca__whiten': False, 'svm__tol': 0.001, 'svm__verbose': False, 'svm__C': 1.6681005372000588, 'steps': [('pca', PCA(copy=True, n_components=5, whiten=False)), ('svm', SVC(C=1.6681005372, cache_size=200, class_weight=None, coef0=0.0, decision_function_shape=None, degree=3, gamma=0.01, kernel='rbf', max_iter=-1, probability=False, random_state=None, shrinking=True, tol=0.001, verbose=False))], 'svm__probability': False, 'svm__class_weight': None, 'pca': PCA(copy=True, n_components=5, whiten=False), 'svm__decision_function_shape': None, 'svm__kernel': 'rbf', 'svm__cache_size': 200} Classification report for classifier GridSearchCV(cv=None, error_score='raise', estimator=Pipeline(steps=[('pca', PCA(copy=True, n_components=None, whiten=False)), ('svm', SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, decision_function_shape=None, degree=3, gamma='auto', kernel='rbf', max_iter=-1, probability=False, random_state=None, shrinking=True, tol=0.001, verbose=False))]), fit_params={}, iid=True, n_jobs=-1, param_grid={'pca__n_components': [2, 3, 4, 5], 'svm__C': [1.0, 1.6681005372000588, 2.7825594022071245, 4.641588833612778, 7.742636826811269, 12.91549665014884, 21.544346900318832, 35.93813663804626, 59.94842503189409, 100.0], 'svm__gamma': [0.001, 0.0021544346900318843, 0.004641588833612777, 0.01, 0.021544346900318832, 0.046415888336127774, 0.1, 0.21544346900318823, 0.46415888336127775, 1.0]}, pre_dispatch='2*n_jobs', refit=True, scoring=None, verbose=0): precision recall f1-score support 0 1.00 0.96 0.98 71 1 0.99 0.97 0.98 73 2 0.94 0.93 0.94 71 3 0.95 0.96 0.95 74 4 0.96 0.96 0.96 74 5 0.97 1.00 0.99 71 6 0.99 1.00 0.99 74 7 0.93 0.92 0.92 72 8 0.84 0.85 0.85 68 9 0.90 0.92 0.91 71 avg / total 0.95 0.95 0.95 719 Confusion matrix: [[68 0 0 0 2 0 1 0 0 0] [ 0 71 0 0 0 0 0 1 0 1] [ 0 0 66 1 0 0 0 0 2 2] [ 0 0 0 71 0 0 0 2 0 1] [ 0 0 0 0 71 0 0 0 3 0] [ 0 0 0 0 0 71 0 0 0 0] [ 0 0 0 0 0 0 74 0 0 0] [ 0 1 0 0 0 0 0 66 5 0] [ 0 0 4 0 1 0 0 2 58 3] [ 0 0 0 3 0 2 0 0 1 65]]