Files
hands-on/15_autoencoders.ipynb
2018-05-24 12:16:03 +09:00

2353 lines
342 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPython 3.6.5\n",
"IPython 6.4.0\n",
"\n",
"numpy 1.14.3\n",
"sklearn 0.19.1\n",
"scipy 1.1.0\n",
"matplotlib 2.2.2\n",
"tensorflow 1.8.0\n"
]
}
],
"source": [
"%load_ext watermark\n",
"%watermark -v -p numpy,sklearn,scipy,matplotlib,tensorflow"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**15장 오토인코더**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"_이 노트북은 15장에 있는 모든 샘플 코드와 연습문제 해답을 가지고 있습니다._"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 설정"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"파이썬 2와 3을 모두 지원합니다. 공통 모듈을 임포트하고 맷플롯립 그림이 노트북 안에 포함되도록 설정하고 생성한 그림을 저장하기 위한 함수를 준비합니다:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# 파이썬 2와 파이썬 3 지원\n",
"from __future__ import division, print_function, unicode_literals\n",
"\n",
"# 공통\n",
"import numpy as np\n",
"import os\n",
"import sys\n",
"\n",
"# 일관된 출력을 위해 유사난수 초기화\n",
"def reset_graph(seed=42):\n",
" tf.reset_default_graph()\n",
" tf.set_random_seed(seed)\n",
" np.random.seed(seed)\n",
"\n",
"# 맷플롯립 설정\n",
"%matplotlib inline\n",
"import matplotlib\n",
"import matplotlib.pyplot as plt\n",
"plt.rcParams['axes.labelsize'] = 14\n",
"plt.rcParams['xtick.labelsize'] = 12\n",
"plt.rcParams['ytick.labelsize'] = 12\n",
"\n",
"# 한글출력\n",
"plt.rcParams['font.family'] = 'NanumBarunGothic'\n",
"plt.rcParams['axes.unicode_minus'] = False\n",
"\n",
"# 그림을 저장할 폴더\n",
"PROJECT_ROOT_DIR = \".\"\n",
"CHAPTER_ID = \"autoencoders\"\n",
"\n",
"def save_fig(fig_id, tight_layout=True):\n",
" path = os.path.join(PROJECT_ROOT_DIR, \"images\", CHAPTER_ID, fig_id + \".png\")\n",
" if tight_layout:\n",
" plt.tight_layout()\n",
" plt.savefig(path, format='png', dpi=300)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"28x28 흑백 이미지를 그리기 위한 유틸리티 함수:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def plot_image(image, shape=[28, 28]):\n",
" plt.imshow(image.reshape(shape), cmap=\"Greys\", interpolation=\"nearest\")\n",
" plt.axis(\"off\")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"def plot_multiple_images(images, n_rows, n_cols, pad=2):\n",
" images = images - images.min() # 최소값을 0으로 만들어 패딩이 하얗게 보이도록 합니다.\n",
" w,h = images.shape[1:]\n",
" image = np.zeros(((w+pad)*n_rows+pad, (h+pad)*n_cols+pad))\n",
" for y in range(n_rows):\n",
" for x in range(n_cols):\n",
" image[(y*(h+pad)+pad):(y*(h+pad)+pad+h),(x*(w+pad)+pad):(x*(w+pad)+pad+w)] = images[y*n_cols+x]\n",
" plt.imshow(image, cmap=\"Greys\", interpolation=\"nearest\")\n",
" plt.axis(\"off\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 선형 오토인코더를 사용한 PCA"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"3D 데이터셋을 만듭니다:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"import numpy.random as rnd\n",
"\n",
"rnd.seed(4)\n",
"m = 200\n",
"w1, w2 = 0.1, 0.3\n",
"noise = 0.1\n",
"\n",
"angles = rnd.rand(m) * 3 * np.pi / 2 - 0.5\n",
"data = np.empty((m, 3))\n",
"data[:, 0] = np.cos(angles) + np.sin(angles)/2 + noise * rnd.randn(m) / 2\n",
"data[:, 1] = np.sin(angles) * 0.7 + noise * rnd.randn(m) / 2\n",
"data[:, 2] = data[:, 0] * w1 + data[:, 1] * w2 + noise * rnd.randn(m)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"데이터를 정규화합니다:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.preprocessing import StandardScaler\n",
"scaler = StandardScaler()\n",
"X_train = scaler.fit_transform(data[:100])\n",
"X_test = scaler.transform(data[100:])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"오토인코더를 만듭니다:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"import tensorflow as tf\n",
"\n",
"reset_graph()\n",
"\n",
"n_inputs = 3\n",
"n_hidden = 2 # 코딩 유닛\n",
"n_outputs = n_inputs\n",
"\n",
"learning_rate = 0.01\n",
"\n",
"X = tf.placeholder(tf.float32, shape=[None, n_inputs])\n",
"hidden = tf.layers.dense(X, n_hidden)\n",
"outputs = tf.layers.dense(hidden, n_outputs)\n",
"\n",
"reconstruction_loss = tf.reduce_mean(tf.square(outputs - X))\n",
"\n",
"optimizer = tf.train.AdamOptimizer(learning_rate)\n",
"training_op = optimizer.minimize(reconstruction_loss)\n",
"\n",
"init = tf.global_variables_initializer()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"n_iterations = 1000\n",
"codings = hidden\n",
"\n",
"with tf.Session() as sess:\n",
" init.run()\n",
" for iteration in range(n_iterations):\n",
" training_op.run(feed_dict={X: X_train})\n",
" codings_val = codings.eval(feed_dict={X: X_test})"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 288x216 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig = plt.figure(figsize=(4,3))\n",
"plt.plot(codings_val[:,0], codings_val[:, 1], \"b.\")\n",
"plt.xlabel(\"$z_1$\", fontsize=18)\n",
"plt.ylabel(\"$z_2$\", fontsize=18, rotation=0)\n",
"save_fig(\"linear_autoencoder_pca_plot\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 적층 오토인코더"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"MNIST 데이터셋을 사용합니다:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"주의: `tf.examples.tutorials.mnist`은 삭제될 예정이므로 대신 `tf.keras.datasets.mnist`를 사용하겠습니다."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"(X_train, y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data()\n",
"X_train = X_train.astype(np.float32).reshape(-1, 28*28) / 255.0\n",
"X_test = X_test.astype(np.float32).reshape(-1, 28*28) / 255.0\n",
"y_train = y_train.astype(np.int32)\n",
"y_test = y_test.astype(np.int32)\n",
"X_valid, X_train = X_train[:5000], X_train[5000:]\n",
"y_valid, y_train = y_train[:5000], y_train[5000:]"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"def shuffle_batch(X, y, batch_size):\n",
" rnd_idx = np.random.permutation(len(X))\n",
" n_batches = len(X) // batch_size\n",
" for batch_idx in np.array_split(rnd_idx, n_batches):\n",
" X_batch, y_batch = X[batch_idx], y[batch_idx]\n",
" yield X_batch, y_batch"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"# from tensorflow.examples.tutorials.mnist import input_data\n",
"# mnist = input_data.read_data_sets(\"/tmp/data/\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 한 번에 모든 층을 훈련하기"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"3개의 은닉층과 1개의 출력층(즉, 두 개를 적층)을 가진 적층 오토인코더를 만들어 보겠습니다. ELU 활성화 함수와 He 초기화, L2 정규화를 사용하겠습니다."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"reset_graph()\n",
"\n",
"from functools import partial\n",
"\n",
"n_inputs = 28 * 28\n",
"n_hidden1 = 300\n",
"n_hidden2 = 150 # 코딩 유닛\n",
"n_hidden3 = n_hidden1\n",
"n_outputs = n_inputs\n",
"\n",
"learning_rate = 0.01\n",
"l2_reg = 0.0001\n",
"\n",
"X = tf.placeholder(tf.float32, shape=[None, n_inputs])\n",
"\n",
"he_init = tf.variance_scaling_initializer() # He 초기화\n",
"#아래와 동일합니다:\n",
"#he_init = lambda shape, dtype=tf.float32: tf.truncated_normal(shape, 0., stddev=np.sqrt(2/shape[0]))\n",
"l2_regularizer = tf.contrib.layers.l2_regularizer(l2_reg)\n",
"my_dense_layer = partial(tf.layers.dense,\n",
" activation=tf.nn.elu,\n",
" kernel_initializer=he_init,\n",
" kernel_regularizer=l2_regularizer)\n",
"\n",
"hidden1 = my_dense_layer(X, n_hidden1)\n",
"hidden2 = my_dense_layer(hidden1, n_hidden2)\n",
"hidden3 = my_dense_layer(hidden2, n_hidden3)\n",
"outputs = my_dense_layer(hidden3, n_outputs, activation=None)\n",
"\n",
"reconstruction_loss = tf.reduce_mean(tf.square(outputs - X))\n",
"\n",
"reg_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)\n",
"loss = tf.add_n([reconstruction_loss] + reg_losses)\n",
"\n",
"optimizer = tf.train.AdamOptimizer(learning_rate)\n",
"training_op = optimizer.minimize(loss)\n",
"\n",
"init = tf.global_variables_initializer()\n",
"saver = tf.train.Saver() # 책에는 없음"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"이제 훈련시켜 보죠! 여기에서는 타깃 값을 주입하지 않습니다(`y_batch`가 사용되지 않습니다). 이는 비지도 학습입니다."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 훈련 MSE: 0.024246655\n",
"1 훈련 MSE: 0.015581552\n",
"2 훈련 MSE: 0.014903595\n",
"3 훈련 MSE: 0.014060436\n",
"4 훈련 MSE: 0.013958205\n"
]
}
],
"source": [
"n_epochs = 5\n",
"batch_size = 150\n",
"\n",
"with tf.Session() as sess:\n",
" init.run()\n",
" for epoch in range(n_epochs):\n",
" n_batches = len(X_train) // batch_size\n",
" for iteration in range(n_batches):\n",
" print(\"\\r{}%\".format(100 * iteration // n_batches), end=\"\") # 책에는 없음\n",
" sys.stdout.flush() # 책에는 없음\n",
" X_batch, y_batch = next(shuffle_batch(X_train, y_train, batch_size))\n",
" sess.run(training_op, feed_dict={X: X_batch})\n",
" loss_train = reconstruction_loss.eval(feed_dict={X: X_batch}) # 책에는 없음\n",
" print(\"\\r{}\".format(epoch), \"훈련 MSE:\", loss_train) # 책에는 없음\n",
" saver.save(sess, \"./my_model_all_layers.ckpt\") # 책에는 없음"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"이 함수는 모델을 로드하고 테스트 세트에서 이를 평가합니다(재구성 오차를 측정합니다). 그런 다음 원본 이미지와 재구성 이미지를 그립니다:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"def show_reconstructed_digits(X, outputs, model_path = None, n_test_digits = 2):\n",
" with tf.Session() as sess:\n",
" if model_path:\n",
" saver.restore(sess, model_path)\n",
"# X_test = mnist.test.images[:n_test_digits]\n",
" outputs_val = outputs.eval(feed_dict={X: X_test[:n_test_digits]})\n",
"\n",
" fig = plt.figure(figsize=(8, 3 * n_test_digits))\n",
" for digit_index in range(n_test_digits):\n",
" plt.subplot(n_test_digits, 2, digit_index * 2 + 1)\n",
" plot_image(X_test[digit_index])\n",
" plt.subplot(n_test_digits, 2, digit_index * 2 + 2)\n",
" plot_image(outputs_val[digit_index])"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO:tensorflow:Restoring parameters from ./my_model_all_layers.ckpt\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 576x432 with 4 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_reconstructed_digits(X, outputs, \"./my_model_all_layers.ckpt\")\n",
"save_fig(\"reconstruction_plot\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 가중치 묶기"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"인코더와 디코더의 가중치를 묶는 일은 자주 있습니다(`weights_decoder = tf.transpose(weights_encoder)`). 안타깝지만 `tf.layers.dense()` 함수를 사용해서 이렇게 하기는 불가능합니다(또는 매우 어렵습니다). 수동으로 직접 오토인코더를 만들어야 합니다:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"reset_graph()\n",
"\n",
"n_inputs = 28 * 28\n",
"n_hidden1 = 300\n",
"n_hidden2 = 150 # 코딩 유닛\n",
"n_hidden3 = n_hidden1\n",
"n_outputs = n_inputs\n",
"\n",
"learning_rate = 0.01\n",
"l2_reg = 0.0005"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"activation = tf.nn.elu\n",
"regularizer = tf.contrib.layers.l2_regularizer(l2_reg)\n",
"initializer = tf.variance_scaling_initializer()\n",
"\n",
"X = tf.placeholder(tf.float32, shape=[None, n_inputs])\n",
"\n",
"weights1_init = initializer([n_inputs, n_hidden1])\n",
"weights2_init = initializer([n_hidden1, n_hidden2])\n",
"\n",
"weights1 = tf.Variable(weights1_init, dtype=tf.float32, name=\"weights1\")\n",
"weights2 = tf.Variable(weights2_init, dtype=tf.float32, name=\"weights2\")\n",
"weights3 = tf.transpose(weights2, name=\"weights3\") # 가중치 묶기\n",
"weights4 = tf.transpose(weights1, name=\"weights4\") # 가중치 묶기\n",
"\n",
"biases1 = tf.Variable(tf.zeros(n_hidden1), name=\"biases1\")\n",
"biases2 = tf.Variable(tf.zeros(n_hidden2), name=\"biases2\")\n",
"biases3 = tf.Variable(tf.zeros(n_hidden3), name=\"biases3\")\n",
"biases4 = tf.Variable(tf.zeros(n_outputs), name=\"biases4\")\n",
"\n",
"hidden1 = activation(tf.matmul(X, weights1) + biases1)\n",
"hidden2 = activation(tf.matmul(hidden1, weights2) + biases2)\n",
"hidden3 = activation(tf.matmul(hidden2, weights3) + biases3)\n",
"outputs = tf.matmul(hidden3, weights4) + biases4\n",
"\n",
"reconstruction_loss = tf.reduce_mean(tf.square(outputs - X))\n",
"reg_loss = regularizer(weights1) + regularizer(weights2)\n",
"loss = reconstruction_loss + reg_loss\n",
"\n",
"optimizer = tf.train.AdamOptimizer(learning_rate)\n",
"training_op = optimizer.minimize(loss)\n",
"\n",
"init = tf.global_variables_initializer()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"saver = tf.train.Saver()"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 훈련 MSE: 0.021188682\n",
"1 훈련 MSE: 0.018240245\n",
"2 훈련 MSE: 0.020062765\n",
"3 훈련 MSE: 0.020047668\n",
"4 훈련 MSE: 0.019466272\n"
]
}
],
"source": [
"n_epochs = 5\n",
"batch_size = 150\n",
"\n",
"with tf.Session() as sess:\n",
" init.run()\n",
" for epoch in range(n_epochs):\n",
" n_batches = len(X_train) // batch_size\n",
" for iteration in range(n_batches):\n",
" print(\"\\r{}%\".format(100 * iteration // n_batches), end=\"\")\n",
" sys.stdout.flush()\n",
" X_batch, y_batch = next(shuffle_batch(X_train, y_train, batch_size))\n",
" sess.run(training_op, feed_dict={X: X_batch})\n",
" loss_train = reconstruction_loss.eval(feed_dict={X: X_batch})\n",
" print(\"\\r{}\".format(epoch), \"훈련 MSE:\", loss_train)\n",
" saver.save(sess, \"./my_model_tying_weights.ckpt\")"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO:tensorflow:Restoring parameters from ./my_model_tying_weights.ckpt\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAa4AAAFrCAYAAACJ0G2dAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAGnxJREFUeJzt3VuMX1W9B/BV29LSll7pBSi0pYAFsQENclGjOSa8mGjU8IA8aNBEYqKJJGogMVFf9E15MWg0oOiDiYm3RAFvJNxFAkRAtNyKXMYWCr0NvXOeTs45rO+iezrTma7O5/P4y1577/lP//NjZ3/5rRlvvPFGAYBevG2qbwAAxkLjAqArGhcAXdG4AOiKxgVAVzQuALqicQHQFY0LgK5oXAB0ReMCoCuzpuCaZkwx0WZM9Q1MVyMjI77PTKhVq1Yd9vvsiQuArmhcAHRF4wKgK1PxjgvguDBjxrDXq63to972tvrZIR1r+6n/zxMXAF3RuADoisYFQFc0LgC6onEB0BWpQuC40kr6pfqhQ4cGn3do2i9dZ9as/Kc2HTt79uxBx7Wuf/Dgwaq2d+/ewdcfep1Wfeg5x8MTFwBd0bgA6IrGBUBXNC4AuiKcARxXxhIkSA4cOBDrKfQwNEiRRjuVUsrMmTMHHdsKd6TQRbr/sQQmxjJeajKCGIknLgC6onEB0BWNC4CuaFwAdEU4AzimjHdKQyswkMIVaXJGa5rG/v37q9q+ffuq2oknnhjXJ3Pnzq1q6T5bP9OcOXMGXSeds1VPgZNWYGUsn99E8sQFQFc0LgC6onEB0BWNC4CuaFwAdEWqEDimtBJ0402wpVFKQ/ezah2bUn3pOik9WEpO8KX1J5xwQlyfRkalWko/tup79uwZdE+l5N/VZOzR5YkLgK5oXAB0ReMCoCsaFwBdEc4AujA0SJFGM5VSyuuvv17VRkdHq1prjFIKUqQgRApStMIR6fopcDJv3ry4Pl0rBSnGEjgZ7/qhgY3WsUN44gKgKxoXAF3RuADoisYFQFemXTjjvvvuq2o33HBDPPa0006rammvnU996lNx/dKlSwfVYLoay5SFVE/7RG3bti2uf+WVV6raf/7zn6q2c+fOuD5Nv1i+fHlVmzWr/rOarl1KKc8//3xVS0GO+fPnx/WpfuaZZ1a1k046Ka5PoY9Ua+0x1pqo8WYpxFKKcAYA04TGBUBXNC4AuqJxAdAVjQuArsxojeI4iib9gv/X29/+9qq2adOmo3KtRYsWVbVLLrnkqFxroq1duzbWr7vuuqp2xhlnHOW7OayJ3eyHwUZGRgZ/n4cmCFvjhXbt2lXVUlrviSeeiOvT93zoGKhS8v2nVF9KBab0YquekpKtzySl/U499dSqtn79+rj+ne98Z1XbsGFDVVuyZElcn1KFKVXZkn7/q1atOuz32RMXAF3RuADoisYFQFc0LgC6Mu1GPv3qV7+qag8//HA89h3veEdVe+yxx6ra/fffH9f/+te/rmq33XZbVVu3bl1Ve+aZZ+I5h2q9ID3llFOq2r///e/B502hja9+9auD18P/lUIHe/bsicemUUwpnNH697x3796qtmPHjsHXX7BgQVVLo4zSz9QajXT66adXtTRaqnVPL7zwQlV76KGHBq9PI6vOOuusqpb2/SplbHtvTSRPXAB0ReMCoCsaFwBd0bgA6Mq0C2ece+65g2otGzdurGpXXnllPPbb3/52VXv22WerWgpnPP3004PvKWm9TE3hjHT9rVu3xvXp/6qHI5WmTKRpFqXk0EP6d9r6t79ixYqqtnDhwqrW2nsq7WmVJmek+0+Bi1JKWbx4cVWbM2dOVUshjFJK+ctf/lLV0t+YV199Na5PIa5UawUu0rGHDh0avP5IeeICoCsaFwBd0bgA6IrGBUBXNC4AujLtUoWTKSWJhqbyxpJ0HIs0nurll1+uahdffHFcf/nll0/4PTF9pQRgGs1USk7wnXbaaVUtJfVKyfvjpTFOrVRiGtuUvuP79++vaikpWEpONaYxSulnL6WUP//5z4Puc+XKlXF9Gjk1b968QecsZfjIp3Rc69ghPHEB0BWNC4CuaFwAdEXjAqArwhnHqd27d8f6xz72saqWRrR897vfjetb43DgcNIL+lQby7+xtJ/UmjVr4rEpiNHat26ooeGC1sinFIRII6PSGKdSShkZGalqaTRV2luwlPxZzZ49u6q1whWt0MabGfkEwLSmcQHQFY0LgK5oXAB0RTjjOHXzzTfHenqZu2zZsqrWesENRyq94E8v91sv/FNoIU3JaE3OSNMrUjBpz549g6+f1qdwRCuckUILL774YlV74IEH4vo09eacc86pahdccEFcv2TJkqqWwhnp5ywlTzlpBTkmkicu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\n",
"text/plain": [
"<Figure size 576x432 with 4 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_reconstructed_digits(X, outputs, \"./my_model_tying_weights.ckpt\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 여러 개의 그래프에서 오토인토더를 따로따로 훈련하기"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"하나의 오토인코더를 따로따로 훈련하는 방법이 많이 있습니다. 첫 번째 방법은 각 오토인코더를 다른 그래프를 사용하여 훈련하는 것입니다. 그런 다음 이런 오토인코더의 가중치와 편향을 복사해 초깃값으로 지정해서 적층 오토인코더를 만듭니다."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"하나의 오토인코더를 훈련하고 변환된 훈련 세트(즉, 은닉층의 출력)와 모델 파라미터를 반환하는 함수를 만들겠습니다."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"reset_graph()\n",
"\n",
"from functools import partial\n",
"\n",
"def train_autoencoder(X_train, n_neurons, n_epochs, batch_size,\n",
" learning_rate = 0.01, l2_reg = 0.0005, seed=42,\n",
" hidden_activation=tf.nn.elu,\n",
" output_activation=tf.nn.elu):\n",
" graph = tf.Graph()\n",
" with graph.as_default():\n",
" tf.set_random_seed(seed)\n",
"\n",
" n_inputs = X_train.shape[1]\n",
"\n",
" X = tf.placeholder(tf.float32, shape=[None, n_inputs])\n",
" \n",
" my_dense_layer = partial(\n",
" tf.layers.dense,\n",
" kernel_initializer=tf.variance_scaling_initializer(),\n",
" kernel_regularizer=tf.contrib.layers.l2_regularizer(l2_reg))\n",
"\n",
" hidden = my_dense_layer(X, n_neurons, activation=hidden_activation, name=\"hidden\")\n",
" outputs = my_dense_layer(hidden, n_inputs, activation=output_activation, name=\"outputs\")\n",
"\n",
" reconstruction_loss = tf.reduce_mean(tf.square(outputs - X))\n",
"\n",
" reg_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)\n",
" loss = tf.add_n([reconstruction_loss] + reg_losses)\n",
"\n",
" optimizer = tf.train.AdamOptimizer(learning_rate)\n",
" training_op = optimizer.minimize(loss)\n",
"\n",
" init = tf.global_variables_initializer()\n",
"\n",
" with tf.Session(graph=graph) as sess:\n",
" init.run()\n",
" for epoch in range(n_epochs):\n",
" n_batches = len(X_train) // batch_size\n",
" for iteration in range(n_batches):\n",
" print(\"\\r{}%\".format(100 * iteration // n_batches), end=\"\")\n",
" sys.stdout.flush()\n",
" indices = rnd.permutation(len(X_train))[:batch_size]\n",
" X_batch = X_train[indices]\n",
" sess.run(training_op, feed_dict={X: X_batch})\n",
" loss_train = reconstruction_loss.eval(feed_dict={X: X_batch})\n",
" print(\"\\r{}\".format(epoch), \"훈련 MSE:\", loss_train)\n",
" params = dict([(var.name, var.eval()) for var in tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES)])\n",
" hidden_val = hidden.eval(feed_dict={X: X_train})\n",
" return hidden_val, params[\"hidden/kernel:0\"], params[\"hidden/bias:0\"], params[\"outputs/kernel:0\"], params[\"outputs/bias:0\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"이제 두 개의 오토인코더를 훈련시켜 보죠. 첫 번째는 훈련 데이터를 사용하고 두 번째는 첫 번째 오토인코더의 은닉층 출력을 사용해 훈련시킵니다:"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 훈련 MSE: 0.01838611\n",
"1 훈련 MSE: 0.017672632\n",
"2 훈련 MSE: 0.019575823\n",
"3 훈련 MSE: 0.019316638\n",
"0 훈련 MSE: 0.0046300227\n",
"1 훈련 MSE: 0.004749075\n",
"2 훈련 MSE: 0.004754316\n",
"3 훈련 MSE: 0.0044352757\n"
]
}
],
"source": [
"hidden_output, W1, b1, W4, b4 = train_autoencoder(X_train, n_neurons=300, n_epochs=4, batch_size=150,\n",
" output_activation=None)\n",
"_, W2, b2, W3, b3 = train_autoencoder(hidden_output, n_neurons=150, n_epochs=4, batch_size=150)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"마지막으로 방금전 훈련한 오토인코더의 가중치와 편향을 재사용하여 적층 오토인코더를 만듭니다:"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
"reset_graph()\n",
"\n",
"n_inputs = 28*28\n",
"\n",
"X = tf.placeholder(tf.float32, shape=[None, n_inputs])\n",
"hidden1 = tf.nn.elu(tf.matmul(X, W1) + b1)\n",
"hidden2 = tf.nn.elu(tf.matmul(hidden1, W2) + b2)\n",
"hidden3 = tf.nn.elu(tf.matmul(hidden2, W3) + b3)\n",
"outputs = tf.matmul(hidden3, W4) + b4"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 576x432 with 4 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_reconstructed_digits(X, outputs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 하나의 그래프에서 오토인코더를 따로따로 훈련하기"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"하나의 그래프를 사용하는 방법도 있습니다. 이 방법은 전체 적층 오토인코더를 위한 그래프를 만들지만 각 오토인코더를 독립적으로 훈련하기 위한 연산도 추가합니다. 단계 1은 맨 아래층과 맨 윗층을 훈련하고(즉, 첫 번째 오토인코더), 단계 2는 두 개의 가운데 층을 훈련합니다(즉, 두 번째 오토인코더)."
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
"reset_graph()\n",
"\n",
"n_inputs = 28 * 28\n",
"n_hidden1 = 300\n",
"n_hidden2 = 150 # 코딩 유닛\n",
"n_hidden3 = n_hidden1\n",
"n_outputs = n_inputs\n",
"\n",
"learning_rate = 0.01\n",
"l2_reg = 0.0001\n",
"\n",
"activation = tf.nn.elu\n",
"regularizer = tf.contrib.layers.l2_regularizer(l2_reg)\n",
"initializer = tf.variance_scaling_initializer()\n",
"\n",
"X = tf.placeholder(tf.float32, shape=[None, n_inputs])\n",
"\n",
"weights1_init = initializer([n_inputs, n_hidden1])\n",
"weights2_init = initializer([n_hidden1, n_hidden2])\n",
"weights3_init = initializer([n_hidden2, n_hidden3])\n",
"weights4_init = initializer([n_hidden3, n_outputs])\n",
"\n",
"weights1 = tf.Variable(weights1_init, dtype=tf.float32, name=\"weights1\")\n",
"weights2 = tf.Variable(weights2_init, dtype=tf.float32, name=\"weights2\")\n",
"weights3 = tf.Variable(weights3_init, dtype=tf.float32, name=\"weights3\")\n",
"weights4 = tf.Variable(weights4_init, dtype=tf.float32, name=\"weights4\")\n",
"\n",
"biases1 = tf.Variable(tf.zeros(n_hidden1), name=\"biases1\")\n",
"biases2 = tf.Variable(tf.zeros(n_hidden2), name=\"biases2\")\n",
"biases3 = tf.Variable(tf.zeros(n_hidden3), name=\"biases3\")\n",
"biases4 = tf.Variable(tf.zeros(n_outputs), name=\"biases4\")\n",
"\n",
"hidden1 = activation(tf.matmul(X, weights1) + biases1)\n",
"hidden2 = activation(tf.matmul(hidden1, weights2) + biases2)\n",
"hidden3 = activation(tf.matmul(hidden2, weights3) + biases3)\n",
"outputs = tf.matmul(hidden3, weights4) + biases4\n",
"\n",
"reconstruction_loss = tf.reduce_mean(tf.square(outputs - X))"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
"optimizer = tf.train.AdamOptimizer(learning_rate)\n",
"\n",
"with tf.name_scope(\"phase1\"):\n",
" phase1_outputs = tf.matmul(hidden1, weights4) + biases4 # hidden2와 hidden3 통과합니다\n",
" phase1_reconstruction_loss = tf.reduce_mean(tf.square(phase1_outputs - X))\n",
" phase1_reg_loss = regularizer(weights1) + regularizer(weights4)\n",
" phase1_loss = phase1_reconstruction_loss + phase1_reg_loss\n",
" phase1_training_op = optimizer.minimize(phase1_loss)\n",
"\n",
"with tf.name_scope(\"phase2\"):\n",
" phase2_reconstruction_loss = tf.reduce_mean(tf.square(hidden3 - hidden1))\n",
" phase2_reg_loss = regularizer(weights2) + regularizer(weights3)\n",
" phase2_loss = phase2_reconstruction_loss + phase2_reg_loss\n",
" train_vars = [weights2, biases2, weights3, biases3]\n",
" phase2_training_op = optimizer.minimize(phase2_loss, var_list=train_vars) # hidden1 동결"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [],
"source": [
"init = tf.global_variables_initializer()\n",
"saver = tf.train.Saver()"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"훈련 단계 #1\n",
"0 훈련 MSE: 0.008080141\n",
"1 훈련 MSE: 0.007390184\n",
"2 훈련 MSE: 0.007787427\n",
"3 훈련 MSE: 0.0077560465\n",
"훈련 단계 #2\n",
"0 훈련 MSE: 0.1520265\n",
"1 훈련 MSE: 0.021897664\n",
"2 훈련 MSE: 0.005637195\n",
"3 훈련 MSE: 0.003436035\n",
"테스트 MSE: 0.010430704\n"
]
}
],
"source": [
"training_ops = [phase1_training_op, phase2_training_op]\n",
"reconstruction_losses = [phase1_reconstruction_loss, phase2_reconstruction_loss]\n",
"n_epochs = [4, 4]\n",
"batch_sizes = [150, 150]\n",
"\n",
"with tf.Session() as sess:\n",
" init.run()\n",
" for phase in range(2):\n",
" print(\"훈련 단계 #{}\".format(phase + 1))\n",
" for epoch in range(n_epochs[phase]):\n",
" n_batches = len(X_train) // batch_sizes[phase]\n",
" for iteration in range(n_batches):\n",
" print(\"\\r{}%\".format(100 * iteration // n_batches), end=\"\")\n",
" sys.stdout.flush()\n",
" X_batch, y_batch = next(shuffle_batch(X_train, y_train, batch_sizes[phase]))\n",
" sess.run(training_ops[phase], feed_dict={X: X_batch})\n",
" loss_train = reconstruction_losses[phase].eval(feed_dict={X: X_batch})\n",
" print(\"\\r{}\".format(epoch), \"훈련 MSE:\", loss_train)\n",
" saver.save(sess, \"./my_model_one_at_a_time.ckpt\")\n",
" loss_test = reconstruction_loss.eval(feed_dict={X: X_test})\n",
" print(\"테스트 MSE:\", loss_test)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 동결 층의 출력을 캐싱하기"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"훈련 단계 #1\n",
"0 훈련 MSE: 0.008428962\n",
"1 훈련 MSE: 0.007754741\n",
"2 훈련 MSE: 0.007211907\n",
"3 훈련 MSE: 0.007919097\n",
"훈련 단계 #2\n",
"0 훈련 MSE: 0.39475387\n",
"1 훈련 MSE: 0.013140139\n",
"2 훈련 MSE: 0.0064841826\n",
"3 훈련 MSE: 0.0036247855\n",
"테스트 MSE: 0.010436372\n"
]
}
],
"source": [
"training_ops = [phase1_training_op, phase2_training_op]\n",
"reconstruction_losses = [phase1_reconstruction_loss, phase2_reconstruction_loss]\n",
"n_epochs = [4, 4]\n",
"batch_sizes = [150, 150]\n",
"\n",
"with tf.Session() as sess:\n",
" init.run()\n",
" for phase in range(2):\n",
" print(\"훈련 단계 #{}\".format(phase + 1))\n",
" if phase == 1:\n",
" hidden1_cache = hidden1.eval(feed_dict={X: X_train})\n",
" for epoch in range(n_epochs[phase]):\n",
" n_batches = len(X_train) // batch_sizes[phase]\n",
" for iteration in range(n_batches):\n",
" print(\"\\r{}%\".format(100 * iteration // n_batches), end=\"\")\n",
" sys.stdout.flush()\n",
" if phase == 1:\n",
" indices = rnd.permutation(len(X_train))\n",
" hidden1_batch = hidden1_cache[indices[:batch_sizes[phase]]]\n",
" feed_dict = {hidden1: hidden1_batch}\n",
" sess.run(training_ops[phase], feed_dict=feed_dict)\n",
" else:\n",
" X_batch, y_batch = next(shuffle_batch(X_train, y_train, batch_sizes[phase]))\n",
" feed_dict = {X: X_batch}\n",
" sess.run(training_ops[phase], feed_dict=feed_dict)\n",
" loss_train = reconstruction_losses[phase].eval(feed_dict=feed_dict)\n",
" print(\"\\r{}\".format(epoch), \"훈련 MSE:\", loss_train)\n",
" saver.save(sess, \"./my_model_cache_frozen.ckpt\")\n",
" loss_test = reconstruction_loss.eval(feed_dict={X: X_test})\n",
" print(\"테스트 MSE:\", loss_test)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 재구성 시각화"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO:tensorflow:Restoring parameters from ./my_model_one_at_a_time.ckpt\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 4 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"n_test_digits = 2\n",
"# X_test = mnist.test.images[:n_test_digits]\n",
"\n",
"with tf.Session() as sess:\n",
" saver.restore(sess, \"./my_model_one_at_a_time.ckpt\") # not shown in the book\n",
" outputs_val = outputs.eval(feed_dict={X: X_test[:n_test_digits]})\n",
"\n",
"def plot_image(image, shape=[28, 28]):\n",
" plt.imshow(image.reshape(shape), cmap=\"Greys\", interpolation=\"nearest\")\n",
" plt.axis(\"off\")\n",
"\n",
"for digit_index in range(n_test_digits):\n",
" plt.subplot(n_test_digits, 2, digit_index * 2 + 1)\n",
" plot_image(X_test[digit_index])\n",
" plt.subplot(n_test_digits, 2, digit_index * 2 + 2)\n",
" plot_image(outputs_val[digit_index])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 특성 시각화"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO:tensorflow:Restoring parameters from ./my_model_one_at_a_time.ckpt\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 5 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"with tf.Session() as sess:\n",
" saver.restore(sess, \"./my_model_one_at_a_time.ckpt\") # 책에는 없음\n",
" weights1_val = weights1.eval()\n",
"\n",
"for i in range(5):\n",
" plt.subplot(1, 5, i + 1)\n",
" plot_image(weights1_val.T[i])\n",
"\n",
"save_fig(\"extracted_features_plot\") # 책에는 없음\n",
"plt.show() # 책에는 없음"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 비지도 사전훈련"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"MNIST 분류 문제를 위한 작은 신경망을 만들겠습니다:"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [],
"source": [
"reset_graph()\n",
"\n",
"n_inputs = 28 * 28\n",
"n_hidden1 = 300\n",
"n_hidden2 = 150\n",
"n_outputs = 10\n",
"\n",
"learning_rate = 0.01\n",
"l2_reg = 0.0005\n",
"\n",
"activation = tf.nn.elu\n",
"regularizer = tf.contrib.layers.l2_regularizer(l2_reg)\n",
"initializer = tf.variance_scaling_initializer()\n",
"\n",
"X = tf.placeholder(tf.float32, shape=[None, n_inputs])\n",
"y = tf.placeholder(tf.int32, shape=[None])\n",
"\n",
"weights1_init = initializer([n_inputs, n_hidden1])\n",
"weights2_init = initializer([n_hidden1, n_hidden2])\n",
"weights3_init = initializer([n_hidden2, n_outputs])\n",
"\n",
"weights1 = tf.Variable(weights1_init, dtype=tf.float32, name=\"weights1\")\n",
"weights2 = tf.Variable(weights2_init, dtype=tf.float32, name=\"weights2\")\n",
"weights3 = tf.Variable(weights3_init, dtype=tf.float32, name=\"weights3\")\n",
"\n",
"biases1 = tf.Variable(tf.zeros(n_hidden1), name=\"biases1\")\n",
"biases2 = tf.Variable(tf.zeros(n_hidden2), name=\"biases2\")\n",
"biases3 = tf.Variable(tf.zeros(n_outputs), name=\"biases3\")\n",
"\n",
"hidden1 = activation(tf.matmul(X, weights1) + biases1)\n",
"hidden2 = activation(tf.matmul(hidden1, weights2) + biases2)\n",
"logits = tf.matmul(hidden2, weights3) + biases3\n",
"\n",
"cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)\n",
"reg_loss = regularizer(weights1) + regularizer(weights2) + regularizer(weights3)\n",
"loss = cross_entropy + reg_loss\n",
"optimizer = tf.train.AdamOptimizer(learning_rate)\n",
"training_op = optimizer.minimize(loss)\n",
"\n",
"correct = tf.nn.in_top_k(logits, y, 1)\n",
"accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))\n",
"\n",
"init = tf.global_variables_initializer()\n",
"pretrain_saver = tf.train.Saver([weights1, weights2, biases1, biases2])\n",
"saver = tf.train.Saver()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(사전훈련 없이)평범하게 훈련시킵니다:"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 검증 세트 정확도: 0.93333334 테스트 정확도: 0.9143\n",
"1 검증 세트 정확도: 0.97333336 테스트 정확도: 0.9413\n",
"2 검증 세트 정확도: 0.96 테스트 정확도: 0.9265\n",
"3 검증 세트 정확도: 0.97333336 테스트 정확도: 0.9392\n"
]
}
],
"source": [
"n_epochs = 4\n",
"batch_size = 150\n",
"n_labeled_instances = 20000\n",
"\n",
"with tf.Session() as sess:\n",
" init.run()\n",
" for epoch in range(n_epochs):\n",
" n_batches = n_labeled_instances // batch_size\n",
" for iteration in range(n_batches):\n",
" print(\"\\r{}%\".format(100 * iteration // n_batches), end=\"\")\n",
" sys.stdout.flush()\n",
" indices = rnd.permutation(n_labeled_instances)[:batch_size]\n",
" X_batch, y_batch = X_train[indices], y_train[indices]\n",
" sess.run(training_op, feed_dict={X: X_batch, y: y_batch})\n",
" accuracy_val = accuracy.eval(feed_dict={X: X_batch, y: y_batch})\n",
" print(\"\\r{}\".format(epoch), \"검증 세트 정확도:\", accuracy_val, end=\" \")\n",
" saver.save(sess, \"./my_model_supervised.ckpt\")\n",
" test_val = accuracy.eval(feed_dict={X: X_test, y: y_test})\n",
" print(\"테스트 정확도:\", test_val)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"사전 훈련된 오토인코더의 첫 두개의 층을 재사용해 보겠습니다:"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO:tensorflow:Restoring parameters from ./my_model_cache_frozen.ckpt\n",
"0 훈련 정확도: 0.96\t테스트 정확도: 0.9113\n",
"1 훈련 정확도: 0.9266667\t테스트 정확도: 0.9386\n",
"2 훈련 정확도: 0.9533333\t테스트 정확도: 0.9356\n",
"3 훈련 정확도: 0.96666664\t테스트 정확도: 0.9433\n"
]
}
],
"source": [
"n_epochs = 4\n",
"batch_size = 150\n",
"n_labeled_instances = 20000\n",
"\n",
"#training_op = optimizer.minimize(loss, var_list=[weights3, biases3]) # layers 1와 2를 동결 (선택사항)\n",
"\n",
"with tf.Session() as sess:\n",
" init.run()\n",
" pretrain_saver.restore(sess, \"./my_model_cache_frozen.ckpt\")\n",
" for epoch in range(n_epochs):\n",
" n_batches = n_labeled_instances // batch_size\n",
" for iteration in range(n_batches):\n",
" print(\"\\r{}%\".format(100 * iteration // n_batches), end=\"\")\n",
" sys.stdout.flush()\n",
" indices = rnd.permutation(n_labeled_instances)[:batch_size]\n",
" X_batch, y_batch = X_train[indices], y_train[indices]\n",
" sess.run(training_op, feed_dict={X: X_batch, y: y_batch})\n",
" accuracy_val = accuracy.eval(feed_dict={X: X_batch, y: y_batch})\n",
" print(\"\\r{}\".format(epoch), \"훈련 정확도:\", accuracy_val, end=\"\\t\")\n",
" saver.save(sess, \"./my_model_supervised_pretrained.ckpt\")\n",
" test_val = accuracy.eval(feed_dict={X: X_test, y: y_test})\n",
" print(\"테스트 정확도:\", test_val)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 적층 잡음제거 오토인코더"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"가우시안 잡음을 사용합니다:"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [],
"source": [
"reset_graph()\n",
"\n",
"n_inputs = 28 * 28\n",
"n_hidden1 = 300\n",
"n_hidden2 = 150 # 코딩 유닛\n",
"n_hidden3 = n_hidden1\n",
"n_outputs = n_inputs\n",
"\n",
"learning_rate = 0.01"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [],
"source": [
"noise_level = 1.0\n",
"\n",
"X = tf.placeholder(tf.float32, shape=[None, n_inputs])\n",
"X_noisy = X + noise_level * tf.random_normal(tf.shape(X))\n",
"\n",
"hidden1 = tf.layers.dense(X_noisy, n_hidden1, activation=tf.nn.relu,\n",
" name=\"hidden1\")\n",
"hidden2 = tf.layers.dense(hidden1, n_hidden2, activation=tf.nn.relu, # 책에는 없음\n",
" name=\"hidden2\") # 책에는 없음\n",
"hidden3 = tf.layers.dense(hidden2, n_hidden3, activation=tf.nn.relu, # 책에는 없음\n",
" name=\"hidden3\") # 책에는 없음\n",
"outputs = tf.layers.dense(hidden3, n_outputs, name=\"outputs\") # 책에는 없음\n",
"\n",
"reconstruction_loss = tf.reduce_mean(tf.square(outputs - X)) # MSE"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [],
"source": [
"optimizer = tf.train.AdamOptimizer(learning_rate)\n",
"training_op = optimizer.minimize(reconstruction_loss)\n",
" \n",
"init = tf.global_variables_initializer()\n",
"saver = tf.train.Saver()"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 훈련 MSE: 0.0442446\n",
"1 훈련 MSE: 0.03856391\n",
"2 훈련 MSE: 0.043473296\n",
"3 훈련 MSE: 0.041986465\n",
"4 훈련 MSE: 0.04145979\n",
"5 훈련 MSE: 0.040962033\n",
"6 훈련 MSE: 0.042370714\n",
"7 훈련 MSE: 0.040187325\n",
"8 훈련 MSE: 0.043344878\n",
"9 훈련 MSE: 0.043597136\n"
]
}
],
"source": [
"n_epochs = 10\n",
"batch_size = 150\n",
"\n",
"with tf.Session() as sess:\n",
" init.run()\n",
" for epoch in range(n_epochs):\n",
" n_batches = len(X_train) // batch_size\n",
" for iteration in range(n_batches):\n",
" print(\"\\r{}%\".format(100 * iteration // n_batches), end=\"\")\n",
" sys.stdout.flush()\n",
" X_batch, y_batch = next(shuffle_batch(X_train, y_train, batch_size))\n",
" sess.run(training_op, feed_dict={X: X_batch})\n",
" loss_train = reconstruction_loss.eval(feed_dict={X: X_batch})\n",
" print(\"\\r{}\".format(epoch), \"훈련 MSE:\", loss_train)\n",
" saver.save(sess, \"./my_model_stacked_denoising_gaussian.ckpt\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"드롭아웃을 사용합니다:"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [],
"source": [
"reset_graph()\n",
"\n",
"n_inputs = 28 * 28\n",
"n_hidden1 = 300\n",
"n_hidden2 = 150 # 코딩 유닛\n",
"n_hidden3 = n_hidden1\n",
"n_outputs = n_inputs\n",
"\n",
"learning_rate = 0.01"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [],
"source": [
"dropout_rate = 0.3\n",
"\n",
"training = tf.placeholder_with_default(False, shape=(), name='training')\n",
"\n",
"X = tf.placeholder(tf.float32, shape=[None, n_inputs])\n",
"X_drop = tf.layers.dropout(X, dropout_rate, training=training)\n",
"\n",
"hidden1 = tf.layers.dense(X_drop, n_hidden1, activation=tf.nn.relu,\n",
" name=\"hidden1\")\n",
"hidden2 = tf.layers.dense(hidden1, n_hidden2, activation=tf.nn.relu, # 책에는 없음\n",
" name=\"hidden2\") # 책에는 없음\n",
"hidden3 = tf.layers.dense(hidden2, n_hidden3, activation=tf.nn.relu, # 책에는 없음\n",
" name=\"hidden3\") # 책에는 없음\n",
"outputs = tf.layers.dense(hidden3, n_outputs, name=\"outputs\") # 책에는 없음\n",
"\n",
"reconstruction_loss = tf.reduce_mean(tf.square(outputs - X)) # MSE"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [],
"source": [
"optimizer = tf.train.AdamOptimizer(learning_rate)\n",
"training_op = optimizer.minimize(reconstruction_loss)\n",
" \n",
"init = tf.global_variables_initializer()\n",
"saver = tf.train.Saver()"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 훈련 MSE: 0.035001453\n",
"1 훈련 MSE: 0.027627887\n",
"2 훈련 MSE: 0.030352144\n",
"3 훈련 MSE: 0.027474204\n",
"4 훈련 MSE: 0.026787175\n",
"5 훈련 MSE: 0.026213126\n",
"6 훈련 MSE: 0.027075535\n",
"7 훈련 MSE: 0.025293095\n",
"8 훈련 MSE: 0.027090674\n",
"9 훈련 MSE: 0.027737001\n"
]
}
],
"source": [
"n_epochs = 10\n",
"batch_size = 150\n",
"\n",
"with tf.Session() as sess:\n",
" init.run()\n",
" for epoch in range(n_epochs):\n",
" n_batches = len(X_train) // batch_size\n",
" for iteration in range(n_batches):\n",
" print(\"\\r{}%\".format(100 * iteration // n_batches), end=\"\")\n",
" sys.stdout.flush()\n",
" X_batch, y_batch = next(shuffle_batch(X_train, y_train, batch_size))\n",
" sess.run(training_op, feed_dict={X: X_batch, training: True})\n",
" loss_train = reconstruction_loss.eval(feed_dict={X: X_batch})\n",
" print(\"\\r{}\".format(epoch), \"훈련 MSE:\", loss_train)\n",
" saver.save(sess, \"./my_model_stacked_denoising_dropout.ckpt\")"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO:tensorflow:Restoring parameters from ./my_model_stacked_denoising_dropout.ckpt\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 576x432 with 4 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_reconstructed_digits(X, outputs, \"./my_model_stacked_denoising_dropout.ckpt\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 희소 오토인코더"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"p = 0.1\n",
"q = np.linspace(0.001, 0.999, 500)\n",
"kl_div = p * np.log(p / q) + (1 - p) * np.log((1 - p) / (1 - q))\n",
"mse = (p - q)**2\n",
"plt.plot([p, p], [0, 0.3], \"k:\")\n",
"plt.text(0.05, 0.32, \"목표 희소\", fontsize=14)\n",
"plt.plot(q, kl_div, \"b-\", label=\"쿨백 라이블러 발산\")\n",
"plt.plot(q, mse, \"r--\", label=\"MSE\")\n",
"plt.legend(loc=\"upper left\")\n",
"plt.xlabel(\"실제 희소\")\n",
"plt.ylabel(\"비용\", rotation=0)\n",
"plt.axis([0, 1, 0, 0.95])\n",
"save_fig(\"sparsity_loss_plot\")"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [],
"source": [
"reset_graph()\n",
"\n",
"n_inputs = 28 * 28\n",
"n_hidden1 = 1000 # 희소 코딩 유닛\n",
"n_outputs = n_inputs"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [],
"source": [
"def kl_divergence(p, q):\n",
" # 쿨백 라이블러 발산\n",
" return p * tf.log(p / q) + (1 - p) * tf.log((1 - p) / (1 - q))\n",
"\n",
"learning_rate = 0.01\n",
"sparsity_target = 0.1\n",
"sparsity_weight = 0.2\n",
"\n",
"X = tf.placeholder(tf.float32, shape=[None, n_inputs]) # 책에는 없음\n",
"\n",
"hidden1 = tf.layers.dense(X, n_hidden1, activation=tf.nn.sigmoid) # 책에는 없음\n",
"outputs = tf.layers.dense(hidden1, n_outputs) # 책에는 없음\n",
"\n",
"hidden1_mean = tf.reduce_mean(hidden1, axis=0) # 배치 평균\n",
"sparsity_loss = tf.reduce_sum(kl_divergence(sparsity_target, hidden1_mean))\n",
"reconstruction_loss = tf.reduce_mean(tf.square(outputs - X)) # MSE\n",
"loss = reconstruction_loss + sparsity_weight * sparsity_loss\n",
"\n",
"optimizer = tf.train.AdamOptimizer(learning_rate)\n",
"training_op = optimizer.minimize(loss)"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {},
"outputs": [],
"source": [
"init = tf.global_variables_initializer()\n",
"saver = tf.train.Saver()"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 훈련 MSE: 0.13764462 \t희소 손실: 0.90867597 \t전체 손실: 0.3193798\n",
"1 훈련 MSE: 0.059780527 \t희소 손실: 0.023853423 \t전체 손실: 0.06455121\n",
"2 훈련 MSE: 0.052597478 \t희소 손실: 0.028876154 \t전체 손실: 0.05837271\n",
"3 훈련 MSE: 0.05017224 \t희소 손실: 0.19674344 \t전체 손실: 0.08952093\n",
"4 훈련 MSE: 0.04457513 \t희소 손실: 0.0070949676 \t전체 손실: 0.04599412\n",
"5 훈련 MSE: 0.03982869 \t희소 손실: 0.35642004 \t전체 손실: 0.1111127\n",
"6 훈련 MSE: 0.03850078 \t희소 손실: 0.04892056 \t전체 손실: 0.048284892\n",
"7 훈련 MSE: 0.036211833 \t희소 손실: 0.023475863 \t전체 손실: 0.040907007\n",
"8 훈련 MSE: 0.033634793 \t희소 손실: 0.05728952 \t전체 손실: 0.0450927\n",
"9 훈련 MSE: 0.030880695 \t희소 손실: 0.042791054 \t전체 손실: 0.039438907\n",
"10 훈련 MSE: 0.028282987 \t희소 손실: 0.32261807 \t전체 손실: 0.0928066\n",
"11 훈련 MSE: 0.02501558 \t희소 손실: 0.030906674 \t전체 손실: 0.031196915\n",
"12 훈련 MSE: 0.023248762 \t희소 손실: 0.08872005 \t전체 손실: 0.040992774\n",
"13 훈련 MSE: 0.021769173 \t희소 손실: 0.06630076 \t전체 손실: 0.035029326\n",
"14 훈련 MSE: 0.02200607 \t희소 손실: 0.11473313 \t전체 손실: 0.044952698\n",
"15 훈련 MSE: 0.020363854 \t희소 손실: 0.047968887 \t전체 손실: 0.029957632\n",
"16 훈련 MSE: 0.017985545 \t희소 손실: 0.18309356 \t전체 손실: 0.05460426\n",
"17 훈련 MSE: 0.018661918 \t희소 손실: 0.029090682 \t전체 손실: 0.024480054\n",
"18 훈련 MSE: 0.017803263 \t희소 손실: 0.23516989 \t전체 손실: 0.06483724\n",
"19 훈련 MSE: 0.017381176 \t희소 손실: 0.024946319 \t전체 손실: 0.02237044\n",
"20 훈련 MSE: 0.017425464 \t희소 손실: 0.0866967 \t전체 손실: 0.034764804\n",
"21 훈련 MSE: 0.016189657 \t희소 손실: 0.041223954 \t전체 손실: 0.024434447\n",
"22 훈련 MSE: 0.016698195 \t희소 손실: 0.04975501 \t전체 손실: 0.026649196\n",
"23 훈련 MSE: 0.015898876 \t희소 손실: 0.05508917 \t전체 손실: 0.026916709\n",
"24 훈련 MSE: 0.01725482 \t희소 손실: 0.07781921 \t전체 손실: 0.032818664\n",
"25 훈련 MSE: 0.015573322 \t희소 손실: 0.08851827 \t전체 손실: 0.033276975\n",
"26 훈련 MSE: 0.014312166 \t희소 손실: 0.071160555 \t전체 손실: 0.028544277\n",
"27 훈련 MSE: 0.013452826 \t희소 손실: 0.039495397 \t전체 손실: 0.021351906\n",
"28 훈련 MSE: 0.0141818 \t희소 손실: 0.034272946 \t전체 손실: 0.02103639\n",
"29 훈련 MSE: 0.0142338965 \t희소 손실: 0.0917896 \t전체 손실: 0.03259182\n",
"30 훈련 MSE: 0.015912354 \t희소 손실: 0.08804717 \t전체 손실: 0.033521786\n",
"31 훈련 MSE: 0.014909098 \t희소 손실: 0.09869958 \t전체 손실: 0.034649014\n",
"32 훈련 MSE: 0.012845991 \t희소 손실: 0.049286373 \t전체 손실: 0.022703266\n",
"33 훈련 MSE: 0.013661297 \t희소 손실: 0.09084565 \t전체 손실: 0.03183043\n",
"34 훈련 MSE: 0.013174699 \t희소 손실: 0.041957993 \t전체 손실: 0.021566298\n",
"35 훈련 MSE: 0.013076462 \t희소 손실: 0.038095992 \t전체 손실: 0.02069566\n",
"36 훈련 MSE: 0.013874385 \t희소 손실: 0.05388694 \t전체 손실: 0.024651773\n",
"37 훈련 MSE: 0.014134639 \t희소 손실: 0.087803714 \t전체 손실: 0.03169538\n",
"38 훈련 MSE: 0.012819664 \t희소 손실: 0.23281287 \t전체 손실: 0.059382237\n",
"39 훈련 MSE: 0.012348052 \t희소 손실: 0.0440435 \t전체 손실: 0.021156752\n",
"40 훈련 MSE: 0.012252705 \t희소 손실: 0.13875237 \t전체 손실: 0.04000318\n",
"41 훈련 MSE: 0.012996037 \t희소 손실: 0.124482624 \t전체 손실: 0.03789256\n",
"42 훈련 MSE: 0.01273182 \t희소 손실: 0.05220629 \t전체 손실: 0.023173079\n",
"43 훈련 MSE: 0.012437585 \t희소 손실: 0.15004826 \t전체 손실: 0.042447235\n",
"44 훈련 MSE: 0.013994326 \t희소 손실: 0.08615906 \t전체 손실: 0.03122614\n",
"45 훈련 MSE: 0.013336399 \t희소 손실: 0.18166158 \t전체 손실: 0.049668714\n",
"46 훈련 MSE: 0.012504962 \t희소 손실: 0.17852002 \t전체 손실: 0.048208967\n",
"47 훈련 MSE: 0.013035357 \t희소 손실: 0.13480854 \t전체 손실: 0.039997064\n",
"48 훈련 MSE: 0.012266207 \t희소 손실: 0.07757069 \t전체 손실: 0.027780345\n",
"49 훈련 MSE: 0.013177205 \t희소 손실: 0.0943829 \t전체 손실: 0.032053784\n",
"50 훈련 MSE: 0.011335693 \t희소 손실: 0.055620328 \t전체 손실: 0.02245976\n",
"51 훈련 MSE: 0.011653456 \t희소 손실: 0.18031868 \t전체 손실: 0.047717195\n",
"52 훈련 MSE: 0.011956116 \t희소 손실: 0.05638638 \t전체 손실: 0.023233391\n",
"53 훈련 MSE: 0.011858154 \t희소 손실: 0.09703225 \t전체 손실: 0.031264603\n",
"54 훈련 MSE: 0.011784152 \t희소 손실: 0.083307154 \t전체 손실: 0.028445583\n",
"55 훈련 MSE: 0.0119370725 \t희소 손실: 0.15825328 \t전체 손실: 0.04358773\n",
"56 훈련 MSE: 0.012403161 \t희소 손실: 0.18447791 \t전체 손실: 0.049298745\n",
"57 훈련 MSE: 0.0120612765 \t희소 손실: 0.14881416 \t전체 손실: 0.04182411\n",
"58 훈련 MSE: 0.013030441 \t희소 손실: 0.2036531 \t전체 손실: 0.05376106\n",
"59 훈련 MSE: 0.015655164 \t희소 손실: 0.1561568 \t전체 손실: 0.046886522\n",
"60 훈련 MSE: 0.012486809 \t희소 손실: 0.25863346 \t전체 손실: 0.06421351\n",
"61 훈련 MSE: 0.015972901 \t희소 손실: 0.9596205 \t전체 손실: 0.207897\n",
"62 훈련 MSE: 0.017744554 \t희소 손실: 0.2004545 \t전체 손실: 0.057835452\n",
"63 훈련 MSE: 0.016123325 \t희소 손실: 0.55819446 \t전체 손실: 0.12776223\n",
"64 훈련 MSE: 0.013705003 \t희소 손실: 0.8484207 \t전체 손실: 0.18338914\n",
"65 훈련 MSE: 0.013311629 \t희소 손실: 0.14226675 \t전체 손실: 0.04176498\n",
"66 훈련 MSE: 0.015507304 \t희소 손실: 1.1463888 \t전체 손실: 0.24478507\n",
"67 훈련 MSE: 0.011973931 \t희소 손실: 0.26371512 \t전체 손실: 0.06471696\n",
"68 훈련 MSE: 0.015678437 \t희소 손실: 0.16926403 \t전체 손실: 0.049531244\n",
"69 훈련 MSE: 0.03865941 \t희소 손실: 0.19129409 \t전체 손실: 0.07691823\n",
"70 훈련 MSE: 0.013939619 \t희소 손실: 0.57569885 \t전체 손실: 0.1290794\n",
"71 훈련 MSE: 0.016075313 \t희소 손실: 0.17884825 \t전체 손실: 0.051844966\n",
"72 훈련 MSE: 0.014636907 \t희소 손실: 0.18175915 \t전체 손실: 0.050988737\n",
"73 훈련 MSE: 0.028090823 \t희소 손실: 0.37423268 \t전체 손실: 0.102937356\n",
"74 훈련 MSE: 0.022609375 \t희소 손실: 0.1392368 \t전체 손실: 0.050456733\n",
"75 훈련 MSE: 0.07680417 \t희소 손실: 0.7973846 \t전체 손실: 0.2362811\n",
"76 훈련 MSE: 0.025242347 \t희소 손실: 0.19677864 \t전체 손실: 0.064598076\n",
"77 훈련 MSE: 0.015000151 \t희소 손실: 0.7557995 \t전체 손실: 0.16616005\n",
"78 훈련 MSE: 0.016652029 \t희소 손실: 0.119504154 \t전체 손실: 0.040552862\n",
"79 훈련 MSE: 0.014573195 \t희소 손실: 0.2708728 \t전체 손실: 0.06874776\n",
"80 훈련 MSE: 0.0149989035 \t희소 손실: 0.2499745 \t전체 손실: 0.064993806\n",
"81 훈련 MSE: 0.012900565 \t희소 손실: 0.6505898 \t전체 손실: 0.14301853\n",
"82 훈련 MSE: 0.017544089 \t희소 손실: 0.6239798 \t전체 손실: 0.14234005\n",
"83 훈련 MSE: 0.015405096 \t희소 손실: 0.19303808 \t전체 손실: 0.054012712\n",
"84 훈련 MSE: 0.029969472 \t희소 손실: 0.18823238 \t전체 손실: 0.06761595\n",
"85 훈련 MSE: 0.014427009 \t희소 손실: 0.6550485 \t전체 손실: 0.1454367\n",
"86 훈련 MSE: 0.015298896 \t희소 손실: 0.13435858 \t전체 손실: 0.042170614\n",
"87 훈련 MSE: 0.015689839 \t희소 손실: 0.25018495 \t전체 손실: 0.06572683\n",
"88 훈련 MSE: 0.028420692 \t희소 손실: 0.29241624 \t전체 손실: 0.086903945\n",
"89 훈련 MSE: 0.016309444 \t희소 손실: 0.43265104 \t전체 손실: 0.10283965\n",
"90 훈련 MSE: 0.018916653 \t희소 손실: 0.17150912 \t전체 손실: 0.053218476\n",
"91 훈련 MSE: 0.036028225 \t희소 손실: 0.21815218 \t전체 손실: 0.07965866\n",
"92 훈련 MSE: 0.024213655 \t희소 손실: 0.90460145 \t전체 손실: 0.20513394\n",
"93 훈련 MSE: 0.015083556 \t희소 손실: 0.07066245 \t전체 손실: 0.029216046\n",
"94 훈련 MSE: 0.014100681 \t희소 손실: 0.4641513 \t전체 손실: 0.10693094\n",
"95 훈련 MSE: 0.014648245 \t희소 손실: 0.08357882 \t전체 손실: 0.03136401\n",
"96 훈련 MSE: 0.01886718 \t희소 손실: 0.95776266 \t전체 손실: 0.21041971\n",
"97 훈련 MSE: 0.017021567 \t희소 손실: 1.006425 \t전체 손실: 0.21830657\n",
"98 훈련 MSE: 0.019905027 \t희소 손실: 0.11643936 \t전체 손실: 0.0431929\n",
"99 훈련 MSE: 0.0144011825 \t희소 손실: 0.28757378 \t전체 손실: 0.07191594\n"
]
}
],
"source": [
"n_epochs = 100\n",
"batch_size = 1000\n",
"\n",
"with tf.Session() as sess:\n",
" init.run()\n",
" for epoch in range(n_epochs):\n",
" n_batches = len(X_train) // batch_size\n",
" for iteration in range(n_batches):\n",
" print(\"\\r{}%\".format(100 * iteration // n_batches), end=\"\")\n",
" sys.stdout.flush()\n",
" X_batch, y_batch = next(shuffle_batch(X_train, y_train, batch_size))\n",
" sess.run(training_op, feed_dict={X: X_batch})\n",
" reconstruction_loss_val, sparsity_loss_val, loss_val = sess.run([reconstruction_loss, sparsity_loss, loss], feed_dict={X: X_batch})\n",
" print(\"\\r{}\".format(epoch), \"훈련 MSE:\", reconstruction_loss_val, \"\\t희소 손실:\", sparsity_loss_val, \"\\t전체 손실:\", loss_val)\n",
" saver.save(sess, \"./my_model_sparse.ckpt\")"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO:tensorflow:Restoring parameters from ./my_model_sparse.ckpt\n"
]
},
{
"data": {
"image/png": "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d5uaClJ41/Tll1+a2gUXXJB1TSml9MEHH5iaCrGo0U4p6X3GVq5caWptbW1yfaW/h9xxAQBCoXEBAEKhcQEAQqFxAQBCIZwxjGbPnl2T89xxxx2mpv6P/pRS2rt3r6n9/ve/r/o1leW9d7fffnuNrwTVooIYKohw4sQJuV7tCaUm0Xj/9ufNm2dqe/bsMbXt27fL9Zs2bTI1FdhQ0yC8PcIUNSHEC1Cp0MR5551namqahrdeTfPwppmocxWZhsF+XACAUYHGBQAIhcYFAAiFxgUACIXGBQAIhVThKdx0002m9vjjj9fhSk7t0UcfrfoxvRSRN3rmZLfccousX3rppVnrV61alfU6xKZSgV4qTaXd1Agwb+8nlYDbsWOHqankrXdcNR5JpRK9pOLUqVNNTaUKvVFnKoGp3ifvPVF1dUw12iklvfeWGsPl/Z5UijsuAEAoNC4AQCg0LgBAKDQuAEAohDNO4bHHHjO1733ve6Y2MDBQ6jxqT5+yY5juueceWV+0aFHW+h//+MeyPn369IqvCaObeuiv9ofzggjqtb29vdnr1RixZcuWmVqRIIPaT0qNgfL241KjmFS4wQusqHBEc3OzqXkj1NT+emoMljea6fzzzze11tbW7PWV4o4LABAKjQsAEAqNCwAQCo0LABDKmCJ7p1RJzU+IEa+6T36RbdeuXaW+z+qhfZEpCyqwUeRcKsjh/SaqcIkKZxw6dCirlpIOUuReZ0p6ko3a46yxsVGuV1M2VJDEe5/b2tpMLfdv8syfP/+0L+aOCwAQCo0LABAKjQsAEAqNCwAQCo0LABAKI58A1I1K8A0ODma/dmhoyNSKJNhUUtBLFaoEoaJGQ3n72Km6On/Za1J/Z0p6ny01hkq9zynp/dSqPd5J4Y4LABAKjQsAEAqNCwAQCo0LABAK4QwAdaPCBV6QQD3090IPuedSo5S88Ua546XU61SIwbsmtd4LrORekxeYyB0v5b3PueGQauOOCwAQCo0LABAKjQsAEAqNCwAQCuEMAHXjBTFyqXBAX1+ffK0KSKjQgzelYmBgIOuYaj8sL9ygwhXqPfHCHWq9ClwU2bdMqVcIw/PtuhoAAE6DxgUACIXGBQAIhcYFAAiFxgUACIVUIYCaUGk3L8FXhkr1eVTazrum3L2z+vv7s8+v1ucmBb1rUorskVX2M6nF58wdFwAgFBoXACAUGhcAIBQaFwAglDHD8XAUAIDhwh0XACAUGhcAIBQaFwAgFBoXACAUGhcAIBQaFwAgFBoXACAUGhcAIBQaFwAgFBoXACAUGhcAIBQaFwAgFBoXACAUGhcAIBQaFwAgFBoXACAUGhcAIBQaFwAgFBoXACAUGhcAIBQaFwAgFBoXACAUGhcAIBQaFwAgFBoXACCU/wMXtCIZJljJngAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 576x432 with 4 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_reconstructed_digits(X, outputs, \"./my_model_sparse.ckpt\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"코딩층은 0에서 1사이의 값을 출력해야 하므로 시그모이드 활성화 함수를 사용합니다:"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [],
"source": [
"hidden1 = tf.layers.dense(X, n_hidden1, activation=tf.nn.sigmoid)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"훈련 속도를 높이기 위해 입력을 0과 1사이로 정규화하고 비용 함수로 MSE 대신 크로스엔트로피를 사용합니다:"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [],
"source": [
"logits = tf.layers.dense(hidden1, n_outputs)\n",
"outputs = tf.nn.sigmoid(logits)\n",
"\n",
"xentropy = tf.nn.sigmoid_cross_entropy_with_logits(labels=X, logits=logits)\n",
"reconstruction_loss = tf.reduce_mean(xentropy)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 변이형 오토인코더"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {},
"outputs": [],
"source": [
"reset_graph()\n",
"\n",
"from functools import partial\n",
"\n",
"n_inputs = 28 * 28\n",
"n_hidden1 = 500\n",
"n_hidden2 = 500\n",
"n_hidden3 = 20 # 코딩 유닛\n",
"n_hidden4 = n_hidden2\n",
"n_hidden5 = n_hidden1\n",
"n_outputs = n_inputs\n",
"learning_rate = 0.001\n",
"\n",
"initializer = tf.variance_scaling_initializer()\n",
"\n",
"my_dense_layer = partial(\n",
" tf.layers.dense,\n",
" activation=tf.nn.elu,\n",
" kernel_initializer=initializer)\n",
"\n",
"X = tf.placeholder(tf.float32, [None, n_inputs])\n",
"hidden1 = my_dense_layer(X, n_hidden1)\n",
"hidden2 = my_dense_layer(hidden1, n_hidden2)\n",
"hidden3_mean = my_dense_layer(hidden2, n_hidden3, activation=None)\n",
"hidden3_sigma = my_dense_layer(hidden2, n_hidden3, activation=None)\n",
"noise = tf.random_normal(tf.shape(hidden3_sigma), dtype=tf.float32)\n",
"hidden3 = hidden3_mean + hidden3_sigma * noise\n",
"hidden4 = my_dense_layer(hidden3, n_hidden4)\n",
"hidden5 = my_dense_layer(hidden4, n_hidden5)\n",
"logits = my_dense_layer(hidden5, n_outputs, activation=None)\n",
"outputs = tf.sigmoid(logits)\n",
"\n",
"xentropy = tf.nn.sigmoid_cross_entropy_with_logits(labels=X, logits=logits)\n",
"reconstruction_loss = tf.reduce_sum(xentropy)"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {},
"outputs": [],
"source": [
"eps = 1e-10 # NaN을 반환하는 log(0)을 피하기 위한 안전항\n",
"latent_loss = 0.5 * tf.reduce_sum(\n",
" tf.square(hidden3_sigma) + tf.square(hidden3_mean)\n",
" - 1 - tf.log(eps + tf.square(hidden3_sigma)))"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {},
"outputs": [],
"source": [
"loss = reconstruction_loss + latent_loss\n",
"\n",
"optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)\n",
"training_op = optimizer.minimize(loss)\n",
"\n",
"init = tf.global_variables_initializer()\n",
"saver = tf.train.Saver()"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 훈련 전체 손실: 30969.459 \t재구성 손실: 24516.871 \t잠재 손실: 6452.588\n",
"1 훈련 전체 손실: 28966.72 \t재구성 손실: 22678.564 \t잠재 손실: 6288.1567\n",
"2 훈련 전체 손실: 26492.55 \t재구성 손실: 21714.719 \t잠재 손실: 4777.832\n",
"3 훈련 전체 손실: 27487.383 \t재구성 손실: 21461.723 \t잠재 손실: 6025.66\n",
"4 훈련 전체 손실: 25391.826 \t재구성 손실: 19977.314 \t잠재 손실: 5414.5117\n",
"5 훈련 전체 손실: 22596.055 \t재구성 손실: 18616.91 \t잠재 손실: 3979.1448\n",
"6 훈련 전체 손실: 21599.162 \t재구성 손실: 17780.654 \t잠재 손실: 3818.5076\n",
"7 훈련 전체 손실: 19658.17 \t재구성 손실: 16267.5625 \t잠재 손실: 3390.6067\n",
"8 훈련 전체 손실: 21420.445 \t재구성 손실: 17632.562 \t잠재 손실: 3787.8838\n",
"9 훈련 전체 손실: 18866.047 \t재구성 손실: 15429.076 \t잠재 손실: 3436.9712\n",
"10 훈련 전체 손실: 16396.531 \t재구성 손실: 13344.035 \t잠재 손실: 3052.4954\n",
"11 훈련 전체 손실: 16818.389 \t재구성 손실: 13674.762 \t잠재 손실: 3143.6274\n",
"12 훈련 전체 손실: 16475.625 \t재구성 손실: 13151.922 \t잠재 손실: 3323.7021\n",
"13 훈련 전체 손실: 16441.584 \t재구성 손실: 13211.978 \t잠재 손실: 3229.606\n",
"14 훈련 전체 손실: 15809.6455 \t재구성 손실: 12506.787 \t잠재 손실: 3302.8582\n",
"15 훈련 전체 손실: 16582.064 \t재구성 손실: 12987.818 \t잠재 손실: 3594.2454\n",
"16 훈련 전체 손실: 17112.182 \t재구성 손실: 13749.431 \t잠재 손실: 3362.7515\n",
"17 훈련 전체 손실: 16962.52 \t재구성 손실: 13360.187 \t잠재 손실: 3602.3337\n",
"18 훈련 전체 손실: 15885.106 \t재구성 손실: 12414.121 \t잠재 손실: 3470.985\n",
"19 훈련 전체 손실: 15645.737 \t재구성 손실: 12275.276 \t잠재 손실: 3370.4607\n",
"20 훈련 전체 손실: 21472.46 \t재구성 손실: 17321.988 \t잠재 손실: 4150.472\n",
"21 훈련 전체 손실: 30887.754 \t재구성 손실: 23065.543 \t잠재 손실: 7822.21\n",
"22 훈련 전체 손실: 34106.145 \t재구성 손실: 23087.611 \t잠재 손실: 11018.534\n",
"23 훈련 전체 손실: 28455.574 \t재구성 손실: 23078.035 \t잠재 손실: 5377.539\n",
"24 훈련 전체 손실: 29275.6 \t재구성 손실: 23641.562 \t잠재 손실: 5634.0366\n",
"25 훈련 전체 손실: 27637.0 \t재구성 손실: 22232.246 \t잠재 손실: 5404.7534\n",
"26 훈련 전체 손실: 32224.32 \t재구성 손실: 22636.662 \t잠재 손실: 9587.659\n",
"27 훈련 전체 손실: 21313.816 \t재구성 손실: 17978.727 \t잠재 손실: 3335.0898\n",
"28 훈련 전체 손실: 22745.164 \t재구성 손실: 18077.477 \t잠재 손실: 4667.6875\n",
"29 훈련 전체 손실: 24317.865 \t재구성 손실: 19554.348 \t잠재 손실: 4763.518\n",
"30 훈련 전체 손실: 22403.871 \t재구성 손실: 18023.01 \t잠재 손실: 4380.8604\n",
"31 훈련 전체 손실: 27779.889 \t재구성 손실: 19985.334 \t잠재 손실: 7794.5547\n",
"32 훈련 전체 손실: 21062.633 \t재구성 손실: 17759.936 \t잠재 손실: 3302.6963\n",
"33 훈련 전체 손실: 27471.139 \t재구성 손실: 21755.688 \t잠재 손실: 5715.451\n",
"34 훈련 전체 손실: 21868.11 \t재구성 손실: 17975.395 \t잠재 손실: 3892.7153\n",
"35 훈련 전체 손실: 23293.21 \t재구성 손실: 18515.408 \t잠재 손실: 4777.802\n",
"36 훈련 전체 손실: 24222.096 \t재구성 손실: 17747.406 \t잠재 손실: 6474.6895\n",
"37 훈련 전체 손실: 27664.906 \t재구성 손실: 20372.93 \t잠재 손실: 7291.976\n",
"38 훈련 전체 손실: 23926.232 \t재구성 손실: 19888.672 \t잠재 손실: 4037.5613\n",
"39 훈련 전체 손실: 21193.496 \t재구성 손실: 16443.598 \t잠재 손실: 4749.8975\n",
"40 훈련 전체 손실: 25521.975 \t재구성 손실: 20088.113 \t잠재 손실: 5433.8613\n",
"41 훈련 전체 손실: 39825.066 \t재구성 손실: 23289.588 \t잠재 손실: 16535.479\n",
"42 훈련 전체 손실: 24308.13 \t재구성 손실: 19179.758 \t잠재 손실: 5128.373\n",
"43 훈련 전체 손실: 25884.607 \t재구성 손실: 20003.258 \t잠재 손실: 5881.3496\n",
"44 훈련 전체 손실: 29764.18 \t재구성 손실: 22110.586 \t잠재 손실: 7653.594\n",
"45 훈련 전체 손실: 21576.438 \t재구성 손실: 16846.219 \t잠재 손실: 4730.2197\n",
"46 훈련 전체 손실: 19421.508 \t재구성 손실: 15778.951 \t잠재 손실: 3642.557\n",
"47 훈련 전체 손실: 17019.273 \t재구성 손실: 13826.726 \t잠재 손실: 3192.547\n",
"48 훈련 전체 손실: 16891.82 \t재구성 손실: 13830.799 \t잠재 손실: 3061.022\n",
"49 훈련 전체 손실: 17236.168 \t재구성 손실: 13861.413 \t잠재 손실: 3374.755\n"
]
}
],
"source": [
"n_epochs = 50\n",
"batch_size = 150\n",
"\n",
"with tf.Session() as sess:\n",
" init.run()\n",
" for epoch in range(n_epochs):\n",
" n_batches = len(X_train) // batch_size\n",
" for iteration in range(n_batches):\n",
" print(\"\\r{}%\".format(100 * iteration // n_batches), end=\"\")\n",
" sys.stdout.flush()\n",
" X_batch, y_batch = next(shuffle_batch(X_train, y_train, batch_size))\n",
" sess.run(training_op, feed_dict={X: X_batch})\n",
" loss_val, reconstruction_loss_val, latent_loss_val = sess.run([loss, reconstruction_loss, latent_loss], feed_dict={X: X_batch})\n",
" print(\"\\r{}\".format(epoch), \"훈련 전체 손실:\", loss_val, \"\\t재구성 손실:\", reconstruction_loss_val, \"\\t잠재 손실:\", latent_loss_val)\n",
" saver.save(sess, \"./my_model_variational.ckpt\")"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [],
"source": [
"reset_graph()\n",
"\n",
"from functools import partial\n",
"\n",
"n_inputs = 28 * 28\n",
"n_hidden1 = 500\n",
"n_hidden2 = 500\n",
"n_hidden3 = 20 # 코딩 유닛\n",
"n_hidden4 = n_hidden2\n",
"n_hidden5 = n_hidden1\n",
"n_outputs = n_inputs\n",
"learning_rate = 0.001\n",
"\n",
"initializer = tf.variance_scaling_initializer()\n",
"my_dense_layer = partial(\n",
" tf.layers.dense,\n",
" activation=tf.nn.elu,\n",
" kernel_initializer=initializer)\n",
"\n",
"X = tf.placeholder(tf.float32, [None, n_inputs])\n",
"hidden1 = my_dense_layer(X, n_hidden1)\n",
"hidden2 = my_dense_layer(hidden1, n_hidden2)\n",
"hidden3_mean = my_dense_layer(hidden2, n_hidden3, activation=None)\n",
"hidden3_gamma = my_dense_layer(hidden2, n_hidden3, activation=None)\n",
"noise = tf.random_normal(tf.shape(hidden3_gamma), dtype=tf.float32)\n",
"hidden3 = hidden3_mean + tf.exp(0.5 * hidden3_gamma) * noise\n",
"hidden4 = my_dense_layer(hidden3, n_hidden4)\n",
"hidden5 = my_dense_layer(hidden4, n_hidden5)\n",
"logits = my_dense_layer(hidden5, n_outputs, activation=None)\n",
"outputs = tf.sigmoid(logits)\n",
"\n",
"xentropy = tf.nn.sigmoid_cross_entropy_with_logits(labels=X, logits=logits)\n",
"reconstruction_loss = tf.reduce_sum(xentropy)\n",
"latent_loss = 0.5 * tf.reduce_sum(\n",
" tf.exp(hidden3_gamma) + tf.square(hidden3_mean) - 1 - hidden3_gamma)\n",
"loss = reconstruction_loss + latent_loss\n",
"\n",
"optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)\n",
"training_op = optimizer.minimize(loss)\n",
"\n",
"init = tf.global_variables_initializer()\n",
"saver = tf.train.Saver()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 숫자 이미지 생성"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"모델을 훈련시켜 랜덤한 이미지를 생성해 보겠습니다:"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 훈련 전체 손실: 18218.76 \t재구성 손실: 14676.055 \t잠재 손실: 3542.7048\n",
"1 훈련 전체 손실: 16157.965 \t재구성 손실: 12554.926 \t잠재 손실: 3603.039\n",
"2 훈련 전체 손실: 16807.945 \t재구성 손실: 13107.26 \t잠재 손실: 3700.6846\n",
"3 훈련 전체 손실: 16130.707 \t재구성 손실: 12394.524 \t잠재 손실: 3736.1821\n",
"4 훈련 전체 손실: 16167.954 \t재구성 손실: 12363.075 \t잠재 손실: 3804.8787\n",
"5 훈련 전체 손실: 15852.156 \t재구성 손실: 12208.578 \t잠재 손실: 3643.5786\n",
"6 훈련 전체 손실: 15705.334 \t재구성 손실: 12007.691 \t잠재 손실: 3697.642\n",
"7 훈련 전체 손실: 15155.031 \t재구성 손실: 11477.658 \t잠재 손실: 3677.3735\n",
"8 훈련 전체 손실: 15498.601 \t재구성 손실: 11717.781 \t잠재 손실: 3780.8193\n",
"9 훈련 전체 손실: 15686.549 \t재구성 손실: 11837.156 \t잠재 손실: 3849.3926\n",
"10 훈련 전체 손실: 14910.417 \t재구성 손실: 11226.355 \t잠재 손실: 3684.0615\n",
"11 훈련 전체 손실: 15763.072 \t재구성 손실: 11938.736 \t잠재 손실: 3824.3362\n",
"12 훈련 전체 손실: 15509.399 \t재구성 손실: 11676.887 \t잠재 손실: 3832.513\n",
"13 훈련 전체 손실: 15698.921 \t재구성 손실: 11909.219 \t잠재 손실: 3789.7024\n",
"14 훈련 전체 손실: 15117.068 \t재구성 손실: 11384.899 \t잠재 손실: 3732.169\n",
"15 훈련 전체 손실: 15423.752 \t재구성 손실: 11687.385 \t잠재 손실: 3736.3667\n",
"16 훈련 전체 손실: 15189.444 \t재구성 손실: 11464.85 \t잠재 손실: 3724.5947\n",
"17 훈련 전체 손실: 15577.088 \t재구성 손실: 11821.83 \t잠재 손실: 3755.258\n",
"18 훈련 전체 손실: 14807.34 \t재구성 손실: 11136.354 \t잠재 손실: 3670.9858\n",
"19 훈련 전체 손실: 14838.291 \t재구성 손실: 11174.918 \t잠재 손실: 3663.3726\n",
"20 훈련 전체 손실: 15333.88 \t재구성 손실: 11513.043 \t잠재 손실: 3820.837\n",
"21 훈련 전체 손실: 15382.906 \t재구성 손실: 11651.821 \t잠재 손실: 3731.0847\n",
"22 훈련 전체 손실: 15237.957 \t재구성 손실: 11471.176 \t잠재 손실: 3766.7817\n",
"23 훈련 전체 손실: 15370.038 \t재구성 손실: 11551.192 \t잠재 손실: 3818.8457\n",
"24 훈련 전체 손실: 15608.235 \t재구성 손실: 11782.35 \t잠재 손실: 3825.8857\n",
"25 훈련 전체 손실: 15079.079 \t재구성 손실: 11408.744 \t잠재 손실: 3670.335\n",
"26 훈련 전체 손실: 15034.0 \t재구성 손실: 11326.258 \t잠재 손실: 3707.7424\n",
"27 훈련 전체 손실: 15015.447 \t재구성 손실: 11293.295 \t잠재 손실: 3722.1528\n",
"28 훈련 전체 손실: 15138.809 \t재구성 손실: 11427.032 \t잠재 손실: 3711.7769\n",
"29 훈련 전체 손실: 15141.48 \t재구성 손실: 11504.628 \t잠재 손실: 3636.8525\n",
"30 훈련 전체 손실: 14788.049 \t재구성 손실: 11041.8955 \t잠재 손실: 3746.1528\n",
"31 훈련 전체 손실: 14709.729 \t재구성 손실: 11039.059 \t잠재 손실: 3670.6694\n",
"32 훈련 전체 손실: 14682.857 \t재구성 손실: 10992.444 \t잠재 손실: 3690.4136\n",
"33 훈련 전체 손실: 15009.77 \t재구성 손실: 11297.744 \t잠재 손실: 3712.0254\n",
"34 훈련 전체 손실: 14526.937 \t재구성 손실: 10948.571 \t잠재 손실: 3578.3652\n",
"35 훈련 전체 손실: 14206.965 \t재구성 손실: 10654.1875 \t잠재 손실: 3552.777\n",
"36 훈련 전체 손실: 14849.254 \t재구성 손실: 11131.516 \t잠재 손실: 3717.7388\n",
"37 훈련 전체 손실: 14679.506 \t재구성 손실: 10997.404 \t잠재 손실: 3682.1018\n",
"38 훈련 전체 손실: 14744.93 \t재구성 손실: 11116.8545 \t잠재 손실: 3628.075\n",
"39 훈련 전체 손실: 15050.721 \t재구성 손실: 11315.764 \t잠재 손실: 3734.9575\n",
"40 훈련 전체 손실: 14831.108 \t재구성 손실: 11115.693 \t잠재 손실: 3715.4148\n",
"41 훈련 전체 손실: 14920.627 \t재구성 손실: 11216.011 \t잠재 손실: 3704.6162\n",
"42 훈련 전체 손실: 14811.677 \t재구성 손실: 11154.946 \t잠재 손실: 3656.7305\n",
"43 훈련 전체 손실: 14609.848 \t재구성 손실: 10981.436 \t잠재 손실: 3628.412\n",
"44 훈련 전체 손실: 14663.687 \t재구성 손실: 11052.582 \t잠재 손실: 3611.1047\n",
"45 훈련 전체 손실: 14979.221 \t재구성 손실: 11217.773 \t잠재 손실: 3761.4468\n",
"46 훈련 전체 손실: 15053.541 \t재구성 손실: 11416.833 \t잠재 손실: 3636.7075\n",
"47 훈련 전체 손실: 14378.854 \t재구성 손실: 10826.66 \t잠재 손실: 3552.193\n",
"48 훈련 전체 손실: 14707.507 \t재구성 손실: 11052.38 \t잠재 손실: 3655.1267\n",
"49 훈련 전체 손실: 15307.982 \t재구성 손실: 11553.088 \t잠재 손실: 3754.894\n"
]
}
],
"source": [
"import numpy as np\n",
"\n",
"n_digits = 60\n",
"n_epochs = 50\n",
"batch_size = 150\n",
"\n",
"with tf.Session() as sess:\n",
" init.run()\n",
" for epoch in range(n_epochs):\n",
" n_batches = len(X_train) // batch_size\n",
" for iteration in range(n_batches):\n",
" print(\"\\r{}%\".format(100 * iteration // n_batches), end=\"\") # not shown in the book\n",
" sys.stdout.flush() # not shown\n",
" X_batch, y_batch = next(shuffle_batch(X_train, y_train, batch_size))\n",
" sess.run(training_op, feed_dict={X: X_batch})\n",
" loss_val, reconstruction_loss_val, latent_loss_val = sess.run([loss, reconstruction_loss, latent_loss], feed_dict={X: X_batch}) # not shown\n",
" print(\"\\r{}\".format(epoch), \"훈련 전체 손실:\", loss_val, \"\\t재구성 손실:\", reconstruction_loss_val, \"\\t잠재 손실:\", latent_loss_val) # not shown\n",
" saver.save(sess, \"./my_model_variational.ckpt\") # not shown\n",
" \n",
" codings_rnd = np.random.normal(size=[n_digits, n_hidden3])\n",
" outputs_val = outputs.eval(feed_dict={hidden3: codings_rnd})"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 576x3600 with 60 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.figure(figsize=(8,50)) # 책에는 없음\n",
"for iteration in range(n_digits):\n",
" plt.subplot(n_digits, 10, iteration + 1)\n",
" plot_image(outputs_val[iteration])"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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ory8nODgYFq1agVwzvvjCHhb8ScTQG63G6fTKdcvEJ1YzwSiV5MYgz/L1ojLwel0kpeXx9atW8nMzASgffv2mM3m82Ifi9pzok2JxWIhMTERs9ks56u51lG0ltm9e7dsL3Hw4EH0ej1Go5HLLrsMgHbt2pGZmXm2xVGPg9gvYm3Bcya9f1ZVVUVjYyMpKSmEhYXJ9jHNvc8VReHll18G4LXXXsPhcNCtWzemTJkCQJ8+fYiPj/cpuRUo5fG8dvGJpnL9+/ensLAQONr9NSIigqqqKpxOp7QiZs+ezfXXX9+sC35shWe9Xu9DVKiqqmL27NmsWbOG9PR0wNNifeDAgWfV8t37+QDFxcXMmTMHvV7P+PHjAWjbtu05bXsNnvGJJoZGoxGj0XjcZa8oChUVFfz2229069YNgI4dO551S/UzhTfhpLa2FovFIlvDm81mOZ6zHZNQshGnRxIAACAASURBVL7++mt++eUX9u/fT2xsLADJyckMHTqUAQMGcNFFFwH4vQfV2UDMkWiEuX79er788kvA05Bv2LBhDBgwQNYWNJlMASPrqKoqXdyrVq3i73//O1u3bvVp+hceHo6qqiQnJwNw8803c9NNN9G2bVu/KQGianhRURGLFy8GPI0nRaFYcT+UlpZitVrp1asXY8aMoXfv3gDNqowoisK3337LfffdB3jce506dWLu3LlkZGTI93E4HD4emD9QNLREXQ0aNGjQcGHhvHXxqarKggULACgvLyckJIRrr72WZ555BvB079y1axdPPfUU2dnZgKffydixY5uFXi16U61cuZI5c+YAHpdN586dKSwsZMeOHYCndbndbsdms7F69WoAtm3bxmuvvUb37t2Pa33elHEA7N27lx9++IG2bdvSv39/ABISEggPDz9n2reqqhw4cEC2khg0aBCDBw8mLi7Ox4qy2WysWLGC33//XVoXaWlpx1l/IhYZKLeRcClnZ2czb9483G631Lw7dOhA7969adWqldxfTbGoXC4XlZWVAKxcuZJNmzZhs9nkdwQFBbF48WKWLl0qW6lfd911AXFLnSlEl2TwzNXevXt5//33qa2tBaBLly6Ul5eTk5PDwIEDAU9w3btnFPjHXaQoCsXFxdIttXr1ajk2YfX27NmTjIwM8vLy2LlzJ+ChUAfCMm9oaGDGjBksXbpU/iw8PJx27doRHx8P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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"n_rows = 6\n",
"n_cols = 10\n",
"plot_multiple_images(outputs_val.reshape(-1, 28, 28), n_rows, n_cols)\n",
"save_fig(\"generated_digits_plot\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"여기에서 잠재 변수 손실은 조금 다르게 계산된 점을 주목하세요:"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [],
"source": [
"latent_loss = 0.5 * tf.reduce_sum(\n",
" tf.exp(hidden3_gamma) + tf.square(hidden3_mean) - 1 - hidden3_gamma)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 인코드 & 디코드"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"인코드:"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO:tensorflow:Restoring parameters from ./my_model_variational.ckpt\n"
]
}
],
"source": [
"n_digits = 3\n",
"# X_test, y_test = mnist.test.next_batch(batch_size)\n",
"X_test_batch, y_test_batch = next(shuffle_batch(X_test, y_test, batch_size))\n",
"codings = hidden3\n",
"\n",
"with tf.Session() as sess:\n",
" saver.restore(sess, \"./my_model_variational.ckpt\")\n",
" codings_val = codings.eval(feed_dict={X: X_test_batch})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"디코드:"
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO:tensorflow:Restoring parameters from ./my_model_variational.ckpt\n"
]
}
],
"source": [
"with tf.Session() as sess:\n",
" saver.restore(sess, \"./my_model_variational.ckpt\")\n",
" outputs_val = outputs.eval(feed_dict={codings: codings_val})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"재구성 이미지를 그려봅니다:"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 576x540 with 6 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig = plt.figure(figsize=(8, 2.5 * n_digits))\n",
"for iteration in range(n_digits):\n",
" plt.subplot(n_digits, 2, 1 + 2 * iteration)\n",
" plot_image(X_test_batch[iteration])\n",
" plt.subplot(n_digits, 2, 2 + 2 * iteration)\n",
" plot_image(outputs_val[iteration])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 숫자 이미지 보간"
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO:tensorflow:Restoring parameters from ./my_model_variational.ckpt\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 792x324 with 6 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAowAAAB8CAYAAADjPuHmAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAGBpJREFUeJzt3XnwXfP9x/FPtLba1xJELUkQEhKCsY/BWGLE0Kl1LDWWtjPoFGPfBdGZWtpaZpjWvoyqttYREUtC1J5IGhUhtCLEEiFp+f3z8/Y8p/d83OS73O35+OtFvvd87/d87jn3M+f9Wfp8/fXXSZIkSaqyWKPfgCRJkpqbHUZJkiRl2WGUJElSlh1GSZIkZdlhlCRJUpYdRkmSJGXZYZQkSVKWHUZJkiRl2WGUJElS1vcb8DvdWqZn9emm49hOPas72sk26lm2UfOzjZqfbdT86mojnzBKkiQpyw6jJEmSsuwwSpIkKcsOoyRJkrLsMEqSJCmrEbOkJbWZr776KnKfPn1qZjXW11/XnmjK/z9v3rzISy+9dGTbVJJPGCVJkpRlh1GSJElZlqTVUlg+szTWu1h2/vLLLwv/9tlnn0VecsklI//gBz+I/P3ve7vpTWyvlFJasGBB5NmzZ0eeOHFiZLbj5MmTI++zzz6Rhw8fXjiu12Hj/Oc//4k8f/78yOXrk9fh4osvHnmxxXxmpPr5aZEkSVKWHUZJkiRl2WGUJElSVp+qpRZ6kJuI96zuGlDUsHYqfyY/+eSTyC+99FLkFVZYITLH5ay99tqRl1122chNNl6nO9qpV9uIS648/vjjhX+79dZbI/ft2zfyqaeeGpltwfGMjW6XzLjYlmujHI5pZFt+8cUXkf/2t79FvuaaayLzvNx+++2F46677rrd+j4XUlu1EfFzWbX00S233BL56quvjvzGG28UjrXDDjtEHjVqVORNNtkk8hJLLNHFd1ypbduojdTVRk31DSpJkqTmY4dRkiRJWW25zgUf3//3v/+NzNJLSil9/vnnkVly4bIgfEzPMtr3vve9mq/VomGbffjhh4V/O+eccyJzCRC2Acttu+66a+RjjjkmMkvV5derNp7Xjz/+OPKNN95Y+Lmnnnoq8kYbbRT55Zdfjjx06NDI3EWEbV8uT/fGtdUp1y//Tp5/3tfWXHPNyO+//37kOXPmRL7yyisLxx09enTN36GFx2uBS+Z8+umnke++++7IF110UeS333675nFSSun555+P/Morr0TeeOONa77GdlQtPmGUJElSlh1GSZIkZbV0Sbqq9PzRRx9F/u1vfxuZMwBTKq6Gz1IYy3DLLLNMZM40O+WUUyKvtNJKheP6OH/hcZeCcePGFf7thRdeiPzWW29FZvuznThD8JFHHom83377FY67yiqrRLbNauM5/uc//xl52rRphZ9jeZ8l6eWWW67mcXmNMZdL0iyX2kZdw/PHzBUG1l9//cg/+tGPIvO622mnnXroHXaecumY90EO57jjjjsijx8/PjK/93itlI/L++NSSy1V8zVeXwuvaiY7hxNw9yS2F9shpeJuPLwPNlO7+IRRkiRJWXYYJUmSlNXSJekFCxZE/s1vfhP5qquuijxr1qzI5VmxK6+8cs3MhaKnT58eefLkyZGnTJkSmYunplR8tKxqfDw/c+bMyM8880zh59g2nMHO0me/fv0iz549O/KYMWMicxZhSin96le/isySTTOVABqNpZUnn3wyModzpJTSoEGDIm+66aaRl19++ZrH5YoFc+fOjcyVC1JKabXVVovMNurOVQqcHfotlsI4M5eL5A8ZMqTwmk4/Z11RLh3zO+3hhx+OzA0LVl111chrrLFG5LFjx0bmdZtS8V7J9mv0ovmNxvPPoTFcFWDChAmF13Bo24svvhiZqwrwPsZj8TuPGxmklNKIESMiX3jhhZFXX331yBxC0Aid/WmRJEnSd7LDKEmSpKyWK0nzkS5Lz5dccklklrtYxirPkj366KMjs4zMxaF53BkzZkR+8MEHI3Mh1ZRSOuywwyJbrqnGEsCbb74ZubxwN2ducqb6zjvvHJllzfvuuy/yzTffHPmBBx4oHJefJS4O7szBb1UtfP/DH/6w8HMDBgyIvMUWW0Rea621IvNcstx53XXXRS7vgcvj/uQnP4nMRdg5y7eqxFYu/fG98G/ksTrRv//978gcjsNrtVzu1KIr31841IL3Om4gwWEaTzzxRGTeA8v7Qg8bNiwyy9ideH9j2X/SpEmRuSD9n//858gsKadUvF9QPd8bVau5pFTco/1f//pXZC7OPnjw4MiN2HjCJ4ySJEnKssMoSZKkrJYoSbOcxD1r+aiWj5k5q4gLd3OP4ZSK5Sf+jv79+0dmeZRly3nz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b73C61vl/lY1/pz3FN632Ka5XaKq8Lzed999kXmvKo/n33bbbSNzHHhv7eJSD58wSpIkKcsOoyRJkrJauiRNfGzLKfEssfARf0rFx74sN44YMaLm66dNmxb51ltvjcxSXUopzZ8/PzJLFFzGh++xHfFxO0vB3Ph98803j7zLLrtELpcPWULgueVm77/4xS8ic0N4lg+4PEFKKe22226RBwwYEJklGJZyWr3UXC+W0rjEFJeEKC+rw+VseM65PAd3Vfjggw8is+z/9NNPF4571FFHRWb5iOef11LVki1VwxpS+t/SbSuoWgKFZeTy0l/cXYf/xvPEc1G1RFFXtdu1w/N0++23R2aJmN89a665ZmQO0yjbYIMNIh9wwAGRuVwPl0ficjHnnHNO4VhVw2z43vmZ6t+/f833Xl5qqdXbku+/ahexnHqWjHv00UcjVw1LSymln/70p5G7svNYT/IJoyRJkrLsMEqSJCmrbUrSxEfL3BC8PFOMq7GzDMlH9nw0zU3H+Th53LhxheOyXMeZ2JwhzF1nmumRc3dhqeOyyy6L/PDDD0d+8sknI7MMvc466xSOxTLbAw88EPnee++N/P7770dmaYCz588+++zCcY899tjI9cxab2c8Zyx5cUcWlqpnzJhReP2hhx4amaXjl156KTKHJrBszfLLMcccUzguh43wuuzONuJseQ5NaGZVu9vcddddkSdOnFh4DUtjPP8s6bNcyhInz72qscTMFRq4mxG/BzbddNPC69mW/O4YP358zddz1i3bl9dgSsXVBrgTGu973GmE/78T277e+wt/jrOpORyBQ6f48+Xvua233nqhf39v8wmjJEmSsuwwSpIkKastnzWz9MwZXixPp1Q9o7Lq/7N0xoWeBw4cWDguZy1ys3aWGPg4uh1n37LkxfIlZ8fy3Jx77rmRuYBqSsUFZTlTneUYzoDefvvtI7McXm6n7pz52U6GDRsWeauttorMkhc/4yml9MILL0TmTPaqmYNrrLFG5AsuuCDyEUccUfi53iiHcUZoq6halJwl0SlTphRewxmaLEMfeOCBkS+66KLILF22y32pJ/DccNMH/v8JEyZEZomyXDrmEBqWnnnfrPpO4j0wd1wOxaoa5mF7LzzeEy+99NLIc+fOjcy+CTcYSel/V/FoRn5jSpIkKcsOoyRJkrLasiRdtRhnDmc4Ve0VyeOyvM2yXfn1nL3LGadDhw6NzLJAVQmv/PubHWfZcabrq6++GnnOnDmROauMs3FTKp4f7sPKhbePO+64yFykttNnP9eL54blq2uvvTYy93weO3Zs4fUsQ3NIwdprrx15yJAhkVl65u9rxDCBqiEozYzvkyXGkSNHRn722WcLr2Eb7bXXXpHPO++8yNzAwCEb9eGQAO4Fze+IK664IvKkSZMil/e3Z1mTM9Y5tGrjjTeOzHvdzjvvHLk8+5rtWrUZgRYe+w33339/zcyf4eoo3CAkpda43pr/HUqSJKmh7DBKkiQpq0+uBNpDev0XVqnaB7KqRFVVtubC0ikV9xN97rnnIrN0wfLcCSecEJkzpcrlgjrLB91VY+hSO/Eccg9izhDkzEHusz148ODCsQYNGhSZJemq/TZbpMzSHW+yx68ltiM/8+VhGyynVLVFvXs7N5GWaKPCL0N7cRWBlIrlTl47Lb5Ic9O2UdX3Bdth1qxZhdewXMyhBsxsu6r9j8vXV4PviU3bRouiah93bl7AkjR/nsOo2E9IKaXlllsucgPaq65f2BJ3bUmSJDWOHUZJkiRltVz9oTvV89i3qozGzDJpSsU9ijkr6qGHHorMfZRZEtp7770jt8q+trXwvPFR+3bbbVczqzmxHVmubMHSZUeomj1d67/Vs6q+L3i/571RrYeL4XNjDuIws9133z0yF9lPqeHDBuriE0ZJkiRl2WGUJElSlh1GSZIkZTkQ6f/VsyxL1f8vL2GwwgorRD7ooIMiL7/88pHnzZsXmbu+cNeL8pJHrTDGQZKkTsDxqFz+bcGCBZHXWmutyPvuu2/kri4tVrUUYE8uWeYTRkmSJGXZYZQkSVJWR+/00qaaYqcXfae22v2gTdlGzc82an5t20bczYc7K5V3WfoGh6U12W5X7vQiSZKkrrPDKEmSpCxL0u3HknRraNsyTRuxjZqfbdT8bKPmZ0lakiRJXWeHUZIkSVmNKElLkiSphfiEUZIkSVl2GCVJkpRlh1GSJElZdhglSZKUZYdRkiRJWXYYJUmSlGWHUZIkSVl2GCVJkpRlh1GSJElZdhglSZKUZYdRkiRJWXYYJUmSlGWHUZIkSVl2GCVJkpRlh1GSJElZdhglSZKUZYdRkiRJWXYYJUmSlGWHUZIkSVl2GCVJkpRlh1GSJElZdhglSZKUZYdRkiRJWXYYJUmSlGWHUZIkSVn/BzmS+jptjB1uAAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 792x324 with 6 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 792x324 with 6 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAowAAAB8CAYAAADjPuHmAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAFhBJREFUeJzt3XmwjvX/x/FP2ze7SAg5Torsh4Y0kphMjTqlUjNaiJpKUWqYTDMxU4qoNCq0TFO0GIkkMYhhorKTJYTs+5ZOpO33V+9en2vu6/M7znovz8dfL9zXfY7rc1/X/Znr/VnO+ueffxwAAAAQ5+zS/gUAAACQ3OgwAgAAIIgOIwAAAILoMAIAACCIDiMAAACC6DACAAAgiA4jAAAAgugwAgAAIIgOIwAAAILOLYWfydYyxeusInof2ql4FUU70UbFizZKfrRR8qONkl++2ognjAAAAAiiwwgAAIAgOowAAAAIosMIAACAIDqMAAAACCqNWdIA0szp06ctn3XWfxPuzjnnnISvKVOmTMn8YigS//zz3yRVbV8AmYMnjAAAAAiiwwgAAICgjC5Ja5nljz/+sBxXcjn33HP/39cAmeCvv/7y/rx69WrL69evt6zX2OWXX265atWqCf9erzEUH22XuHzkyBHLq1atsjxjxgzvvXJzcy136NDBMm0JpBeeMAIAACCIDiMAAACC6DACAAAgKKMGmej4HOecO3r0qOUhQ4ZY3rVrl+UKFSpYHjRokOWGDRtaZqwOMk10DG+zZs0s63jg3bt3Wx4/frzl2rVrW37ggQcs16pVK/hzUDTizquOTT1w4IBlbaO9e/d6xxw/ftxyu3btLHNfBNILTxgBAAAQRIcRAAAAQWlfM9Ay9KlTp7x/mzx5suUFCxZYPnjwoOWTJ09aXrt2reVx48ZZbt26tfe+Z59NP/xM/f3335b1nDvnl8YqVqxouWzZspb1nJ933nmWdaeRqOIqd2bCrhjR/5ee85ycHMvaLidOnLC8ZMmShK+vXr167PuieGhbav7xxx8t6/CdaNvrtQsgfdGzAQAAQBAdRgAAAASlfUlaRUsn2dnZlrOysizrLE+lMwjnzp1rWWeIOudcuXLlCvV7ZiIdLjBt2jTv31asWGFZz62ed511W61aNcta4tQStnN+uVrLyHFDCvLzGuf8z0m67g4U/b/ouSxTpoxlbaOOHTta/uabbyzrTi+hIQQofvrZ3bZtW8LXRGeyd+/e3TLtVzyiK3z8S7+rdCjPzz//7L2uUqVKli+88ELL5cuXt5yJbafnVfsHeXl5ljds2OAds3HjRst79uyxrEPZ9u3bZ7l+/fqWn3jiCctVqlTx3jcVhrIl/28IAACAUkWHEQAAAEFpX5LWR87Rx/r6qLhHjx6W9dGwPo7WvHnzZstbtmzx3rdp06aW06kMWdR+//13y6NGjbI8ZswY73Va1q1Zs6blmTNnWq5Ro4ZlLc1omUWPdc6fgatlBp2J3aRJE8v6GdHhDNGZvJm+YHHcjPU6depY/u233yzHzdJF6Yorken14ZxzLVu2tJyJZc0zpaVPvQc6528asWjRIsvr16+3rAunf/3115Z/+eUXy6dPn479+VqGvu666yy//fbblnVYTzpck/rdr6s16PCnVatWWZ4zZ45l3XzAOb/9dAjHn3/+mfDn6ffB0qVLLesqLc757ZKseMIIAACAIDqMAAAACMqo2lm0XHLBBRdY7tChg2WdTdugQQPLWracP3++5Ysuush732HDhlnO9PJklD7OX7x4seVXX33V8q+//uodU69ePct169a1rOdW31cXGd65c6dlLQc458/M1tKQlmDWrVtnWUtBvXr1sqwlOeeYeRg3o1MdO3bMspaFBgwY4L0uE89fadK2e//99y3rrNErrrjCO6Zq1aqWU2GmZ0nREqUOwdDz+tFHH3nH6PAmPUbFrcKgwz+i7aD3Om1L3bBi8ODBlnWIkK56kEr0PO3YscPyLbfcYnn79u2Wdday5k6dOnnvq8Of4ixbtszymjVrLC9cuNCyfv8559z1119vOVmHAXB1AwAAIIgOIwAAAIIyql4afcwbV9LUR9n6yP6rr76yfPz4cctannbOn62mj7aT9TFzSdLS78iRIy0fOXLEcps2bbxjRo8ebTlukWddZPj111+3rOVpLYM655dwdHjCNddcY1lLz7oItZZpKlSo4L2vlqIynZY4dTHhTZs2WdaFhKOzRlkEv2RpmUyHY6i77rrL+3OmD7vRz7h+focOHWp56tSplvU6iH4n6J/1ntSoUSPLugqH3isvu+wyyzoUxznnPvnkE8v6naZl75UrV1rWVUB0CEIq7e2uM8X79+9vWfdI/9///mf5pptusjx8+HDL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\n",
"text/plain": [
"<Figure size 792x324 with 6 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"n_iterations = 3\n",
"n_digits = 6\n",
"codings_rnd = np.random.normal(size=[n_digits, n_hidden3])\n",
"\n",
"with tf.Session() as sess:\n",
" saver.restore(sess, \"./my_model_variational.ckpt\")\n",
" target_codings = np.roll(codings_rnd, -1, axis=0)\n",
" for iteration in range(n_iterations + 1):\n",
" codings_interpolate = codings_rnd + (target_codings - codings_rnd) * iteration / n_iterations\n",
" outputs_val = outputs.eval(feed_dict={codings: codings_interpolate})\n",
" plt.figure(figsize=(11, 1.5*n_iterations))\n",
" for digit_index in range(n_digits):\n",
" plt.subplot(1, n_digits, digit_index + 1)\n",
" plot_image(outputs_val[digit_index])\n",
" plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"# 연습문제 해답"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Coming soon..."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"nav_menu": {
"height": "381px",
"width": "453px"
},
"toc": {
"navigate_menu": true,
"number_sections": true,
"sideBar": true,
"threshold": 6,
"toc_cell": false,
"toc_section_display": "block",
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 1
}