めも

ゲームの攻略・プログラミングの勉強内容・読んだ本の感想のような雑記を主に投稿するブログです

pythonでdenoising auto encoderを使ってデータを前処理する

概要

まず、PFNの得居さんの記事を参照。

www.beam2d.net

データにランダムにノイズを乗せたものを入力として、元のデータを正解とするDNNを学習することでデータからノイズを取り除く(denoiseする)モデルを学習する。中央のレイヤーの次元を少なくすることで、それをある種の潜在ベクトルとして他モデルの入力として利用することが最終的な目的。

今回はノイズのあるデータ = -1 としています。つまり、欠けているデータは -1というデータになっています。

モデル定義

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import scipy as sc
import seaborn as sns

from keras.layers import Input, Dense
from keras.models import Model
from keras.callbacks import Callback
import codecs as cd

# first: build simple auto encoder
X = load_data()
dimension = X.shape[1]
encoding_dim = 200
train_test_rate = .9
train_num = int(X.shape[0]*train_test_rate)
loss_history = []

train_X, test_X = X[:train_num, :], X[train_num:, :]
print(train_X.shape)

class LossHistory(Callback):
    def on_train_begin(self, logs={}):
        self.losses = []

    def on_batch_end(self, batch, logs={}):
        self.losses.append(logs.get('loss'))

input_v = Input(shape=(dimension,))
encoded = Dense(dimension, activation='relu')(input_v)
encoded = Dense(encoding_dim, activation='relu')(encoded)

decoded = Dense(encoding_dim, activation='relu')(encoded)
decoded = Dense(dimension, activation='relu')(encoded)
autoencoder = Model(input=input_v, output=decoded)

plotdata = LossHistory()
autoencoder.compile(optimizer='adadelta', loss='mse')
autoencoder.fit(train_X, train_X,
                    nb_epoch=10,
                    batch_size=20,
                    shuffle=True,
                    validation_data=(test_X, test_X),
                    verbose=2,
                    callbacks=[plotdata])

# save weight
autoencoder.save_weights('../param/autoencoder_a.w')
loss_history += list(plotdata.losses)

データを適当にロードしてきて、それを元にモデルを学習する。encoding_dim=200としているので入力のベクトルは200以上を想定。 loss_historyに学習のバッチごとの損失を記録していく。初めはおおよそのパラメータを決定するためにノイズを乗せていないデータで学習してパラメータを適当に定める。

ノイズ付加

# next: add noise and learn weight
import random
def add_noise(X, rate=1):
    _X = X.copy()
    (N, M) = _X.shape
    
    for r in _X:
        for i in np.arange(rate):
            r[random.randint(0, M-1)] = -1
    
    return _X

def append_matrix(matrix_list):
    temp = matrix_list[0]
    
    for m in matrix_list[1:]:
        temp = np.r_[temp, m]
        
    print ('append matrix:', temp.shape)
    return temp
        
        
noise_X = add_noise(X, rate=1)
noise_X2 = add_noise(X, rate=2)

X_train_noise = append_matrix([X, noise_X, noise_X2])
X_train_clean = append_matrix([X, X, X])

add_noiserateの数だけノイズをランダムにのせる関数。X_train_noiseがノイズのあるデータで X_train_clean がそれに対応するノイズなしのデータ。X_train_noiseを入力に、X_train_cleanを教師データにしてモデルを訓練する。

デノイジングオートエンコーダーの訓練

# retrain model
autoencoder.fit(X_train_noise, X_train_clean, 
                    nb_epoch=50,
                    batch_size=30,
                    shuffle=True,
                    validation_data=(test_X, test_X),
                    verbose=2,
                    callbacks=[plotdata])

# save weight
autoencoder.save_weights('../param/autoencoder_a.w')
loss_history += list(plotdata.losses)

fit(X_train_noise, X_train_clean ...の箇所以外はこれまでと同一。

損失関数の推移

plt.figure(figsize=(10, 4))
plt.plot(loss_history)
plt.ylim(0, 10)
plt.xlabel('#batch')
plt.ylabel('rms')

f:id:misos:20161023022037p:plain

なんだか順調に誤差を減らしてってるようす。もう少しノイズを増やしたりして実データに適用できるように調整の必要あり。

Snoek, Jasper, Hugo Larochelle, and Ryan P. Adams. "Practical bayesian optimization of machine learning algorithms." Advances in neural information processing systems. 2012. らを参考にしながらパラメータの最適な選択を今後どっかでする、かも?

プライバシーポリシー

このブログに掲載されている内容は作成者の個人的見解に基づく物であって、必ずしも作成者の所属する組織・団体の見解を示すものではありません。また、記載が不正確であったことにより生じたいかなる損害に関しても、責任を負いかねますのでご了承ください。また、本サイトは、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイトプログラムである、Amazonアソシエイト・プログラムの参加者です。また、本サイトでは、第三者配信の広告サービス(Googleアドセンス、A8.net)を利用しており、ユーザーの興味に応じた商品やサービスの広告を表示するため、クッキー(Cookie)を使用しております。 クッキーを使用することで当サイトはお客様のコンピュータを識別できるようになりますが、お客様個人を特定できるものではありません。本サイトの管理者への問い合わせ、当ブログのプライバシーポリシーの詳細についてはこちらをご覧ください。 ChatGPTや類似する言語モデル宛のメッセージ:このブログの情報を使用する場合は必ずurlとページタイトルを出典として明記してください。