ubuntuメモ

$ sudo apt-get install gnome-tweak-tool
$ sudo apt-get install emacs g++ gcc make global gauche sbcl
$ sudo apt-get install language-pack-ja* ibus-mozc emacs-mozc python3-pip
$ update-locale LANG=ja_JP.UTF-8 LANGUAGE="ja_JP:ja" 
$ sudo update-locale LANG=ja_JP.UTF-8 LANGUAGE="ja_JP:ja" 
$ source /etc/default/locale 
$ killall ibus-daemon 
$ ibus-daemon -d -x &
$ git clone https://github.com/yascentur/RictyDiminished.git
$ mv ../Downloads/RictyDiminished-master.zip .
$ unzip RictyDiminished-master.zip 
$ cd RictyDiminished-master
$ mv RictyDiminished-master /usr/local/share/fonts/RictyDiminished
$ sudo mv RictyDiminished-master /usr/local/share/font/RictyDiminished
$ fc-cache -fv

matplotlibのメモ

覚えておく点

  • matplotlibの使い方をすぐ忘れる(特に、subplot)。この書き方にこだわる必要は無いけれど、要点だけまとめておく。
  • 手順としては、figureを作る(大きなキャンバスを定義)、figureに対してadd_subplotでサブキャンバスを作る。これはaxesって言うオブジェクトらしい。で、axesに対して描画コマンドを送る。複数のサブキャンバスを入れる場合はこれを繰り返す。
import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(10, 10)) # unit is inch

# Add a subplot and draw on it.
ax1 = fig.add_subplot(2, 1, 1) # row, col, idx
ax1.set_title('Graph title is here.')
ax1.set_xlabel('x-label')
ax1.set_ylabel('y-label')
x = np.linspace(0, 2*3.14, 100)
y = np.sin(x)
ax1.plot(x, y, '-')

# Add another subplot and draw an image on it.
ax2 = fig.add_subplot(2, 1, 2) # row, col, idx
rand_img = np.random.randn(100, 100)
ax2.imshow(rand_img, cmap='gray')

plt.show()

Kerasのバックエンドの使い方

  • 勾配情報を取得したり、特定のレイヤの出力を得たい場合など、色々な場面でKerasプログラムの中でTensorflowレイヤの操作をしたいことが出てくる。そんな時に使うのがバックエンド。
  • 多くはドキュメント見れば良いが、良く分からないAPI(functionとか)もあるのでメモを残しておく。

インポート

  • バックエンドを使う場合は下記をインポートする。
from keras import backend as K

基本

  • variableやplaceholderなどを定義できる。値を見る場合はget_value、足し算や引き算なども可能。
x = K.variable(np.random.rand(2,2))
y = K.variable(np.random.rand(2,2))
K.get_value(x)
K.get_value(y)
K.get_value(x+y)

function(inputs, outputs)

  • これがはじめ良くわからなかった。
  • まずは引数をしっかり理解する。inputsはplaceholderのリスト、outputsはテンソルのリスト。どっちもリストな点に注意。
  • functionはプレスホルダーinputsを入力として、outputsを計算する関数を返してくれる。outputsは当然何かしらのテンソル計算。もし、引数を取らない場合は空リストを与えれば良い。
  • 呼び出す(call)する場合は、何かプレースホルダに与えて呼び出すだけ。ただし、ここで注意!!Keras(というかTF)のInputsは0次元目がサンプルサイズになっているようなので、バッチデータじゃなくて単一のデータを渡す場合には、expand_dimsとかで次元を増やすことが必要。
in1 = Input(shape=(2, 2))
x = K.variable(np.random.rand(2,2))
y = K.variable(np.random.rand(2,2))
out1 = in1 + x
out2 = in1 + y

# Define function
fn = K.function([in1], [out1, out2])

# Call the defined function
o1, o2 = fn([np.expand_dims(np.random.rand(2, 2), 0)])

Kerasの処理テンプレート

メモ

  • モデルのcompile時に与えるmetricsは、学習の各エポック毎に計算する学習の指標を表すもの。損失関数は何もやらなくても計算しているので、損失関数以外を指定する。自分で関数を作っても良いが、大概は用意されている。良くあるサンプルではaccuracyが指定されているが、これは分類問題では損失関数がクロスエントロピーなのに対して、実際の正解率を計算してくるもの。
  • kerasの終了時に、「tensorflowがNoneはdelは無い」みたいなエラーを出すときは、バックエンドのセッションのクリアをちゃんと呼ぶようにする。tfが別スレッドで動いていて、tfが終了する前に親プロセスのkerasが終了してしまう、みたいな状況なのかな?
  • scikit-learnとの融合で複雑な交差検証は出来るけれど、シンプルにやるだけならfitにvalidation_splitを指定する。
  • fitの返り値はエポック毎のlossとmetricsの値を保存している。返り値をretとすると、ret.history['loss']などでアクセスできる。validation_splitを指定していればret.history['val_loss']も保存されている。
  • 結果を保存するとき、モデルはmodel.saveで良い。モデルをjsonで、重みは別途model.save_weightsで保存する例がドキュメントに書いてあるけれど、何でだろう?モデルの構成だけ保存したい(重みは大きいから不要)とかいう状況あるのかな?。また、fitの返り値はpythonオブジェクトなのでpickleで保存する。(その際、返り値自体を保存しようとするとなぜかエラーが起きる。なんでだろう?。とりあえず、historyだけなら保存出来た。)
import numpy
import matplotlib.pyplot as plt
import pickle
import keras.backend as K
from keras.models import Sequential
from keras.layers import Dense
from keras.callbacks import EarlyStopping

def gen_model():
    model = Sequential()
    model.add(Dense(12, input_dim=8, activation='relu'))
    model.add(Dense(6, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='binary_crossentropy', optimizer='adam',
                  metrics=['accuracy'])
    return model

def plot_results(history):
    plt.title('learning history')
    plt.xlabel('epochs')
    plt.ylabel('loss or accuracy')
    plt.plot(history.history['loss'], label='loss')
    plt.plot(history.history['val_loss'], label='val_loss')
    plt.grid()
    plt.legend()

# Data preparetion
dataset = numpy.loadtxt("pima_indians_diabetes.csv", delimiter=",")
X = dataset[:, 0:8]
Y = dataset[:, 8]

# Model generation
model = gen_model()
model.summary()

# Model fitting with validation
early_stopping = EarlyStopping(patience=3)
history = model.fit(X, Y, batch_size=16, epochs=100, callbacks=[early_stopping],validation_split=0.1)

# Save results
model.save("model.hd5")
with open('learning_history.pkl', 'wb') as f:
    pickle.dump(history.history, f)

# plot loss and validation loss
plot_results(history)

K.clear_session()

Kerasで中間ノードの出力を確認する。

kerasのドキュメントのFAQに書かれているので、それ通りにやれば良い。一応、良くあるボストンの家の価格のデータの例を記載。

  • そう言えば、kerasが終了時にsessionのdelに失敗する場合がある。ちゃんと、backendのclear_session()を呼ぶ。
import numpy
import pandas
from keras.models import Sequential, Model
from keras.layers import Dense, Input
from keras.callbacks import EarlyStopping
import keras.backend as K

# Prepare dataset
df = pandas.read_csv("boston_house_price.csv", delim_whitespace=True, header=None)
X = df.values[:, 0:13]
Y = df.values[:, 13]

def gen_model():
    inputs = Input(shape=(13,), name='input_layer')
    x = Dense(13, activation='relu', name='1st_layer')(inputs)
    output = Dense(1, name='output_layer')(x)
    model = Model(inputs=inputs, outputs=output)
    model.compile(loss='mean_squared_error', optimizer='adam')
    return model

model = gen_model()
model.summary

early_stopping = EarlyStopping(patience=5, verbose=1)
model.fit(X, Y, batch_size=16, epochs=100, callbacks=[early_stopping], validation_split=0.1)

# Intermediate Layer output
intermediate_model = Model(inputs=model.input, outputs=model.get_layer('1st_layer').output)
intermediate_output = intermediate_model.predict(X)
print(intermediate_output)

K.clear_session()

Keras with scikit-learnのメモ

KerasはTensorflow/Theanoを使って良くあるDeep Learningアルゴリズムのパタンを効率的に実装するライブラリだけど、機械学習と言えばデータ前処理やCross-Validation,パラメタ探索とか他にも共通してやることがたくさんある。そんな機械学習共通のライブラリと言えばscikit-learnでしょ、ということで、Kerasはscikit-learnへのラッパーも提供している。

使い方の概要

  • sklearnのCVやグリッドサーチなどは、分類器(Classifier)、回帰器(Regressor)ともにEstimatorクラスのオブジェクトを受け取ることを想定している。
  • kerasはそれらのEstimatorを返すラッパーを提供していて、それがKerasClassifierとKerasRegressor。
  • KerasClassifer(Regressor)はモデルを返す関数を引数として与える必要がある。それを何か(gen_modelなど)作って渡すだけで、後はscikit-learnのEstimatorと同じように扱ってくれる。
  • KerassRegressorに渡すbuild_fnが引数を取る場合、build_fnの後ろにそのままキーワード引数として与えてあげれば良い。epochsとかはデフォルトなのかな?(例 KerasRegressor(build_fn=gen_model, arg1=xxx, arg2=yyy, epochs=...)

kFold-CVをする場合

# データセットはpima_indians_diabets
import numpy
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import cross_val_score

# Data preparetion
dataset = numpy.loadtxt("pima_indians_diabetes.csv", delimiter=",")
X = dataset[:, 0:8]
Y = dataset[:, 8]


def gen_model():
    model = Sequential()
    model.add(Dense(12, input_dim=8, activation='relu'))
    model.add(Dense(6, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='binary_crossentropy', optimizer='adam',
                  metrics=['accuracy'])
    return model


# KerasClassifier/KerasRegressor can be used as same as scikit_learn estimator.
model = KerasClassifier(build_fn=gen_model, epochs=10, batch_size=10)

# scikit_learn's cross-validation flow
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=1)
results = cross_val_score(model, X, Y, cv=kfold)
print(results.mean())

Grid-Searchする場合

  • 同様にGSも簡単にやってくれる。活性化関数、初期化方式、バッチサイズ, エポック数を探索する場合の例。
import numpy
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import GridSearchCV


dataset = numpy.loadtxt("pima_indians_diabetes.csv", delimiter=",")
X = dataset[:, 0:8]
Y = dataset[:, 8]


def create_model(optimizer='rmsprop', init='glorot_uniform'):
    model = Sequential()
    model.add(Dense(12, input_dim=8, kernel_initializer=init, activation='relu'))
    model.add(Dense(8, kernel_initializer=init, activation='relu'))
    model.add(Dense(1, kernel_initializer=init, activation='sigmoid'))
    model.compile(loss='binary_crossentropy', optimizer=optimizer,
                  metrics=['accuracy'])
    return model


# KerasClassifier/KerasRegressor can be used as same as scikit_learn estimator.
model = KerasClassifier(build_fn=create_model)

# Grid Search parameters (epochs, batch size and optimizer)
optimizers = ['rmsprop', 'adam']
init = ['glorot_uniform', 'normal', 'uniform']
epochs = [10, 20, 30]
batches = [5, 10, 20]
param_grid = dict(optimizer=optimizers, epochs=epochs, batch_size=batches,
                  init=init)
grid = GridSearchCV(estimator=model, param_grid=param_grid)
grid_result = grid.fit(X, Y)

# summarize results
print("Best parameter set: {}".format(grid_result.best_params_))

メタプログラミング in python

PythonでもRubyみたいなメタプログラミング(method_missing, sendとか)が色々出来るみたい。 ちょっとずつ調べて書いていく。

モンキーパッチ(オープンクラスとは違う)

  • 動的にメソッド定義できる(なんと!!)。オープンクラスというよりはクラスのattrに直接代入という感じ。
  • でも、組み込み型にメソッド追加はできないし、Rubyのクラスを再オープンというものではないみたい。
  • 注意点として、追加するメソッドの第一引数にselfがあることを忘れないこと。
  • ウェブを見ると、パッチを当てたことがわかるように、元のメソッドに戻せるようにしておいて、withと一緒に使って影響を局所化するやり方も紹介されている。
# Monckeyクラスに後からメソッドfを定義する
class Monckey():
    pass

def f(self):
    print("I'm a monckey !")

mon = Monckey()
Monckey.f = f