mirror of
https://github.com/fchollet/deep-learning-with-python-notebooks.git
synced 2021-07-27 01:28:40 +03:00
452 lines
14 KiB
Plaintext
452 lines
14 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Using TensorFlow backend.\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"'2.0.8'"
|
|
]
|
|
},
|
|
"execution_count": 1,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"import keras\n",
|
|
"keras.__version__"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# A first look at a neural network\n",
|
|
"\n",
|
|
"This notebook contains the code samples found in Chapter 2, Section 1 of [Deep Learning with Python](https://www.manning.com/books/deep-learning-with-python?a_aid=keras&a_bid=76564dff). Note that the original text features far more content, in particular further explanations and figures: in this notebook, you will only find source code and related comments.\n",
|
|
"\n",
|
|
"----\n",
|
|
"\n",
|
|
"We will now take a look at a first concrete example of a neural network, which makes use of the Python library Keras to learn to classify \n",
|
|
"hand-written digits. Unless you already have experience with Keras or similar libraries, you will not understand everything about this \n",
|
|
"first example right away. You probably haven't even installed Keras yet. Don't worry, that is perfectly fine. In the next chapter, we will \n",
|
|
"review each element in our example and explain them in detail. So don't worry if some steps seem arbitrary or look like magic to you! \n",
|
|
"We've got to start somewhere.\n",
|
|
"\n",
|
|
"The problem we are trying to solve here is to classify grayscale images of handwritten digits (28 pixels by 28 pixels), into their 10 \n",
|
|
"categories (0 to 9). The dataset we will use is the MNIST dataset, a classic dataset in the machine learning community, which has been \n",
|
|
"around for almost as long as the field itself and has been very intensively studied. It's a set of 60,000 training images, plus 10,000 test \n",
|
|
"images, assembled by the National Institute of Standards and Technology (the NIST in MNIST) in the 1980s. You can think of \"solving\" MNIST \n",
|
|
"as the \"Hello World\" of deep learning -- it's what you do to verify that your algorithms are working as expected. As you become a machine \n",
|
|
"learning practitioner, you will see MNIST come up over and over again, in scientific papers, blog posts, and so on."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The MNIST dataset comes pre-loaded in Keras, in the form of a set of four Numpy arrays:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"from keras.datasets import mnist\n",
|
|
"\n",
|
|
"(train_images, train_labels), (test_images, test_labels) = mnist.load_data()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"`train_images` and `train_labels` form the \"training set\", the data that the model will learn from. The model will then be tested on the \n",
|
|
"\"test set\", `test_images` and `test_labels`. Our images are encoded as Numpy arrays, and the labels are simply an array of digits, ranging \n",
|
|
"from 0 to 9. There is a one-to-one correspondence between the images and the labels.\n",
|
|
"\n",
|
|
"Let's have a look at the training data:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"(60000, 28, 28)"
|
|
]
|
|
},
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"train_images.shape"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"60000"
|
|
]
|
|
},
|
|
"execution_count": 4,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"len(train_labels)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([5, 0, 4, ..., 5, 6, 8], dtype=uint8)"
|
|
]
|
|
},
|
|
"execution_count": 5,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"train_labels"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Let's have a look at the test data:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"(10000, 28, 28)"
|
|
]
|
|
},
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"test_images.shape"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"10000"
|
|
]
|
|
},
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"len(test_labels)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([7, 2, 1, ..., 4, 5, 6], dtype=uint8)"
|
|
]
|
|
},
|
|
"execution_count": 8,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"test_labels"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Our workflow will be as follow: first we will present our neural network with the training data, `train_images` and `train_labels`. The \n",
|
|
"network will then learn to associate images and labels. Finally, we will ask the network to produce predictions for `test_images`, and we \n",
|
|
"will verify if these predictions match the labels from `test_labels`.\n",
|
|
"\n",
|
|
"Let's build our network -- again, remember that you aren't supposed to understand everything about this example just yet."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"from keras import models\n",
|
|
"from keras import layers\n",
|
|
"\n",
|
|
"network = models.Sequential()\n",
|
|
"network.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))\n",
|
|
"network.add(layers.Dense(10, activation='softmax'))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n",
|
|
"The core building block of neural networks is the \"layer\", a data-processing module which you can conceive as a \"filter\" for data. Some \n",
|
|
"data comes in, and comes out in a more useful form. Precisely, layers extract _representations_ out of the data fed into them -- hopefully \n",
|
|
"representations that are more meaningful for the problem at hand. Most of deep learning really consists of chaining together simple layers \n",
|
|
"which will implement a form of progressive \"data distillation\". A deep learning model is like a sieve for data processing, made of a \n",
|
|
"succession of increasingly refined data filters -- the \"layers\".\n",
|
|
"\n",
|
|
"Here our network consists of a sequence of two `Dense` layers, which are densely-connected (also called \"fully-connected\") neural layers. \n",
|
|
"The second (and last) layer is a 10-way \"softmax\" layer, which means it will return an array of 10 probability scores (summing to 1). Each \n",
|
|
"score will be the probability that the current digit image belongs to one of our 10 digit classes.\n",
|
|
"\n",
|
|
"To make our network ready for training, we need to pick three more things, as part of \"compilation\" step:\n",
|
|
"\n",
|
|
"* A loss function: the is how the network will be able to measure how good a job it is doing on its training data, and thus how it will be \n",
|
|
"able to steer itself in the right direction.\n",
|
|
"* An optimizer: this is the mechanism through which the network will update itself based on the data it sees and its loss function.\n",
|
|
"* Metrics to monitor during training and testing. Here we will only care about accuracy (the fraction of the images that were correctly \n",
|
|
"classified).\n",
|
|
"\n",
|
|
"The exact purpose of the loss function and the optimizer will be made clear throughout the next two chapters."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"network.compile(optimizer='rmsprop',\n",
|
|
" loss='categorical_crossentropy',\n",
|
|
" metrics=['accuracy'])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n",
|
|
"Before training, we will preprocess our data by reshaping it into the shape that the network expects, and scaling it so that all values are in \n",
|
|
"the `[0, 1]` interval. Previously, our training images for instance were stored in an array of shape `(60000, 28, 28)` of type `uint8` with \n",
|
|
"values in the `[0, 255]` interval. We transform it into a `float32` array of shape `(60000, 28 * 28)` with values between 0 and 1."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"train_images = train_images.reshape((60000, 28 * 28))\n",
|
|
"train_images = train_images.astype('float32') / 255\n",
|
|
"\n",
|
|
"test_images = test_images.reshape((10000, 28 * 28))\n",
|
|
"test_images = test_images.astype('float32') / 255"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"We also need to categorically encode the labels, a step which we explain in chapter 3:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 12,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"from keras.utils import to_categorical\n",
|
|
"\n",
|
|
"train_labels = to_categorical(train_labels)\n",
|
|
"test_labels = to_categorical(test_labels)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"We are now ready to train our network, which in Keras is done via a call to the `fit` method of the network: \n",
|
|
"we \"fit\" the model to its training data."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 13,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 1/5\n",
|
|
"60000/60000 [==============================] - 2s - loss: 0.2577 - acc: 0.9245 \n",
|
|
"Epoch 2/5\n",
|
|
"60000/60000 [==============================] - 1s - loss: 0.1042 - acc: 0.9690 \n",
|
|
"Epoch 3/5\n",
|
|
"60000/60000 [==============================] - 1s - loss: 0.0687 - acc: 0.9793 \n",
|
|
"Epoch 4/5\n",
|
|
"60000/60000 [==============================] - 1s - loss: 0.0508 - acc: 0.9848 \n",
|
|
"Epoch 5/5\n",
|
|
"60000/60000 [==============================] - 1s - loss: 0.0382 - acc: 0.9890 \n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"<keras.callbacks.History at 0x7fce5fed5fd0>"
|
|
]
|
|
},
|
|
"execution_count": 13,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"network.fit(train_images, train_labels, epochs=5, batch_size=128)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Two quantities are being displayed during training: the \"loss\" of the network over the training data, and the accuracy of the network over \n",
|
|
"the training data.\n",
|
|
"\n",
|
|
"We quickly reach an accuracy of 0.989 (i.e. 98.9%) on the training data. Now let's check that our model performs well on the test set too:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 14,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
" 9536/10000 [===========================>..] - ETA: 0s"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"test_loss, test_acc = network.evaluate(test_images, test_labels)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"test_acc: 0.9777\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print('test_acc:', test_acc)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n",
|
|
"Our test set accuracy turns out to be 97.8% -- that's quite a bit lower than the training set accuracy. \n",
|
|
"This gap between training accuracy and test accuracy is an example of \"overfitting\", \n",
|
|
"the fact that machine learning models tend to perform worse on new data than on their training data. \n",
|
|
"Overfitting will be a central topic in chapter 3.\n",
|
|
"\n",
|
|
"This concludes our very first example -- you just saw how we could build and a train a neural network to classify handwritten digits, in \n",
|
|
"less than 20 lines of Python code. In the next chapter, we will go in detail over every moving piece we just previewed, and clarify what is really \n",
|
|
"going on behind the scenes. You will learn about \"tensors\", the data-storing objects going into the network, about tensor operations, which \n",
|
|
"layers are made of, and about gradient descent, which allows our network to learn from its training examples."
|
|
]
|
|
}
|
|
],
|
|
"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.5.2"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|