Use tf.layers instead of tf.contrib.layers

This commit is contained in:
Aurélien Geron
2017-04-30 10:21:27 +02:00
parent 14101abcf9
commit 326d32cae0
7 changed files with 531 additions and 258 deletions

View File

@@ -402,50 +402,101 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"cell_type": "markdown",
"metadata": {
"collapsed": true
"deletable": true,
"editable": true
},
"outputs": [],
"source": [
"from six.moves import urllib\n",
"from sklearn.datasets import fetch_mldata\n",
"try:\n",
" mnist = fetch_mldata('MNIST original')\n",
"except urllib.error.HTTPError as ex:\n",
" print(\"Could not download MNIST data from mldata.org, trying alternative...\")\n",
"Note: instead of using the `fully_connected()`, `conv2d()` and `dropout()` functions from the `tensorflow.contrib.layers` module (as in the book), we now use the `dense()`, `conv2d()` and `dropout()` functions (respectively) from the `tf.layers` module, which did not exist when this chapter was written. This is preferable because anything in contrib may change or be deleted without notice, while `tf.layers` is part of the official API. As you will see, the code is mostly the same.\n",
"\n",
" # Alternative method to load MNIST, if mldata.org is down\n",
" from scipy.io import loadmat\n",
" mnist_alternative_url = \"https://github.com/amplab/datascience-sp14/raw/master/lab7/mldata/mnist-original.mat\"\n",
" mnist_path = \"./mnist-original.mat\"\n",
" response = urllib.request.urlopen(mnist_alternative_url)\n",
" with open(mnist_path, \"wb\") as f:\n",
" content = response.read()\n",
" f.write(content)\n",
" mnist_raw = loadmat(mnist_path)\n",
" mnist = {\n",
" \"data\": mnist_raw[\"data\"].T,\n",
" \"target\": mnist_raw[\"label\"][0],\n",
" \"COL_NAMES\": [\"label\", \"data\"],\n",
" \"DESCR\": \"mldata.org dataset: mnist-original\",\n",
" }\n",
" print(\"Success!\")"
"For all these functions:\n",
"* the `scope` parameter was renamed to `name`, and the `_fn` suffix was removed in all the parameters that had it (for example the `activation_fn` parameter was renamed to `activation`).\n",
"\n",
"The other main differences in `tf.layers.dense()` are:\n",
"* the `weights` parameter was renamed to `kernel` (and the weights variable is now named `\"kernel\"` rather than `\"weights\"`),\n",
"* the default activation is `None` instead of `tf.nn.relu`\n",
"\n",
"The other main differences in `tf.layers.conv2d()` are:\n",
"* the `num_outputs` parameter was renamed to `filters`,\n",
"* the `stride` parameter was renamed to `strides`,\n",
"* the default `activation` is now `None` instead of `tf.nn.relu`.\n",
"\n",
"The other main differences in `tf.layers.dropout()` are:\n",
"* it takes the dropout rate (`rate`) rather than the keep probability (`keep_prob`). Of course, `rate == 1 - keep_prob`,\n",
"* the `is_training` parameters was renamed to `training`."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": true,
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [],
"source": [
"X_train, X_test = mnist[\"data\"][:60000].astype(np.float64), mnist[\"data\"][60000:].astype(np.float64)\n",
"y_train, y_test = mnist[\"target\"][:60000].astype(np.int64), mnist[\"target\"][60000:].astype(np.int64)"
"height = 28\n",
"width = 28\n",
"channels = 1\n",
"n_inputs = height * width\n",
"\n",
"conv1_fmaps = 32\n",
"conv1_ksize = 3\n",
"conv1_stride = 1\n",
"conv1_pad = \"SAME\"\n",
"\n",
"conv2_fmaps = 64\n",
"conv2_ksize = 3\n",
"conv2_stride = 1\n",
"conv2_pad = \"SAME\"\n",
"conv2_dropout_rate = 0.25\n",
"\n",
"pool3_fmaps = conv2_fmaps\n",
"\n",
"n_fc1 = 128\n",
"fc1_dropout_rate = 0.5\n",
"\n",
"n_outputs = 10\n",
"\n",
"graph = tf.Graph()\n",
"with graph.as_default():\n",
" with tf.name_scope(\"inputs\"):\n",
" X = tf.placeholder(tf.float32, shape=[None, n_inputs], name=\"X\")\n",
" X_reshaped = tf.reshape(X, shape=[-1, height, width, channels])\n",
" y = tf.placeholder(tf.int32, shape=[None], name=\"y\")\n",
" is_training = tf.placeholder_with_default(False, shape=[], name='is_training')\n",
"\n",
" conv1 = tf.layers.conv2d(X_reshaped, filters=conv1_fmaps, kernel_size=conv1_ksize, strides=conv1_stride, padding=conv1_pad, activation=tf.nn.relu, name=\"conv1\")\n",
" conv2 = tf.layers.conv2d(conv1, filters=conv2_fmaps, kernel_size=conv2_ksize, strides=conv2_stride, padding=conv2_pad, activation=tf.nn.relu, name=\"conv2\")\n",
"\n",
" with tf.name_scope(\"pool3\"):\n",
" pool3 = tf.nn.max_pool(conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding=\"VALID\")\n",
" pool3_flat = tf.reshape(pool3, shape=[-1, pool3_fmaps * 14 * 14])\n",
" pool3_flat_drop = tf.layers.dropout(pool3_flat, conv2_dropout_rate, training=is_training)\n",
"\n",
" with tf.name_scope(\"fc1\"):\n",
" fc1 = tf.layers.dense(pool3_flat_drop, n_fc1, activation=tf.nn.relu, name=\"fc1\")\n",
" fc1_drop = tf.layers.dropout(fc1, fc1_dropout_rate, training=is_training)\n",
"\n",
" with tf.name_scope(\"output\"):\n",
" logits = tf.layers.dense(fc1, n_outputs, name=\"output\")\n",
" Y_proba = tf.nn.softmax(logits, name=\"Y_proba\")\n",
"\n",
" with tf.name_scope(\"train\"):\n",
" xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=y)\n",
" loss = tf.reduce_mean(xentropy)\n",
" optimizer = tf.train.AdamOptimizer()\n",
" training_op = optimizer.minimize(loss)\n",
"\n",
" with tf.name_scope(\"eval\"):\n",
" correct = tf.nn.in_top_k(logits, y, 1)\n",
" accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))\n",
"\n",
" with tf.name_scope(\"init_and_save\"):\n",
" init = tf.global_variables_initializer()\n",
" saver = tf.train.Saver()"
]
},
{
@@ -458,9 +509,78 @@
},
"outputs": [],
"source": [
"height, width = 28, 28\n",
"images = X_test[5000].reshape(1, height, width, 1)\n",
"plot_image(images[0, :, :, 0])"
"from tensorflow.examples.tutorials.mnist import input_data\n",
"mnist = input_data.read_data_sets(\"/tmp/data/\")"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": true,
"deletable": true,
"editable": true
},
"outputs": [],
"source": [
"def get_model_params():\n",
" gvars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES)\n",
" return {gvar.op.name: value for gvar, value in zip(gvars, tf.get_default_session().run(gvars))}\n",
"\n",
"def restore_model_params(model_params):\n",
" gvar_names = list(model_params.keys())\n",
" assign_ops = {gvar_name: tf.get_default_graph().get_operation_by_name(gvar_name + \"/Assign\")\n",
" for gvar_name in gvar_names}\n",
" init_values = {gvar_name: assign_op.inputs[1] for gvar_name, assign_op in assign_ops.items()}\n",
" feed_dict = {init_values[gvar_name]: model_params[gvar_name] for gvar_name in gvar_names}\n",
" tf.get_default_session().run(assign_ops, feed_dict=feed_dict)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [],
"source": [
"n_epochs = 1000\n",
"batch_size = 50\n",
"\n",
"best_acc_val = 0\n",
"check_interval = 100\n",
"checks_since_last_progress = 0\n",
"max_checks_without_progress = 100\n",
"best_model_params = None \n",
"\n",
"with tf.Session(graph=graph) as sess:\n",
" init.run()\n",
" for epoch in range(n_epochs):\n",
" for iteration in range(mnist.train.num_examples // batch_size):\n",
" X_batch, y_batch = mnist.train.next_batch(batch_size)\n",
" sess.run(training_op, feed_dict={X: X_batch, y: y_batch, is_training: True})\n",
" if iteration % check_interval == 0:\n",
" acc_val = accuracy.eval(feed_dict={X: mnist.test.images[:2000], y: mnist.test.labels[:2000]})\n",
" if acc_val > best_acc_val:\n",
" best_acc_val = acc_val\n",
" checks_since_last_progress = 0\n",
" best_model_params = get_model_params()\n",
" else:\n",
" checks_since_last_progress += 1\n",
" acc_train = accuracy.eval(feed_dict={X: X_batch, y: y_batch})\n",
" acc_test = accuracy.eval(feed_dict={X: mnist.test.images[2000:], y: mnist.test.labels[2000:]})\n",
" print(epoch, \"Train accuracy:\", acc_train, \"Test accuracy:\", acc_test, \"Best validation accuracy:\", best_acc_val)\n",
" if checks_since_last_progress > max_checks_without_progress:\n",
" print(\"Early stopping!\")\n",
" break\n",
"\n",
" if best_model_params:\n",
" restore_model_params(best_model_params)\n",
" acc_test = accuracy.eval(feed_dict={X: mnist.test.images[2000:], y: mnist.test.labels[2000:]})\n",
" print(\"Final accuracy on test set:\", acc_test)\n",
" save_path = saver.save(sess, \"./my_mnist_model\")"
]
},
{
@@ -475,7 +595,7 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 21,
"metadata": {
"collapsed": true,
"deletable": true,
@@ -511,7 +631,7 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": 22,
"metadata": {
"collapsed": false,
"deletable": true,
@@ -524,7 +644,7 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": 23,
"metadata": {
"collapsed": true,
"deletable": true,
@@ -544,7 +664,7 @@
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": 24,
"metadata": {
"collapsed": false,
"deletable": true,
@@ -557,7 +677,7 @@
},
{
"cell_type": "code",
"execution_count": 21,
"execution_count": 25,
"metadata": {
"collapsed": true,
"deletable": true,
@@ -572,7 +692,7 @@
},
{
"cell_type": "code",
"execution_count": 22,
"execution_count": 26,
"metadata": {
"collapsed": false,
"deletable": true,
@@ -589,7 +709,7 @@
},
{
"cell_type": "code",
"execution_count": 23,
"execution_count": 27,
"metadata": {
"collapsed": false,
"deletable": true,
@@ -611,7 +731,7 @@
},
{
"cell_type": "code",
"execution_count": 24,
"execution_count": 28,
"metadata": {
"collapsed": false,
"deletable": true,
@@ -628,7 +748,7 @@
},
{
"cell_type": "code",
"execution_count": 25,
"execution_count": 29,
"metadata": {
"collapsed": false,
"deletable": true,
@@ -641,7 +761,7 @@
},
{
"cell_type": "code",
"execution_count": 26,
"execution_count": 30,
"metadata": {
"collapsed": false,
"deletable": true,
@@ -654,7 +774,7 @@
},
{
"cell_type": "code",
"execution_count": 27,
"execution_count": 31,
"metadata": {
"collapsed": false,
"deletable": true,
@@ -717,7 +837,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2+"
"version": "3.5.3"
},
"nav_menu": {},
"toc": {