What is Numpy?

It stands for Numerical python. It is a python package which is used to perform a wide variety of mathematical operations on arrays and works faster than a regular python list.

What can we do with Numpy?

One of the easiest things to do with Numpy is to change the shape of an array

import numpy as np

a = np.array([1, 2, 3, 4, 5, 6])

print(a)

b = np.reshape(
               a,     # the array being reshaped
               (2,3)  # dimensions of the new array
              )

print(b) 

c = np.reshape(
               a,    
               (6,1)  
              )

print(c) 
[1 2 3 4 5 6]
[[1 2 3]
 [4 5 6]]
[[1]
 [2]
 [3]
 [4]
 [5]
 [6]]

Create two dimensional array.

a_list = [[1, 2, 3, 4, 5, 6], [6, 5, 4, 3, 2, 1]]
d = np.array([a_list])
d
array([[[1, 2, 3, 4, 5, 6],
        [6, 5, 4, 3, 2, 1]]])

Accessing Elements: Can find a specific index, similar to regular python lists

z1 = np.random.randint (10, size=6)

z1[0] # Find an index
8
z1[0:2] # Create an array of the specified range
array([2, 8])
z1[-1] # Get last element of the list
6

Using Numpy With Images

from skimage import io
photo = io.imread('san_diego.jpg')
type(photo)
numpy.ndarray
import matplotlib.pyplot as plt
plt.imshow(photo)

photo.shape
(549, 976, 3)

Output a mirror image

plt.imshow(photo[::-1])
<matplotlib.image.AxesImage at 0x7f8c20a3d9d0>

Find specific part of the image by putting axes into an array

plt.imshow(photo[150:400, 675:775])
<matplotlib.image.AxesImage at 0x7f8c1885d520>

Reduce the size of an image

plt.imshow(photo[::2, ::2])
<matplotlib.image.AxesImage at 0x7f8c18830f70>

Can use Numpy math functions to find values related to an image

photo
photo_sin = np.sin(photo)
photo_sin
array([[[-0.355  ,  0.8857 ,  0.9946 ],
        [-0.355  ,  0.8857 ,  0.9946 ],
        [-0.355  ,  0.8857 ,  0.9946 ],
        ...,
        [ 0.3467 , -0.9985 , -0.5063 ],
        [ 0.9766 , -0.491  ,  0.452  ],
        [ 0.9766 , -0.491  ,  0.452  ]],

       [[-0.355  ,  0.8857 ,  0.9946 ],
        [-0.355  ,  0.8857 ,  0.9946 ],
        [-0.355  ,  0.8857 ,  0.9946 ],
        ...,
        [ 0.9766 , -0.491  ,  0.452  ],
        [ 0.9766 , -0.491  ,  0.452  ],
        [ 0.9766 , -0.491  ,  0.452  ]],

       [[-0.355  ,  0.8857 ,  0.9946 ],
        [-0.355  ,  0.8857 ,  0.9946 ],
        [-0.355  ,  0.8857 ,  0.9946 ],
        ...,
        [ 0.9766 , -0.491  ,  0.452  ],
        [ 0.7085 ,  0.4678 ,  0.9946 ],
        [ 0.7085 ,  0.4678 ,  0.9946 ]],

       ...,

       [[-0.404  , -0.677  ,  0.869  ],
        [-0.1323 , -0.02655,  0.721  ],
        [ 0.9907 , -0.5586 , -0.46   ],
        ...,
        [-0.906  , -0.9663 , -0.1935 ],
        [-0.846  , -0.305  , -0.8115 ],
        [-0.906  , -0.305  , -0.7905 ]],

       [[ 0.5513 , -0.9854 ,  0.8857 ],
        [ 0.5293 , -0.3877 , -0.9424 ],
        [-0.988  ,  0.774  ,  0.6963 ],
        ...,
        [-0.846  , -0.7393 , -0.1935 ],
        [-0.751  , -0.5215 ,  0.9727 ],
        [-0.2878 , -0.5586 , -0.1935 ]],

       [[-0.751  , -0.305  ,  0.5806 ],
        [-1.     ,  0.987  ,  0.785  ],
        [-0.757  ,  0.0177 , -0.09717],
        ...,
        [-0.846  ,  0.92   , -0.93   ],
        [ 0.6504 , -0.9995 , -0.616  ],
        [-1.     ,  0.6704 , -0.46   ]]], dtype=float16)

Numpy Hacks

For your hacks, use matplotlib and numpy to slice this image to display Waldo. Also find and display one other numpy function and blog about what it is used for.

photo_a = io.imread('waldo.jpg')
type(photo_a)

plt.imshow(photo_a)
<matplotlib.image.AxesImage at 0x7f8c18782f70>

What is Pandas?

Pandas is an open source Python package which is used for data analysis and machine learning. Pandas is built using numpy which supports it using multidimensional arrays such as what is shown below:

Data can then be manipulated using pandas to do all sorts of different things such as data cleaning, statistical analysis, and data visualization. Below is an example of data visualization in a table using pandas.

import pandas as pd

pd.__version__
'1.4.2'
classes = pd.Series(["Mathematics","Chemistry","Physics","History","Geography","German"])

grades  = pd.Series([90,54,77,22,25])


pd.DataFrame({"Classes": classes, "Grades": grades})
Classes Grades
0 Mathematics 90.0
1 Chemistry 54.0
2 Physics 77.0
3 History 22.0
4 Geography 25.0
5 German NaN

What is TenserFlow?

Tensor Flow is a machine learning platform which has tools to validate and transform large datasets and also provides standard datasets for machine learning training.

An example of this is the fashion MNIST (Modified National Institute of Standards and Technology) database:

In this dataset there are many pictures which are each28x28 Numpy arrays.

Setting up

This will train a neural network model to identify pictures of clothing.
We will use tf.keras, a high-level API to build and train models in TensorFlow.

import tensorflow as tf

# Helper libraries
import numpy as np
import matplotlib.pyplot as plt

print(tf.__version__)
2.12.0

We will use the Fashion MNIST dataset which contains 70,000 grayscale images in 10 categories.
Here we will load the database.

fashion_mnist = tf.keras.datasets.fashion_mnist

(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
29515/29515 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26421880/26421880 [==============================] - 2s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
5148/5148 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4422102/4422102 [==============================] - 0s 0us/step

This dataset loads 4 NumPy arrays:
train_images and train_labels arrays are the training set, used for the models to learn
test_images and test_labels arrays test the accuracy

Each imaged is mapped to a label. The class names are not included with the dataset, store them here to use later when plotting images:

class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

Let's explore the format of the dataset before training the model. The following shows there are 60,000 images in the training set, with each image represented as 28 x 28 pixels:

train_images.shape
(60000, 28, 28)

Likewise, there are 60,000 labels in the training set:

len(train_labels)
60000

Each label is an integer between 0 and 9:

train_labels
array([9, 0, 0, ..., 3, 0, 5], dtype=uint8)

There are 10,000 images in the test set. Again, each image is represented as 28 x 28 pixels:

test_images.shape
(10000, 28, 28)

And the test set contains 10,000 images labels:

len(test_labels)
10000

Preprocessing data

The data must be preprocessed before training the network. If you inspect the first image in the training set, you will see that the pixel values fall in the range of 0 to 255:

plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()

Scale these values to a range of 0 to 1 before feeding them to the neural network model. To do so, divide the values by 255. It's important that the training set and the testing set be preprocessed in the same way:

train_images = train_images / 255.0

test_images = test_images / 255.0

To verify that the data is in the correct format and that you're ready to build and train the network, let's display the first 25 images from the training set and display the class name below each image.

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    plt.xlabel(class_names[train_labels[i]])
plt.show()

Building the neural network requires configuring the layers of the model, then compiling the model.

The basic building block of a neural network is the layer. Layers extract representations from the data fed into them. Hopefully, these representations are meaningful for the problem at hand.

Most of deep learning consists of chaining together simple layers. Most layers, such as tf.keras.layers.Dense, have parameters that are learned during training.

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10)
])

The first layer in this network, tf.keras.layers.Flatten, transforms the format of the images from a two-dimensional array (of 28 by 28 pixels) to a one-dimensional array (of 28 * 28 = 784 pixels). Think of this layer as unstacking rows of pixels in the image and lining them up. This layer has no parameters to learn; it only reformats the data.

After the pixels are flattened, the network consists of a sequence of two tf.keras.layers.Dense layers. These are densely connected, or fully connected, neural layers. The first Dense layer has 128 nodes (or neurons). The second layer returns a logits array with length of 10. Each node contains a score that indicates the current image belongs to one of the 10 classes.

Before the model is ready for training, it needs a few more settings. These are added during the model's compile step:

  • Loss function —This measures how accurate the model is during training. You want to minimize this function to "steer" the model in the right direction.
  • Optimizer —This is how the model is updated based on the data it sees and its loss function.
  • Metrics —Used to monitor the training and testing steps. The following example uses accuracy, the fraction of the images that are correctly classified.
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

Training

Training the neural network model requires the following steps:

  • Feed the training data to the model. (train_images and train_labels arrays.)
  • The model learns to associate images and labels.
  • You ask the model to make predictions about a test set (test_images array)
  • Verify that the predictions match the labels from the test_labels array.

To start training, call the model.fit method

model.fit(train_images, train_labels, epochs=10)
Epoch 1/10
2023-04-04 11:53:51.070373: W tensorflow/tsl/framework/cpu_allocator_impl.cc:83] Allocation of 188160000 exceeds 10% of free system memory.
1875/1875 [==============================] - 11s 6ms/step - loss: 0.4959 - accuracy: 0.8268
Epoch 2/10
1875/1875 [==============================] - 10s 5ms/step - loss: 0.3762 - accuracy: 0.8651
Epoch 3/10
1875/1875 [==============================] - 10s 6ms/step - loss: 0.3361 - accuracy: 0.8778
Epoch 4/10
1875/1875 [==============================] - 10s 6ms/step - loss: 0.3130 - accuracy: 0.8860
Epoch 5/10
1875/1875 [==============================] - 10s 5ms/step - loss: 0.2946 - accuracy: 0.8903
Epoch 6/10
1875/1875 [==============================] - 10s 5ms/step - loss: 0.2816 - accuracy: 0.8958
Epoch 7/10
1875/1875 [==============================] - 10s 5ms/step - loss: 0.2679 - accuracy: 0.9011
Epoch 8/10
1875/1875 [==============================] - 10s 5ms/step - loss: 0.2578 - accuracy: 0.9027
Epoch 9/10
1875/1875 [==============================] - 10s 5ms/step - loss: 0.2494 - accuracy: 0.9062
Epoch 10/10
1875/1875 [==============================] - 11s 6ms/step - loss: 0.2393 - accuracy: 0.9107
<keras.callbacks.History at 0x7f41ac3327f0>

As the model trains, the loss and accuracy metrics are displayed. This model reaches an accuracy of about 0.91 (or 91%) on the training data.

Next, compare how the model performs on the test dataset:

test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)

print('\nTest accuracy:', test_acc)
313/313 - 1s - loss: 0.3225 - accuracy: 0.8908 - 1s/epoch - 3ms/step

Test accuracy: 0.8907999992370605

It turns out that the accuracy on the test dataset is a little less than the accuracy on the training dataset. This gap between training accuracy and test accuracy represents overfitting. Overfitting is when a machine learning model performs worse on new, previouly unseen inputs than on the training data.

Predicting Images

With the model trained, you can use it to make predictions about some images. Attach a softmax layer to convert the model's linear outputs (logits) to probabilities, which should be easier to interpret.

probability_model = tf.keras.Sequential([model, 
                                         tf.keras.layers.Softmax()])
predictions = probability_model.predict(test_images)
313/313 [==============================] - 1s 3ms/step

Here, the model has predicted the label for each image in the testing set. Let's take a look at the first prediction:

predictions[0]
array([1.7737974e-10, 9.8017128e-10, 2.4250555e-08, 2.7087502e-10,
       3.3816602e-11, 7.0955430e-04, 1.5008560e-09, 2.1424549e-02,
       2.1235054e-09, 9.7786587e-01], dtype=float32)

A prediction is an array of 10 numbers. They represent the model's "confidence" that the image corresponds to each of the 10 different articles of clothing. You can see which label has the highest confidence value:

np.argmax(predictions[0])
9

So, the model is most confident that this image is an ankle boot, or class_names[9]. Examining the test label shows that this classification is correct:

test_labels[0]
9

Graph this to look at the full set of 10 class predictions.

def plot_image(i, predictions_array, true_label, img):
  true_label, img = true_label[i], img[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])

  plt.imshow(img, cmap=plt.cm.binary)

  predicted_label = np.argmax(predictions_array)
  if predicted_label == true_label:
    color = 'blue'
  else:
    color = 'red'

  plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                100*np.max(predictions_array),
                                class_names[true_label]),
                                color=color)

def plot_value_array(i, predictions_array, true_label):
  true_label = true_label[i]
  plt.grid(False)
  plt.xticks(range(10))
  plt.yticks([])
  thisplot = plt.bar(range(10), predictions_array, color="#777777")
  plt.ylim([0, 1])
  predicted_label = np.argmax(predictions_array)

  thisplot[predicted_label].set_color('red')
  thisplot[true_label].set_color('blue')

With the model trained, you can use it to make predictions about some images.

Let's look at the 0th image, predictions, and prediction array. Correct prediction labels are blue and incorrect prediction labels are red. The number gives the percentage (out of 100) for the predicted label.

i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i],  test_labels)
plt.show()
i = 12
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i],  test_labels)
plt.show()

Let's plot several images with their predictions. Note that the model can be wrong even when very confident.

# Color correct predictions in blue and incorrect predictions in red.
num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
  plt.subplot(num_rows, 2*num_cols, 2*i+1)
  plot_image(i, predictions[i], test_labels, test_images)
  plt.subplot(num_rows, 2*num_cols, 2*i+2)
  plot_value_array(i, predictions[i], test_labels)
plt.tight_layout()
plt.show()

Finally, use the trained model to make a prediction about a single image.

img = test_images[1]

print(img.shape)
(28, 28)

tf.keras models are optimized to make predictions on a batch, or collection, of examples at once. Accordingly, even though you're using a single image, you need to add it to a list:

img = (np.expand_dims(img,0))

print(img.shape)
(1, 28, 28)

Now predict the correct label for this image:

predictions_single = probability_model.predict(img)

print(predictions_single)
1/1 [==============================] - 0s 52ms/step
[[1.0949210e-05 4.1276347e-11 9.9810290e-01 1.2848138e-10 1.0825287e-03
  1.3133799e-13 8.0366491e-04 1.1366387e-15 3.2978012e-10 1.3686339e-15]]
plot_value_array(1, predictions_single[0], test_labels)
_ = plt.xticks(range(10), class_names, rotation=45)
plt.show()

tf.keras.Model.predict returns a list of lists, one list for each image in the batch of data. Grab the predictions for our (only) image in the batch:

np.argmax(predictions_single[0])
2

And the model predicts a label as expected.