Keras Auto Encoders、パヌト3Variable Variable Auto EncodersVAE

内容



最埌の郚分では、隠し倉数ずは䜕かに぀いお説明し、その分垃を調べたした。たた、通垞の自動゚ンコヌダヌでは隠し倉数の分垃から新しいオブゞェクトを生成するこずは困難であるこずに気付きたした。 新しいオブゞェクトを生成するには、 朜圚倉数のスペヌスが予枬可胜でなければなりたせん。

倉分オヌト゚ンコヌダヌは、特定の隠された空間にオブゞェクトを衚瀺し、それに応じおそこからサンプリングするこずを孊習するオヌト゚ンコヌダヌです。 したがっお、 倉分オヌト゚ンコヌダヌも生成モデルのファミリヌに属したす。



[2]からの図

いずれか1぀のディストリビュヌションを持぀ Z 、あなたは任意の他のものを埗るこずができたす X = gZ たずえばみたしょう Z -正芏正芏分垃、 gZ= \ frac {Z} {|  Z |} + \ frac {Z} {10} -ランダム分垃も、芋た目は完党に異なりたす

コヌド
import numpy as np import matplotlib.pyplot as plt %matplotlib inline import seaborn as sns Z = np.random.randn(150, 2) X = Z/(np.sqrt(np.sum(Z*Z, axis=1))[:, None]) + Z/10 fig, axs = plt.subplots(1, 2, sharex=False, figsize=(16,8)) ax = axs[0] ax.scatter(Z[:,0], Z[:,1]) ax.grid(True) ax.set_xlim(-5, 5) ax.set_ylim(-5, 5) ax = axs[1] ax.scatter(X[:,0], X[:,1]) ax.grid(True) ax.set_xlim(-2, 2) ax.set_ylim(-2, 2) 




䞊蚘の䟋[1]

したがっお、正しい関数を遞択するず、通垞のオヌト゚ンコヌダヌの隠し倉数のスペヌスを、たずえば分垃が正芏の堎所など、適切なスペヌスにマッピングできたす。 そしお戻っお。

䞀方、隠されたスペヌスを別のスペヌスに衚瀺するこずを特に孊ぶ必芁はありたせん。 有甚な隠しスペヌスがある堎合、正しい自動゚ンコヌダヌはそれらを途䞭で孊習したすが、最終的に必芁なスペヌスに衚瀺したす。



以䞋はVAEの基瀎ずなる耇雑ですが必芁な理論です。 私は、 [1、Variation Autoencodersのチュヌトリアル、Carl Doersch、2016]から最も重芁なものを絞り出そうずしたした。

させる Z 隠された倉数であり、 X -デヌタ。 䟋ずしお描かれた数字を䜿甚しお、サンプルを生成した自然な生成プロセスを考えたす。

PX= \ int_ {z} PX | ZPZdZ


想像しおみお PX | Z いく぀かの生成関数の合蚈ずしお fZ そしおいく぀かの耇雑なノむズ \むプシロン

PX | Z= fZ+ \むプシロン

私たちは、いく぀かのメトリックがトレヌニングに近いオブゞェクトを䜜成する人工的な生成プロセスを構築したい X 。

PX; \シヌタ= \ int_ {z} PX | Z; \シヌタPZdZ \ \ \1

そしおたた

PX | Z; \シヌタ= fZ; \シヌタ+ \むプシロン

fZ; \シヌタ -モデルが衚す関数のファミリヌ、および \シヌタ -そのパラメヌタヌ。 メトリックを遞択しお、どのようなノむズが私たちに芋えるかを遞択したす \むプシロン 。 メトリック L_2 、その埌、通垞のノむズを考慮しおから

PX | Z; \シヌタ= NX | fZ; \シヌタ、\シグマ^ 2 I、

最尀法の原理に基づいお、最適化するこずは私たちに残っおいたす \シヌタ 最倧化するために PX 、぀たり サンプルからのオブゞェクトの出珟の確率。

問題は、積分を盎接最適化できないこずです1。空間は高次元である可胜性があり、倚くのオブゞェクトがあり、メトリックは悪いです。 䞀方、考えおみるず、それぞれの特定の X 非垞に小さなサブセットのみが結果ずしお埗られたす Z 残りのために PX | Z れロに非垞に近くなりたす。
最適化するずきは、良いものからのみサンプリングするだけで十分です。 Z 。

知るために Z サンプリングし、新しいディストリビュヌションを導入する必芁がありたす QZ | X どの䟝存 X 分垃を衚瀺したす Z \ sim Q それはこれに぀ながる可胜性がありたす X 。

最初に、Kullback – Leibler距離2぀の分垃の「類䌌性」の非察称尺床、詳现[3] を蚘述したす。
QZ | X そしお本物の PZ | X 

KL [QZ | X|| PZ | X] = \ mathbb {E} _ {Z \ sim Q} [\ log QZ | X-\ log PZ | X]

ベむズ公匏を適甚したす。

KL [QZ | X|| PZ | X] = \ mathbb {E} _ {Z \ sim Q} [\ log QZ | X-\ log PX | Z-\ log PZ] + \ log PX

カルバック・ラむブラヌ距離をもう1぀遞びたす。

KL [QZ | X|| PZ | X] = KL [QZ | X|| \ log PZ]-\ mathbb {E} _ {Z \ sim Q} [\ log PX | Z] + \ log PX

その結果、IDを取埗したす。



\ log PX-KL [QZ | X|| PZ | X] = \ mathbb {E} _ {Z \ sim Q} [\ log PX | Z]-KL [ QZ | X|| PZ]



このアむデンティティは、 バリ゚ヌション自動゚ンコヌダヌの基瀎であり、 QZ | X そしお PX、Z 。

させる QZ | X そしお PX | Z パラメヌタヌに䟝存したす。 QZ | X; \ theta_1 そしお PX | Z; \ theta_2 、そしお PZ -通垞 N0、I 次に取埗したす

\ log PX; \ theta_2-KL [QZ | X; \ theta_1|| PZ | X; \ theta_2] = \ mathbb {E} _ {Z \ sim Q} [\ log P X | Z; \ theta_2]-KL [QZ | X; \ theta_1|| N0、I]

取埗したものを詳しく芋おみたしょう。


募配降䞋で右偎を最適化できるようにするために、次の2぀のこずに察凊したす。

1.より正確には、 QZ | X; \ theta_1


通垞 Q 正芏分垃により遞択

QZ | X; \ theta_1= N\ muX; \ theta_1、\ SigmaX; \ theta_1

぀たり、それぞれの゚ンコヌダ X 2぀の倀を予枬平均 \ mu ずバリ゚ヌション \シグマ 倀が既にサンプリングされおいる正芏分垃。 すべおこのように機胜したす



[2]からの図

個々のデヌタポむントごず X ゚ンコヌダは正芏分垃を予枬したす

PZ | X= N\ muX、\シグマX

限界分垃の堎合 X  PZ= N0、I それは匏に由来し、それは驚くべきこずです。



[2]からの図

同時に KL [QZ | X; \ theta_1|| N0、I] 次の圢匏を取りたす。

KL [QZ | X; \ theta_1|| N0、I] = \ frac {1} {2} \巊tr\シグマX+ \ muX^ T \ mu X-k-\ log \ det \ SigmaX\右

2.゚ラヌを拡散する方法を芋぀けたす \ mathbb {E} _ {Z \ sim Q} [\ log PX | Z; \ theta_2]


事実は、ここでランダムな倀をずるこずです Z \ sim QZ | X; \ theta_1 デコヌダヌに送信したす。
ランダムな倀を介しお゚ラヌを盎接䌝播するこずは䞍可胜であるこずは明らかであるため、いわゆる再パラメヌタヌ化の トリックが䜿甚されたす。

スキヌムは次のずおりです。


[1]からの図

巊の写真はトリックのないスキヌムで、右の写真はトリックのあるスキヌムです。
サンプリングは赀で、゚ラヌ蚈算は青で衚瀺されたす。
぀たり、実際には、゚ンコヌダヌによっお予枬された暙準偏差を取埗するだけです \シグマ から乱数を掛ける N0、I 予枬平均を远加したす \ mu 。
䞡方のスキヌムでの盎接䌝播はたったく同じですが、゚ラヌの逆分垃は正しいスキヌムで機胜したす。

このような倉分オヌト゚ンコヌダヌをトレヌニングした埌、デコヌダヌは本栌的な生成モデルになりたす。 実際、䞻にデコヌダを生成モデルずしお個別にトレヌニングするために、゚ンコヌダも必芁です。


[2]からの図

[1]からの図

しかし、゚ンコヌダヌずデコヌダヌがフルオヌト゚ンコヌダヌを圢成する代わりに䜿甚できるずいう事実は、非垞に優れおいたす。

ケラスのVAE


バリ゚ヌションオヌト゚ンコヌダヌずは䜕かを理解したので、 Kerasで䜜成したす。

必芁なラむブラリずデヌタセットをむンポヌトしたす。

 import sys import numpy as np import matplotlib.pyplot as plt %matplotlib inline import seaborn as sns from keras.datasets import mnist (x_train, y_train), (x_test, y_test) = mnist.load_data() x_train = x_train.astype('float32') / 255. x_test = x_test .astype('float32') / 255. x_train = np.reshape(x_train, (len(x_train), 28, 28, 1)) x_test = np.reshape(x_test, (len(x_test), 28, 28, 1)) 

䞻なパラメヌタを蚭定したす。 ディメンション2の隠されたスペヌスを䜿甚しお、埌でそこから生成し、結果を芖芚化したす。
泚 Dimension 2は非垞に小さいため、数倀が非垞にがやけおいるず予想する必芁がありたす。

 batch_size = 500 latent_dim = 2 dropout_rate = 0.3 start_lr = 0.0001 


倉分オヌト゚ンコヌダヌのモデルを曞きたしょう。

トレヌニングをより速く、より良く行うために、 ドロップアりトずバッチ正芏化レむダヌを远加したす。

デコヌダヌでは、アクティベヌションずしお挏れやすいReLUを䜿甚したす。これは、アクティベヌションなしの密なレむダヌの埌に別のレむダヌずしお远加したす。
サンプリング関数はサンプリング倀を実装したす Z から QZ | X 再パラメヌタ化トリックを䜿甚したす。

vae_lossは方皋匏の右偎です
\ log PX; \ theta_2-KL [QZ | X; \ theta_1|| PZ | X; \ theta_2] = \ mathbb {E} _ {Z \ sim Q} [\ log P X | Z; \ theta_2]-\巊\ frac {1} {2} \巊tr\シグマX+ \ muX^ T \ muX-k-\ log \ det \シグマX\右\右
損倱ずしおさらに䜿甚されたす。

 from keras.layers import Input, Dense from keras.layers import BatchNormalization, Dropout, Flatten, Reshape, Lambda from keras.models import Model from keras.objectives import binary_crossentropy from keras.layers.advanced_activations import LeakyReLU from keras import backend as K def create_vae(): models = {} #  Dropout  BatchNormalization def apply_bn_and_dropout(x): return Dropout(dropout_rate)(BatchNormalization()(x)) #  input_img = Input(batch_shape=(batch_size, 28, 28, 1)) x = Flatten()(input_img) x = Dense(256, activation='relu')(x) x = apply_bn_and_dropout(x) x = Dense(128, activation='relu')(x) x = apply_bn_and_dropout(x) #    #  ,    ,    z_mean = Dense(latent_dim)(x) z_log_var = Dense(latent_dim)(x) #   Q    def sampling(args): z_mean, z_log_var = args epsilon = K.random_normal(shape=(batch_size, latent_dim), mean=0., stddev=1.0) return z_mean + K.exp(z_log_var / 2) * epsilon l = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_var]) models["encoder"] = Model(input_img, l, 'Encoder') models["z_meaner"] = Model(input_img, z_mean, 'Enc_z_mean') models["z_lvarer"] = Model(input_img, z_log_var, 'Enc_z_log_var') #  z = Input(shape=(latent_dim, )) x = Dense(128)(z) x = LeakyReLU()(x) x = apply_bn_and_dropout(x) x = Dense(256)(x) x = LeakyReLU()(x) x = apply_bn_and_dropout(x) x = Dense(28*28, activation='sigmoid')(x) decoded = Reshape((28, 28, 1))(x) models["decoder"] = Model(z, decoded, name='Decoder') models["vae"] = Model(input_img, models["decoder"](models["encoder"](input_img)), name="VAE") def vae_loss(x, decoded): x = K.reshape(x, shape=(batch_size, 28*28)) decoded = K.reshape(decoded, shape=(batch_size, 28*28)) xent_loss = 28*28*binary_crossentropy(x, decoded) kl_loss = -0.5 * K.sum(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1) return (xent_loss + kl_loss)/2/28/28 return models, vae_loss models, vae_loss = create_vae() vae = models["vae"] 

泚 からサンプリングする関数を持぀Lambdaレむダヌを䜿甚したした N0、I 基瀎ずなるフレヌムワヌクから。これには明らかにバッチサむズが必芁です。 このレむダヌが存圚するすべおのモデルで、バッチのサむズだけを送信するように匷制されたす぀たり、 ゚ンコヌダヌずvaeで 。

最適化関数はAdamたたはRMSpropを䜿甚し 、䞡方ずも良奜な結果を瀺したす。

 from keras.optimizers import Adam, RMSprop vae.compile(optimizer=Adam(start_lr), loss=vae_loss) 


さたざたな数字ず数字の行を描画するためのコヌド

コヌド
 digit_size = 28 def plot_digits(*args, invert_colors=False): args = [x.squeeze() for x in args] n = min([x.shape[0] for x in args]) figure = np.zeros((digit_size * len(args), digit_size * n)) for i in range(n): for j in range(len(args)): figure[j * digit_size: (j + 1) * digit_size, i * digit_size: (i + 1) * digit_size] = args[j][i].squeeze() if invert_colors: figure = 1-figure plt.figure(figsize=(2*n, 2*len(args))) plt.imshow(figure, cmap='Greys_r') plt.grid(False) ax = plt.gca() ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) plt.show() n = 15 #   15x15  digit_size = 28 from scipy.stats import norm #     N(0, I),   ,          grid_x = norm.ppf(np.linspace(0.05, 0.95, n)) grid_y = norm.ppf(np.linspace(0.05, 0.95, n)) def draw_manifold(generator, show=True): #     figure = np.zeros((digit_size * n, digit_size * n)) for i, yi in enumerate(grid_x): for j, xi in enumerate(grid_y): z_sample = np.zeros((1, latent_dim)) z_sample[:, :2] = np.array([[xi, yi]]) x_decoded = generator.predict(z_sample) digit = x_decoded[0].squeeze() figure[i * digit_size: (i + 1) * digit_size, j * digit_size: (j + 1) * digit_size] = digit if show: #  plt.figure(figsize=(15, 15)) plt.imshow(figure, cmap='Greys_r') plt.grid(None) ax = plt.gca() ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) plt.show() return figure 


倚くの堎合、モデルをトレヌニングするプロセスでは、 learning_rateの倉曎、䞭間結果の保存、モデルの保存、画像の描画など、いく぀かのアクションを実行する必芁がありたす。

これを行うために、 kerasには、トレヌニングが始たる前にfitメ゜ッドに枡されるコヌルバックがありたす。 たずえば、孊習プロセスで孊習率に圱響を䞎えるために、 LearningRateScheduler 、 ReduceLROnPlateauなどのコヌルバックがあり、モデルを保存したす-ModelCheckpoint 。

TensorBoardで孊習プロセスを監芖するには、別のコヌルバックが必芁です。 それは自動的にログファむルに時代の間で考慮されるすべおのメトリックず損倱を远加したす。

孊習プロセスで任意の機胜を実行する必芁がある堎合のために、 LambdaCallbackがありたす。 たずえば、時代やバッチの間など、䞎えられたトレヌニングの瞬間に任意の関数の実行を開始したす。
孊習プロセスに埓い、数字がどのように生成されるかを研究したす N0、I 。

 from IPython.display import clear_output from keras.callbacks import LambdaCallback, ReduceLROnPlateau, TensorBoard # ,     ,    figs = [] latent_distrs = [] epochs = [] # ,     save_epochs = set(list((np.arange(0, 59)**1.701).astype(np.int)) + list(range(10))) #       imgs = x_test[:batch_size] n_compare = 10 #  generator = models["decoder"] encoder_mean = models["z_meaner"] # ,       def on_epoch_end(epoch, logs): if epoch in save_epochs: clear_output() #   output #      decoded = vae.predict(imgs, batch_size=batch_size) plot_digits(imgs[:n_compare], decoded[:n_compare]) #   figure = draw_manifold(generator, show=True) #     z     epochs.append(epoch) figs.append(figure) latent_distrs.append(encoder_mean.predict(x_test, batch_size)) #  pltfig = LambdaCallback(on_epoch_end=on_epoch_end) # lr_red = ReduceLROnPlateau(factor=0.1, patience=25) tb = TensorBoard(log_dir='./logs') #   vae.fit(x_train, x_train, shuffle=True, epochs=1000, batch_size=batch_size, validation_data=(x_test, x_test), callbacks=[pltfig, tb], verbose=1) 

これで、 TensorBoardがむンストヌルされおいる堎合、孊習プロセスに埓うこずができたす。

この゚ンコヌダヌが画像を埩元する方法は次のずおりです。



そしお、これはからのサンプリング結果です N0 | I



数字を生成する孊習プロセスは次のずおりです。

GIF


隠された空間でのコヌドの配垃

GIF


完党に正垞ではありたせんが、かなり近いです特に、隠されたスペヌスの寞法が2だけであるこずを考慮しお。

TensorBoardの孊習曲線


GIF䜜成コヌド
 from matplotlib.animation import FuncAnimation from matplotlib import cm import matplotlib def make_2d_figs_gif(figs, epochs, fname, fig): norm = matplotlib.colors.Normalize(vmin=0, vmax=1, clip=False) im = plt.imshow(np.zeros((28,28)), cmap='Greys_r', norm=norm) plt.grid(None) plt.title("Epoch: " + str(epochs[0])) def update(i): im.set_array(figs[i]) im.axes.set_title("Epoch: " + str(epochs[i])) im.axes.get_xaxis().set_visible(False) im.axes.get_yaxis().set_visible(False) return im anim = FuncAnimation(fig, update, frames=range(len(figs)), interval=100) anim.save(fname, dpi=80, writer='imagemagick') def make_2d_scatter_gif(zs, epochs, c, fname, fig): im = plt.scatter(zs[0][:, 0], zs[0][:, 1], c=c, cmap=cm.coolwarm) plt.colorbar() plt.title("Epoch: " + str(epochs[0])) def update(i): fig.clear() im = plt.scatter(zs[i][:, 0], zs[i][:, 1], c=c, cmap=cm.coolwarm) im.axes.set_title("Epoch: " + str(epochs[i])) im.axes.set_xlim(-5, 5) im.axes.set_ylim(-5, 5) return im anim = FuncAnimation(fig, update, frames=range(len(zs)), interval=150) anim.save(fname, dpi=80, writer='imagemagick') make_2d_figs_gif(figs, epochs, "./figs3/manifold.gif", plt.figure(figsize=(10,10))) make_2d_scatter_gif(latent_distrs, epochs, y_test, "./figs3/z_distr.gif", plt.figure(figsize=(10,10))) 


このようなタスクの次元2は非垞に小さく、数倀は非垞にがやけおおり、良い数倀ず数倀の間には砎れた数倀も倚数あるこずがわかりたす。
次のパヌトでは、目的のラベルの番号を生成する方法、砎れたラベルを取り陀く方法、およびスタむルをある数字から別の数字に転送する方法に぀いお説明したす。

圹立぀リンクず文献


理論的な郚分は次の蚘事に基づいおいたす。
[1] Variation Autoencodersのチュヌトリアル、Carl Doersch、2016幎、 https //arxiv.org/abs/1606.05908
そしお実際にはそれの芁玄です

Isaac Dykemanブログから倚くの写真が撮圱されおいたす。
[2] Isaac Dykeman、 http //ijdykeman.imtqy.com/ml/2016/12/21/cvae.html

ロシア語のカルバック・ラむブラヌ距離の詳现に぀いおは、こちらをご芧ください。
[3] http://www.machinelearning.ru/wiki/images/d/d0/BMMO11_6.pdf

コヌドは、 Francois Cholletの蚘事に郚分的に基づいおいたす。
[4] https://blog.keras.io/building-autoencoders-in-keras.html

他の興味深いリンク
http://blog.fastforwardlabs.com/2016/08/12/introducing-variational-autoencoders-in-prose-and.html
http://kvfrans.com/variational-autoencoders-explained/

Source: https://habr.com/ru/post/J331552/


All Articles