Convolutional neural networks (CNNs) were developed during the last
+decade of the previous century, with a focus on character recognition
+tasks. Nowadays, CNNs are a central element in the spectacular success
+of deep learning methods. The success in for example image
+classifications have made them a central tool for most machine
+learning practitioners.
+
+
+
CNNs are very similar to ordinary Neural Networks.
+They are made up of neurons that have learnable weights and
+biases. Each neuron receives some inputs, performs a dot product and
+optionally follows it with a non-linearity. The whole network still
+expresses a single differentiable score function: from the raw image
+pixels on one end to class scores at the other. And they still have a
+loss function (for example Softmax) on the last (fully-connected) layer
+and all the tips/tricks we developed for learning regular Neural
+Networks still apply (back propagation, gradient descent etc etc).
+
+
+
+
What is the Difference
+
+
CNN architectures make the explicit assumption that
+the inputs are images, which allows us to encode certain properties
+into the architecture. These then make the forward function more
+efficient to implement and vastly reduce the amount of parameters in
+the network.
+
Neural networks are defined as affine transformations, that is
+a vector is received as input and is multiplied with a matrix of so-called weights (our unknown paramters) to produce an
+output (to which a bias vector is usually added before passing the result
+through a nonlinear activation function). This is applicable to any type of input, be it an
+image, a sound clip or an unordered collection of features: whatever their
+dimensionality, their representation can always be flattened into a vector
+before the transformation.
+
+
+
+
Why CNNS for images, sound files, medical images from CT scans etc?
+
+
However, when we consider images, sound clips and many other similar kinds of data, these data have an intrinsic
+structure. More formally, they share these important properties:
+
+
+
They are stored as multi-dimensional arrays (think of the pixels of a figure) .
+
They feature one or more axes for which ordering matters (e.g., width and height axes for an image, time axis for a sound clip).
+
One axis, called the channel axis, is used to access different views of the data (e.g., the red, green and blue channels of a color image, or the left and right channels of a stereo audio track).
+
These properties are not exploited when an affine transformation is applied; in
+fact, all the axes are treated in the same way and the topological information
+is not taken into account. Still, taking advantage of the implicit structure of
+the data may prove very handy in solving some tasks, like computer vision and
+speech recognition, and in these cases it would be best to preserve it. This is
+where discrete convolutions come into play.
+
+
+
A discrete convolution is a linear transformation that preserves this notion of
+ordering. It is sparse (only a few input units contribute to a given output
+unit) and reuses parameters (the same weights are applied to multiple locations
+in the input).
+
+
+
+
Regular NNs don’t scale well to full images
+
+
As an example, consider
+an image of size \( 32\times 32\times 3 \) (32 wide, 32 high, 3 color channels), so a
+single fully-connected neuron in a first hidden layer of a regular
+Neural Network would have \( 32\times 32\times 3 = 3072 \) weights. This amount still
+seems manageable, but clearly this fully-connected structure does not
+scale to larger images. For example, an image of more respectable
+size, say \( 200\times 200\times 3 \), would lead to neurons that have
+\( 200\times 200\times 3 = 120,000 \) weights.
+
+
+
We could have
+several such neurons, and the parameters would add up quickly! Clearly,
+this full connectivity is wasteful and the huge number of parameters
+would quickly lead to possible overfitting.
+
+
+
+
+
+
Figure 1: A regular 3-layer Neural Network.
+
+
+
+
+
+
3D volumes of neurons
+
+
Convolutional Neural Networks take advantage of the fact that the
+input consists of images and they constrain the architecture in a more
+sensible way.
+
+
+
In particular, unlike a regular Neural Network, the
+layers of a CNN have neurons arranged in 3 dimensions: width,
+height, depth. (Note that the word depth here refers to the third
+dimension of an activation volume, not to the depth of a full Neural
+Network, which can refer to the total number of layers in a network.)
+
+
+
To understand it better, the above example of an image
+with an input volume of
+activations has dimensions \( 32\times 32\times 3 \) (width, height,
+depth respectively).
+
+
+
The neurons in a layer will
+only be connected to a small region of the layer before it, instead of
+all of the neurons in a fully-connected manner. Moreover, the final
+output layer could for this specific image have dimensions \( 1\times 1 \times 10 \),
+because by the
+end of the CNN architecture we will reduce the full image into a
+single vector of class scores, arranged along the depth
+dimension.
+
+
+
+
+
+
Figure 2: A CNN arranges its neurons in three dimensions (width, height, depth), as visualized in one of the layers. Every layer of a CNN transforms the 3D input volume to a 3D output volume of neuron activations. In this example, the red input layer holds the image, so its width and height would be the dimensions of the image, and the depth would be 3 (Red, Green, Blue channels).
+
+
+
+
+
+
Layers used to build CNNs
+
+
A simple CNN is a sequence of layers, and every layer of a CNN
+transforms one volume of activations to another through a
+differentiable function. We use three main types of layers to build
+CNN architectures: Convolutional Layer, Pooling Layer, and
+Fully-Connected Layer (exactly as seen in regular Neural Networks). We
+will stack these layers to form a full CNN architecture.
+
+
+
A simple CNN for image classification could have the architecture:
+
+
+
INPUT (\( 32\times 32 \times 3 \)) will hold the raw pixel values of the image, in this case an image of width 32, height 32, and with three color channels R,G,B.
+
CONV (convolutional )layer will compute the output of neurons that are connected to local regions in the input, each computing a dot product between their weights and a small region they are connected to in the input volume. This may result in volume such as \( [32\times 32\times 12] \) if we decided to use 12 filters.
+
RELU layer will apply an elementwise activation function, such as the \( max(0,x) \) thresholding at zero. This leaves the size of the volume unchanged (\( [32\times 32\times 12] \)).
+
POOL (pooling) layer will perform a downsampling operation along the spatial dimensions (width, height), resulting in volume such as \( [16\times 16\times 12] \).
+
FC (i.e. fully-connected) layer will compute the class scores, resulting in volume of size \( [1\times 1\times 10] \), where each of the 10 numbers correspond to a class score, such as among the 10 categories of the MNIST images we considered above . As with ordinary Neural Networks and as the name implies, each neuron in this layer will be connected to all the numbers in the previous volume.
+
+
+
Transforming images
+
+
CNNs transform the original image layer by layer from the original
+pixel values to the final class scores.
+
+
+
Observe that some layers contain
+parameters and other don’t. In particular, the CNN layers perform
+transformations that are a function of not only the activations in the
+input volume, but also of the parameters (the weights and biases of
+the neurons). On the other hand, the RELU/POOL layers will implement a
+fixed function. The parameters in the CONV/FC layers will be trained
+with gradient descent so that the class scores that the CNN computes
+are consistent with the labels in the training set for each image.
+
However, both standard feed forwards networks and CNNs perform well on data with unknown length.
+
The textbook by Goodfellow et al, see chapter 9 contains an in depth discussion as well.
+
+
+
Key Idea
+
+
A dense neural network is representd by an affine operation (like matrix-matrix multiplication) where all parameters are included.
+
+
The key idea in CNNs for say imaging is that in images neighbor pixels tend to be related! So we connect
+only neighboring neurons in the input instead of connecting all with the first hidden layer.
+
+
+
We say we perform a filtering (convolution is the mathematical operation).
+
+
+
Mathematics of CNNs
+
+
The mathematics of CNNs is based on the mathematical operation of
+convolution. In mathematics (in particular in functional analysis),
+convolution is represented by mathematical operation (integration,
+summation etc) on two function in order to produce a third function
+that expresses how the shape of one gets modified by the other.
+Convolution has a plethora of applications in a variety of disciplines, spanning from statistics to signal processing, computer vision, solutions of differential equations,linear algebra, engineering, and yes, machine learning.
+
+
+
Mathematically, convolution is defined as follows (one-dimensional example):
+Let us define a continuous function \( y(t) \) given by
+
+$$
+y(t) = \int x(a) w(t-a) da,
+$$
+
+
where \( x(a) \) represents a so-called input and \( w(t-a) \) is normally called the weight function or kernel.
+
+
The above integral is written in a more compact form as
Computing the inverse of the above convolution operations is known as deconvolution.
+
+
How can we use this? And what does it mean? Let us study some familiar examples first.
+
+
+
Convolution Examples: Polynomial multiplication
+
+
We have already met such an example in project 1 when we tried to set
+up the design matrix for a two-dimensional function. This was an
+example of polynomial multiplication. Let us recast such a problem in terms of the convolution operation.
+Let us look a the following polynomials to second and third order, respectively:
+
Computing polynomial products can be implemented efficiently if we rewrite the more brute force multiplications using convolution.
+We note first that the new coefficients are given as
+
Do you see a potential drawback with these equations?
+
+
+
A more efficient way of coding the above Convolution
+
+
Since we only have a finite number of \( \alpha \) and \( \beta \) values
+which are non-zero, we can rewrite the above convolution expressions
+as a matrix-vector multiplication
+
The process is commutative and we can easily see that we can rewrite the multiplication in terms of a matrix holding \( \beta \) and a vector holding \( \alpha \).
+In this case we have
+
Note that the use of these matrices is for mathematical purposes only and not implementation purposes.
+When implementing the above equation we do not encode (and allocate memory) the matrices explicitely.
+We rather code the convolutions in the minimal memory footprint that they require.
+
+
+
Does the number of floating point operations change here when we use the commutative property?
+
+
+
Convolution Examples: Principle of Superposition and Periodic Forces (Fourier Transforms)
+
+
For problems with so-called harmonic oscillations, given by for example the following differential equation
where \( F(t) \) is an applied external force acting on the system (often called a driving force), one can use the theory of Fourier transformations to find the solutions of this type of equations.
+
+
If one has several driving forces, \( F(t)=\sum_n F_n(t) \), one can find
+the particular solution to each \( F_n \), \( x_{pn}(t) \), and the particular
+solution for the entire driving force is then given by a series like
+
This is known as the principle of superposition. It only applies when
+the homogenous equation is linear. If there were an anharmonic term
+such as \( x^3 \) in the homogenous equation, then when one summed various
+solutions, \( x=(\sum_n x_n)^2 \), one would get cross
+terms. Superposition is especially useful when \( F(t) \) can be written
+as a sum of sinusoidal terms, because the solutions for each
+sinusoidal (sine or cosine) term is analytic.
+
+
+
Driving forces are often periodic, even when they are not
+sinusoidal. Periodicity implies that for some time \( \tau \)
+
One example of a non-sinusoidal periodic force is a square wave. Many
+components in electric circuits are non-linear, e.g. diodes, which
+makes many wave forms non-sinusoidal even when the circuits are being
+driven by purely sinusoidal sources.
+
+
+
+
Simple Code Example
+
+
The code here shows a typical example of such a square wave generated using the functionality included in the scipy Python package. We have used a period of \( \tau=0.2 \).
+
+
+
+
+
+
+
+
+
importnumpyasnp
+importmath
+fromscipyimport signal
+importmatplotlib.pyplotasplt
+
+# number of points
+n =500
+# start and final times
+t0 =0.0
+tn =1.0
+# Period
+t = np.linspace(t0, tn, n, endpoint=False)
+SqrSignal = np.zeros(n)
+SqrSignal =1.0+signal.square(2*np.pi*5*t)
+plt.plot(t, SqrSignal)
+plt.ylim(-0.5, 2.5)
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
For the sinusoidal example the
+period is \( \tau=2\pi/\omega \). However, higher harmonics can also
+satisfy the periodicity requirement. In general, any force that
+satisfies the periodicity requirement can be expressed as a sum over
+harmonics,
+
We can write down the answer for
+\( x_{pn}(t) \), by substituting \( f_n/m \) or \( g_n/m \) for \( F_0/m \). By
+writing each factor \( 2n\pi t/\tau \) as \( n\omega t \), with \( \omega\equiv
+2\pi/\tau \),
+
Because the forces have been applied for a long time, any non-zero
+damping eliminates the homogenous parts of the solution, so one need
+only consider the particular solution for each \( n \).
+
+
+
The problem is considered solved if one can find expressions for the
+coefficients \( f_n \) and \( g_n \), even though the solutions are expressed
+as an infinite sum. The coefficients can be extracted from the
+function \( F(t) \) by
+
To check the consistency of these expressions and to verify
+Eq. \eqref{eq:fourierdef2}, one can insert the expansion of \( F(t) \) in
+Eq. \eqref{eq:fourierdef1} into the expression for the coefficients in
+Eq. \eqref{eq:fourierdef2} and see whether
+
Immediately, one can throw away all the terms with \( g_m \) because they
+convolute an even and an odd function. The term with \( f_0/2 \)
+disappears because \( \cos(n\omega t) \) is equally positive and negative
+over the interval and will integrate to zero. For all the terms
+\( f_m\cos(m\omega t) \) appearing in the sum, one can use angle addition
+formulas to see that \( \cos(m\omega t)\cos(n\omega
+t)=(1/2)(\cos[(m+n)\omega t]+\cos[(m-n)\omega t] \). This will integrate
+to zero unless \( m=n \). In that case the \( m=n \) term gives
+
The same method can be used to check for the consistency of \( g_n \).
+
+
+
Final words on Fourier Transforms
+
+
The code here uses the Fourier series applied to a
+square wave signal. The code here
+visualizes the various approximations given by Fourier series compared
+with a square wave with period \( T=0.2 \) (dimensionless time), width \( 0.1 \) and max value of the force \( F=2 \). We
+see that when we increase the number of components in the Fourier
+series, the Fourier series approximation gets closer and closer to the
+square wave signal.
+
+
+
+
+
+
+
+
+
+
importnumpyasnp
+importmath
+fromscipyimport signal
+importmatplotlib.pyplotasplt
+
+# number of points
+n =500
+# start and final times
+t0 =0.0
+tn =1.0
+# Period
+T =0.2
+# Max value of square signal
+Fmax=2.0
+# Width of signal
+Width =0.1
+t = np.linspace(t0, tn, n, endpoint=False)
+SqrSignal = np.zeros(n)
+FourierSeriesSignal = np.zeros(n)
+SqrSignal =1.0+signal.square(2*np.pi*5*t+np.pi*Width/T)
+a0 = Fmax*Width/T
+FourierSeriesSignal = a0
+Factor =2.0*Fmax/np.pi
+for i inrange(1,500):
+ FourierSeriesSignal += Factor/(i)*np.sin(np.pi*i*Width/T)*np.cos(i*t*2*np.pi/T)
+plt.plot(t, SqrSignal)
+plt.plot(t, FourierSeriesSignal)
+plt.ylim(-0.5, 2.5)
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Two-dimensional Objects
+
+
We often use convolutions over more than one dimension at a time. If
+we have a two-dimensional image \( I \) as input, we can have a filter
+defined by a two-dimensional kernel \( K \). This leads to an output \( S \)
+
Normally the latter is more straightforward to implement in a machine elarning library since there is less variation in the range of values of \( m \) and \( n \).
+
+
+
Cross-Correlation
+
+
Many deep learning libraries implement cross-correlation instead of convolution
In feilds like signal processing (and imaging as well), one designs
+so-called filters. These filters are defined by the convolutions and
+are often hand-crafted. One may specify filters for smoothing, edge
+detection, frequency reshaping, and similar operations. However with
+neural networks the idea is to automatically learn the filters and use
+many of them in conjunction with non-linear operations (activation
+functions).
+
+
+
As an example consider a neural network operating on sound sequence
+data. Assume that we an input vector \( \boldsymbol{x} \) of length \( d=10^6 \). We
+construct then a neural network with onle hidden layer only with
+\( 10^4 \) nodes. This means that we will have a weight matrix with
+\( 10^4\times 10^6=10^{10} \) weights to be determined, together with \( 10^4 \) biases.
+
+
+
Assume furthermore that we have an output layer which is meant to train whether the sound sequence represents a human voice (true) or something else (false).
+It means that we have only one output node. But since this output node connects to \( 10^4 \) nodes in the hidden layer, there are in total \( 10^4 \) weights to be determined for the output layer, plus one bias. In total we have
+
In today’s architecture one can train such neural networks, however
+this is a huge number of parameters for the task at hand. In general,
+it is a very wasteful and inefficient use of dense matrices as
+parameters. Just as importantly, such trained network parameters are
+very specific for the type of input data on which they were trained
+and the network is not likely to generalize easily to variations in
+the input.
+
+
+
The main principles that justify convolutions is locality of
+information and repetion of patterns within the signal. Sound samples
+of the input in adjacent spots are much more likely to affect each
+other than those that are very far away. Similarly, sounds are
+repeated in multiple times in the signal. While slightly simplistic,
+reasoning about such a sound example demonstrates this. The same
+principles then apply to images and other similar data.
+
CNNs in more detail, building convolutional neural networks in Tensorflow and Keras
+
+
As discussed above, CNNs are neural networks built from the assumption that the inputs
+to the network are 2D images. This is important because the number of features or pixels in images
+grows very fast with the image size, and an enormous number of weights and biases are needed in order to build an accurate network.
+
+
+
As before, we still have our input, a hidden layer and an output. What's novel about convolutional networks
+are the convolutional and pooling layers stacked in pairs between the input and the hidden layer.
+In addition, the data is no longer represented as a 2D feature matrix, instead each input is a number of 2D
+matrices, typically 1 for each color dimension (Red, Green, Blue).
+
+
+
+
Setting it up
+
+
It means that to represent the entire
+dataset of images, we require a 4D matrix or tensor. This tensor has the dimensions:
+
The MNIST dataset consists of grayscale images with a pixel size of
+\( 28\times 28 \), meaning we require \( 28 \times 28 = 724 \) weights to each
+neuron in the first hidden layer.
+
+
+
If we were to analyze images of size \( 128\times 128 \) we would require
+\( 128 \times 128 = 16384 \) weights to each neuron. Even worse if we were
+dealing with color images, as most images are, we have an image matrix
+of size \( 128\times 128 \) for each color dimension (Red, Green, Blue),
+meaning 3 times the number of weights \( = 49152 \) are required for every
+single neuron in the first hidden layer.
+
+
+
+
+
Strong correlations
+
+
Images typically have strong local correlations, meaning that a small
+part of the image varies little from its neighboring regions. If for
+example we have an image of a blue car, we can roughly assume that a
+small blue part of the image is surrounded by other blue regions.
+
+
+
Therefore, instead of connecting every single pixel to a neuron in the
+first hidden layer, as we have previously done with deep neural
+networks, we can instead connect each neuron to a small part of the
+image (in all 3 RGB depth dimensions). The size of each small area is
+fixed, and known as a receptive.
+
+
+
+
+
Layers of a CNN
+
The layers of a convolutional neural network arrange neurons in 3D: width, height and depth.
+The input image is typically a square matrix of depth 3.
+
+
+
A convolution is performed on the image which outputs
+a 3D volume of neurons. The weights to the input are arranged in a number of 2D matrices, known as filters.
+
+
+
Each filter slides along the input image, taking the dot product
+between each small part of the image and the filter, in all depth
+dimensions. This is then passed through a non-linear function,
+typically the Rectified Linear (ReLu) function, which serves as the
+activation of the neurons in the first convolutional layer. This is
+further passed through a pooling layer, which reduces the size of the
+convolutional layer, e.g. by taking the maximum or average across some
+small regions, and this serves as input to the next convolutional
+layer.
+
+
+
+
Systematic reduction
+
+
By systematically reducing the size of the input volume, through
+convolution and pooling, the network should create representations of
+small parts of the input, and then from them assemble representations
+of larger areas. The final pooling layer is flattened to serve as
+input to a hidden layer, such that each neuron in the final pooling
+layer is connected to every single neuron in the hidden layer. This
+then serves as input to the output layer, e.g. a softmax output for
+classification.
+
+
+
+
+
Prerequisites: Collect and pre-process data
+
+
+
+
+
+
+
+
# import necessary packages
+importnumpyasnp
+importmatplotlib.pyplotasplt
+fromsklearnimport datasets
+
+
+# ensure the same random numbers appear every time
+np.random.seed(0)
+
+# display images in notebook
+%matplotlib inline
+plt.rcParams['figure.figsize'] = (12,12)
+
+
+# download MNIST dataset
+digits = datasets.load_digits()
+
+# define inputs and labels
+inputs = digits.images
+labels = digits.target
+
+# RGB images have a depth of 3
+# our images are grayscale so they should have a depth of 1
+inputs = inputs[:,:,:,np.newaxis]
+
+print("inputs = (n_inputs, pixel_width, pixel_height, depth) = "+str(inputs.shape))
+print("labels = (n_inputs) = "+str(labels.shape))
+
+
+# choose some random images to display
+n_inputs =len(inputs)
+indices = np.arange(n_inputs)
+random_indices = np.random.choice(indices, size=5)
+
+for i, image inenumerate(digits.images[random_indices]):
+ plt.subplot(1, 5, i+1)
+ plt.axis('off')
+ plt.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')
+ plt.title("Label: %d"% digits.target[random_indices[i]])
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Importing Keras and Tensorflow
+
+
+
+
+
+
+
+
fromtensorflow.kerasimport datasets, layers, models
+fromtensorflow.keras.layersimport Input
+fromtensorflow.keras.modelsimport Sequential #This allows appending layers to existing models
+fromtensorflow.keras.layersimport Dense #This allows defining the characteristics of a particular layer
+fromtensorflow.kerasimport optimizers #This allows using whichever optimiser we want (sgd,adam,RMSprop)
+fromtensorflow.kerasimport regularizers #This allows using whichever regularizer we want (l1,l2,l1_l2)
+fromtensorflow.keras.utilsimport to_categorical #This allows using categorical cross entropy as the cost function
+#from tensorflow.keras import Conv2D
+#from tensorflow.keras import MaxPooling2D
+#from tensorflow.keras import Flatten
+
+fromsklearn.model_selectionimport train_test_split
+
+# representation of labels
+labels = to_categorical(labels)
+
+# split into train and test data
+# one-liner from scikit-learn library
+train_size =0.8
+test_size =1- train_size
+X_train, X_test, Y_train, Y_test = train_test_split(inputs, labels, train_size=train_size,
+ test_size=test_size)
+
The CIFAR10 dataset contains 60,000 color images in 10 classes, with
+6,000 images in each class. The dataset is divided into 50,000
+training images and 10,000 testing images. The classes are mutually
+exclusive and there is no overlap between them.
+
+
+
+
+
+
+
+
+
+
importtensorflowastf
+
+fromtensorflow.kerasimport datasets, layers, models
+importmatplotlib.pyplotasplt
+
+# We import the data set
+(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()
+
+# Normalize pixel values to be between 0 and 1 by dividing by 255.
+train_images, test_images = train_images /255.0, test_images /255.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Verifying the data set
+
+
To verify that the dataset looks correct, let's plot the first 25 images from the training set and display the class name below each image.
+
+
+
+
+
+
+
+
+
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
+ 'dog', 'frog', 'horse', 'ship', 'truck']
+
+plt.figure(figsize=(10,10))
+for i inrange(25):
+ plt.subplot(5,5,i+1)
+ plt.xticks([])
+ plt.yticks([])
+ plt.grid(False)
+ plt.imshow(train_images[i], cmap=plt.cm.binary)
+ # The CIFAR labels happen to be arrays,
+ # which is why you need the extra index
+ plt.xlabel(class_names[train_labels[i][0]])
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Set up the model
+
+
The 6 lines of code below define the convolutional base using a common pattern: a stack of Conv2D and MaxPooling2D layers.
+
+
As input, a CNN takes tensors of shape (image_height, image_width, color_channels), ignoring the batch size. If you are new to these dimensions, color_channels refers to (R,G,B). In this example, you will configure our CNN to process inputs of shape (32, 32, 3), which is the format of CIFAR images. You can do this by passing the argument input_shape to our first layer.
+
+
+
+
+
+
+
+
+
model = models.Sequential()
+model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
+model.add(layers.MaxPooling2D((2, 2)))
+model.add(layers.Conv2D(64, (3, 3), activation='relu'))
+model.add(layers.MaxPooling2D((2, 2)))
+model.add(layers.Conv2D(64, (3, 3), activation='relu'))
+
+# Let's display the architecture of our model so far.
+
+model.summary()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
You can see that the output of every Conv2D and MaxPooling2D layer is a 3D tensor of shape (height, width, channels). The width and height dimensions tend to shrink as you go deeper in the network. The number of output channels for each Conv2D layer is controlled by the first argument (e.g., 32 or 64). Typically, as the width and height shrink, you can afford (computationally) to add more output channels in each Conv2D layer.
+
+
+
Add Dense layers on top
+
+
To complete our model, you will feed the last output tensor from the
+convolutional base (of shape (4, 4, 64)) into one or more Dense layers
+to perform classification. Dense layers take vectors as input (which
+are 1D), while the current output is a 3D tensor. First, you will
+flatten (or unroll) the 3D output to 1D, then add one or more Dense
+layers on top. CIFAR has 10 output classes, so you use a final Dense
+layer with 10 outputs and a softmax activation.
+
+
+
+
+
+
+
+
+
+
model.add(layers.Flatten())
+model.add(layers.Dense(64, activation='relu'))
+model.add(layers.Dense(10))
+Here's the complete architecture of our model.
+
+model.summary()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
As you can see, our (4, 4, 64) outputs were flattened into vectors of shape (1024) before going through two Dense layers.
@@ -1069,7 +2389,7 @@ samples
$$
\begin{equation}
x = g(z; \theta^{(g)})
-\label{_auto1}
+\label{_auto4}
\end{equation}
$$
@@ -1086,7 +2406,7 @@ value given by
$$
\begin{equation}
d(x; \theta^{(d)})
-\label{_auto2}
+\label{_auto5}
\end{equation}
$$
@@ -1099,7 +2419,7 @@ which a function
$$
\begin{equation}
v(\theta^{(g)}, \theta^{(d)})
-\label{_auto3}
+\label{_auto6}
\end{equation}
$$
@@ -1110,7 +2430,7 @@ conjugate reward
$$
\begin{equation}
-v(\theta^{(g)}, \theta^{(d)})
-\label{_auto4}
+\label{_auto7}
\end{equation}
$$
@@ -1145,7 +2465,7 @@ $$
\begin{equation}
g^* = \underset{g}{\mathrm{argmin}}\hspace{2pt}
\underset{d}{\mathrm{max}}v(\theta^{(g)}, \theta^{(d)})
-\label{_auto5}
+\label{_auto8}
\end{equation}
$$
@@ -1155,7 +2475,7 @@ $$
v(\theta^{(g)}, \theta^{(d)}) = \mathbb{E}_{x\sim p_\mathrm{data}}\log d(x)
+ \mathbb{E}_{x\sim p_\mathrm{model}}
\log (1 - d(x))
-\label{_auto6}
+\label{_auto9}
\end{equation}
$$
@@ -1166,7 +2486,7 @@ approximation of a partition function. In the case where
$$
\begin{equation}
\underset{d}{\mathrm{max}}v(\theta^{(g)}, \theta^{(d)})
-\label{_auto7}
+\label{_auto10}
\end{equation}
$$
@@ -2122,1207 +3442,6 @@ plot_results(results, plot_number)
-
-
Basic ideas of the Principal Component Analysis (PCA)
-
-
The principal component analysis deals with the problem of fitting a
-low-dimensional affine subspace \( S \) of dimension \( d \) much smaller than
-the total dimension \( D \) of the problem at hand (our data
-set). Mathematically it can be formulated as a statistical problem or
-a geometric problem. In our discussion of the theorem for the
-classical PCA, we will stay with a statistical approach.
-Historically, the PCA was first formulated in a statistical setting in order to estimate the principal component of a multivariate random variable.
-
-
-
We have a data set defined by a design/feature matrix \( \boldsymbol{X} \) (see below for its definition)
-
-
Each data point is determined by \( p \) extrinsic (measurement) variables
-
We may want to ask the following question: Are there fewer intrinsic variables (say \( d < < p \)) that still approximately describe the data?
-
If so, these intrinsic variables may tell us something important and finding these intrinsic variables is what dimension reduction methods do.
Introducing the Covariance and Correlation functions
-
-
Before we discuss the PCA theorem, we need to remind ourselves about
-the definition of the covariance and the correlation function. These are quantities
-
-
-
Suppose we have defined two vectors
-\( \hat{x} \) and \( \hat{y} \) with \( n \) elements each. The covariance matrix \( \boldsymbol{C} \) is defined as
-
The covariance takes values between zero and infinity and may thus
-lead to problems with loss of numerical precision for particularly
-large values. It is common to scale the covariance matrix by
-introducing instead the correlation matrix defined via the so-called
-correlation function
-
The correlation function is then given by values \( \mathrm{corr}[\boldsymbol{x},\boldsymbol{y}]
-\in [-1,1] \). This avoids eventual problems with too large values. We
-can then define the correlation matrix for the two vectors \( \boldsymbol{x} \)
-and \( \boldsymbol{y} \) as
-
In the above example this is the function we constructed using pandas.
-
-
-
Reminding ourselves about Linear Regression
-
In our derivation of the various regression algorithms like Ordinary Least Squares or Ridge regression
-we defined the design/feature matrix \( \boldsymbol{X} \) as
-
with \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \), with the predictors/features \( p \) refering to the column numbers and the
-entries \( n \) being the row elements.
-We can rewrite the design/feature matrix in terms of its column vectors as
-
With these definitions, we can now rewrite our \( 2\times 2 \)
-correlation/covariance matrix in terms of a moe general design/feature
-matrix \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \). This leads to a \( p\times p \)
-covariance matrix for the vectors \( \boldsymbol{x}_i \) with \( i=0,1,\dots,p-1 \)
-
The Numpy function np.cov calculates the covariance elements using
-the factor \( 1/(n-1) \) instead of \( 1/n \) since it assumes we do not have
-the exact mean values. The following simple function uses the
-np.vstack function which takes each vector of dimension \( 1\times n \)
-and produces a \( 2\times n \) matrix \( \boldsymbol{W} \)
-
which in turn is converted into into the \( 2\times 2 \) covariance matrix
-\( \boldsymbol{C} \) via the Numpy function np.cov(). We note that we can also calculate
-the mean value of each set of samples \( \boldsymbol{x} \) etc using the Numpy
-function np.mean(x). We can also extract the eigenvalues of the
-covariance matrix through the np.linalg.eig() function.
-
The previous example can be converted into the correlation matrix by
-simply scaling the matrix elements with the variances. We should also
-subtract the mean values for each column. This leads to the following
-code which sets up the correlations matrix for the previous example in
-a more brute force way. Here we scale the mean values for each column of the design matrix, calculate the relevant mean values and variances and then finally set up the \( 2\times 2 \) correlation matrix (since we have only two vectors).
-
-
-
-
-
-
-
-
-
-
importnumpyasnp
-n =100
-# define two vectors
-x = np.random.random(size=n)
-y =4+3*x+np.random.normal(size=n)
-#scaling the x and y vectors
-x = x - np.mean(x)
-y = y - np.mean(y)
-variance_x = np.sum(x@x)/n
-variance_y = np.sum(y@y)/n
-print(variance_x)
-print(variance_y)
-cov_xy = np.sum(x@y)/n
-cov_xx = np.sum(x@x)/n
-cov_yy = np.sum(y@y)/n
-C = np.zeros((2,2))
-C[0,0]= cov_xx/variance_x
-C[1,1]= cov_yy/variance_y
-C[0,1]= cov_xy/np.sqrt(variance_y*variance_x)
-C[1,0]= C[0,1]
-print(C)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
We see that the matrix elements along the diagonal are one as they
-should be and that the matrix is symmetric. Furthermore, diagonalizing
-this matrix we easily see that it is a positive definite matrix.
-
-
-
The above procedure with numpy can be made more compact if we use pandas.
-
-
-
Using Pandas
-
-
We whow here how we can set up the correlation matrix using pandas, as done in this simple code
We expand this model to the Franke function discussed above.
-
-
-
-
-
-
-
-
-
# Common imports
-importnumpyasnp
-importpandasaspd
-
-
-defFrankeFunction(x,y):
- term1 =0.75*np.exp(-(0.25*(9*x-2)**2) -0.25*((9*y-2)**2))
- term2 =0.75*np.exp(-((9*x+1)**2)/49.0-0.1*(9*y+1))
- term3 =0.5*np.exp(-(9*x-7)**2/4.0-0.25*((9*y-3)**2))
- term4 =-0.2*np.exp(-(9*x-4)**2- (9*y-7)**2)
- return term1 + term2 + term3 + term4
-
-
-defcreate_X(x, y, n ):
- iflen(x.shape) >1:
- x = np.ravel(x)
- y = np.ravel(y)
-
- N =len(x)
- l =int((n+1)*(n+2)/2) # Number of elements in beta
- X = np.ones((N,l))
-
- for i inrange(1,n+1):
- q =int((i)*(i+1)/2)
- for k inrange(i+1):
- X[:,q+k] = (x**(i-k))*(y**k)
-
- return X
-
-
-# Making meshgrid of datapoints and compute Franke's function
-n =4
-N =100
-x = np.sort(np.random.uniform(0, 1, N))
-y = np.sort(np.random.uniform(0, 1, N))
-z = FrankeFunction(x, y)
-X = create_X(x, y, n=n)
-
-Xpd = pd.DataFrame(X)
-# subtract the mean values and set up the covariance matrix
-Xpd = Xpd - Xpd.mean()
-covariance_matrix = Xpd.cov()
-print(covariance_matrix)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
We note here that the covariance is zero for the first rows and
-columns since all matrix elements in the design matrix were set to one
-(we are fitting the function in terms of a polynomial of degree \( n \)). We would however not include the intercept
-and wee can simply
-drop these elements and construct a correlation
-matrix without them by centering our matrix elements by subtracting the mean of each column.
-
-
-
-
Lnks with the Design Matrix
-
-
We can rewrite the covariance matrix in a more compact form in terms of the design/feature matrix \( \boldsymbol{X} \) as
where we wrote $$\boldsymbol{C}[\boldsymbol{x}_0,\boldsymbol{x}_1] = \boldsymbol{C}[\boldsymbol{x}]$$ to indicate that this the covariance of the vectors \( \boldsymbol{x} \) of the design/feature matrix \( \boldsymbol{X} \).
-
-
It is easy to generalize this to a matrix \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \).
-
-
-
Towards the PCA theorem
-
-
We have that the covariance matrix (the correlation matrix involves a simple rescaling) is given as
Let us now assume that we can perform a series of orthogonal transformations where we employ some orthogonal matrices \( \boldsymbol{S} \).
-These matrices are defined as \( \boldsymbol{S}\in {\mathbb{R}}^{p\times p} \) and obey the orthogonality requirements \( \boldsymbol{S}\boldsymbol{S}^T=\boldsymbol{S}^T\boldsymbol{S}=\boldsymbol{I} \). The matrix can be written out in terms of the column vectors \( \boldsymbol{s}_i \) as \( \boldsymbol{S}=[\boldsymbol{s}_0,\boldsymbol{s}_1,\dots,\boldsymbol{s}_{p-1}] \) and \( \boldsymbol{s}_i \in {\mathbb{R}}^{p} \).
-
-
-
Assume also that there is a transformation \( \boldsymbol{S}^T\boldsymbol{C}[\boldsymbol{x}]\boldsymbol{S}=\boldsymbol{C}[\boldsymbol{y}] \) such that the new matrix \( \boldsymbol{C}[\boldsymbol{y}] \) is diagonal with elements \( [\lambda_0,\lambda_1,\lambda_2,\dots,\lambda_{p-1}] \).
In the derivation of the PCA theorem we will assume that the eigenvalues are ordered in descending order, that is
-\( \lambda_0 > \lambda_1 > \dots > \lambda_{p-1} \).
-
-
-
The eigenvalues tell us then how much we need to stretch the
-corresponding eigenvectors. Dimensions with large eigenvalues have
-thus large variations (large variance) and define therefore useful
-dimensions. The data points are more spread out in the direction of
-these eigenvectors. Smaller eigenvalues mean on the other hand that
-the corresponding eigenvectors are shrunk accordingly and the data
-points are tightly bunched together and there is not much variation in
-these specific directions. Hopefully then we could leave it out
-dimensions where the eigenvalues are very small. If \( p \) is very large,
-we could then aim at reducing \( p \) to \( l < < p \) and handle only \( l \)
-features/predictors.
-
-
-
-
The Algorithm before theorem
-
-
Here's how we would proceed in setting up the algorithm for the PCA, see also discussion below here.
-
-
Set up the datapoints for the design/feature matrix \( \boldsymbol{X} \) with \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \), with the predictors/features \( p \) referring to the column numbers and the entries \( n \) being the row elements.
Center the data by subtracting the mean value for each column. This leads to a new matrix \( \boldsymbol{X}\rightarrow \overline{\boldsymbol{X}} \).
-
Compute then the covariance/correlation matrix \( \mathbb{E}[\overline{\boldsymbol{X}}^T\overline{\boldsymbol{X}}] \).
-
Find the eigenpairs of \( \boldsymbol{C} \) with eigenvalues \( [\lambda_0,\lambda_1,\dots,\lambda_{p-1}] \) and eigenvectors \( [\boldsymbol{s}_0,\boldsymbol{s}_1,\dots,\boldsymbol{s}_{p-1}] \).
-
Order the eigenvalue (and the eigenvectors accordingly) in order of decreasing eigenvalues.
-
Keep only those \( l \) eigenvalues larger than a selected threshold value, discarding thus \( p-l \) features since we expect small variations in the data here.
-
-
-
Writing our own PCA code
-
-
We will use a simple example first with two-dimensional data
-drawn from a multivariate normal distribution with the following mean and covariance matrix (we have fixed these quantities but will play around with them below):
-
Note that the mean refers to each column of data.
-We will generate \( n = 10000 \) points \( X = \{ x_1, \ldots, x_N \} \) from
-this distribution, and store them in the \( 1000 \times 2 \) matrix \( \boldsymbol{X} \). This is our design matrix where we have forced the covariance and mean values to take specific values.
-
-
-
-
Implementing it
-
The following Python code aids in setting up the data and writing out the design matrix.
-Note that the function multivariate returns also the covariance discussed above and that it is defined by dividing by \( n-1 \) instead of \( n \).
-
Now we are going to implement the PCA algorithm. We will break it down into various substeps.
-
-
-
First Step
-
-
The first step of PCA is to compute the sample mean of the data and use it to center the data. Recall that the sample mean is
-$$
-\mu_n = \frac{1}{n} \sum_{i=1}^n x_i
-$$
-
-
and the mean-centered data \( \bar{X} = \{ \bar{x}_1, \ldots, \bar{x}_n \} \) takes the form
-$$
-\bar{x}_i = x_i - \mu_n.
-$$
-
-
When you are done with these steps, print out \( \mu_n \) to verify it is
-close to \( \mu \) and plot your mean centered data to verify it is
-centered at the origin!
-The following code elements perform these operations using pandas or using our own functionality for doing so. The latter, using numpy is rather simple through the mean() function.
-
-
-
-
-
-
-
-
-
df = pd.DataFrame(X)
-# Pandas does the centering for us
-df = df -df.mean()
-# we center it ourselves
-X_centered = X - X.mean(axis=0)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Scaling
-
Alternatively, we could use the functions we discussed
-earlier for scaling the data set. That is, we could have used the
-StandardScaler function in Scikit-Learn, a function which ensures
-that for each feature/predictor we study the mean value is zero and
-the variance is one (every column in the design/feature matrix). You
-would then not get the same results, since we divide by the
-variance. The diagonal covariance matrix elements will then be one,
-while the non-diagonal ones need to be divided by \( 2\sqrt{2} \) for our
-specific case.
-
-
-
-
Centered Data
-
-
Now we are going to use the mean centered data to compute the sample covariance of the data by using the following equation
where the data points \( x_i \in \mathbb{R}^p \) (here in this example \( p = 2 \)) are column vectors and \( x^T \) is the transpose of \( x \).
-We can write our own code or simply use either the functionaly of numpy or that of pandas, as follows
-
-
-
-
-
-
-
-
-
print(df.cov())
-print(np.cov(X_centered.T))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Note that the way we define the covariance matrix here has a factor \( n-1 \) instead of \( n \). This is included in the cov() function by numpy and pandas.
-Our own code here is not very elegant and asks for obvious improvements. It is tailored to this specific \( 2\times 2 \) covariance matrix.
-
-
-
-
-
-
-
-
-
# extract the relevant columns from the centered design matrix of dim n x 2
-x = X_centered[:,0]
-y = X_centered[:,1]
-Cov = np.zeros((2,2))
-Cov[0,1] = np.sum(x.T@y)/(n-1.0)
-Cov[0,0] = np.sum(x.T@x)/(n-1.0)
-Cov[1,1] = np.sum(y.T@y)/(n-1.0)
-Cov[1,0]= Cov[0,1]
-print("Centered covariance using own code")
-print(Cov)
-plt.plot(x, y, 'x')
-plt.axis('equal')
-plt.show()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Exploring
-
-
Depending on the number of points \( n \), we will get results that are close to the covariance values defined above.
-The plot shows how the data are clustered around a line with slope close to one. Is this expected? Try to change the covariance and the mean values. For example, try to make the variance of the first element much larger than that of the second diagonal element. Try also to shrink the covariance (the non-diagonal elements) and see how the data points are distributed.
-
-
-
-
Diagonalize the sample covariance matrix to obtain the principal components
-
-
Now we are ready to solve for the principal components! To do so we
-diagonalize the sample covariance matrix \( \Sigma \). We can use the
-function np.linalg.eig to do so. It will return the eigenvalues and
-eigenvectors of \( \Sigma \). Once we have these we can perform the
-following tasks:
-
-
-
-
We compute the percentage of the total variance captured by the first principal component
-
We plot the mean centered data and lines along the first and second principal components
-
Then we project the mean centered data onto the first and second principal components, and plot the projected data.
Collecting all these steps we can write our own PCA function and
-compare this with the functionality included in Scikit-Learn.
-
-
-
The code here outlines some of the elements we could include in the
-analysis. Feel free to extend upon this in order to address the above
-questions.
-
-
-
-
-
-
-
-
-
-
# diagonalize and obtain eigenvalues, not necessarily sorted
-EigValues, EigVectors = np.linalg.eig(Cov)
-# sort eigenvectors and eigenvalues
-#permute = EigValues.argsort()
-#EigValues = EigValues[permute]
-#EigVectors = EigVectors[:,permute]
-print("Eigenvalues of Covariance matrix")
-for i inrange(2):
- print(EigValues[i])
-FirstEigvector = EigVectors[:,0]
-SecondEigvector = EigVectors[:,1]
-print("First eigenvector")
-print(FirstEigvector)
-print("Second eigenvector")
-print(SecondEigvector)
-#thereafter we do a PCA with Scikit-learn
-fromsklearn.decompositionimport PCA
-pca = PCA(n_components =2)
-X2Dsl = pca.fit_transform(X)
-print("Eigenvector of largest eigenvalue")
-print(pca.components_.T[:, 0])
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
This code does not contain all the above elements, but it shows how we can use Scikit-Learn to extract the eigenvector which corresponds to the largest eigenvalue. Try to address the questions we pose before the above code. Try also to change the values of the covariance matrix by making one of the diagonal elements much larger than the other. What do you observe then?
-
-
-
Classical PCA Theorem
-
-
We assume now that we have a design matrix \( \boldsymbol{X} \) which has been
-centered as discussed above. For the sake of simplicity we skip the
-overline symbol. The matrix is defined in terms of the various column
-vectors \( [\boldsymbol{x}_0,\boldsymbol{x}_1,\dots, \boldsymbol{x}_{p-1}] \) each with dimension
-\( \boldsymbol{x}\in {\mathbb{R}}^{n} \).
-
-
-
The PCA theorem states that minimizing the above reconstruction error
-corresponds to setting \( \boldsymbol{W}=\boldsymbol{S} \), the orthogonal matrix which
-diagonalizes the empirical covariance(correlation) matrix. The optimal
-low-dimensional encoding of the data is then given by a set of vectors
-\( \boldsymbol{z}_i \) with at most \( l \) vectors, with \( l < < p \), defined by the
-orthogonal projection of the data onto the columns spanned by the
-eigenvectors of the covariance(correlations matrix).
-
-
-
-
The PCA Theorem
-
-
To show the PCA theorem let us start with the assumption that there is one vector \( \boldsymbol{s}_0 \) which corresponds to a solution which minimized the reconstruction error \( J \). This is an orthogonal vector. It means that we now approximate the reconstruction error in terms of \( \boldsymbol{w}_0 \) and \( \boldsymbol{z}_0 \) as
-
-
We are almost there, we have obtained a relation between minimizing
-the reconstruction error and the variance and the covariance
-matrix. Minimizing the error is equivalent to maximizing the variance
-of the projected data.
-
-
-
We could trivially maximize the variance of the projection (and
-thereby minimize the error in the reconstruction function) by letting
-the norm-2 of \( \boldsymbol{w}_0 \) go to infinity. However, this norm since we
-want the matrix \( \boldsymbol{W} \) to be an orthogonal matrix, is constrained by
-\( \vert\vert \boldsymbol{w}_0 \vert\vert_2^2=1 \). Imposing this condition via a
-Lagrange multiplier we can then in turn maximize
-
The direction that maximizes the variance (or minimizes the construction error) is an eigenvector of the covariance matrix! If we left multiply with \( \boldsymbol{w}_0^T \) we have the variance of the projected data is
If we want to maximize the variance (minimize the construction error)
-we simply pick the eigenvector of the covariance matrix with the
-largest eigenvalue. This establishes the link between the minimization
-of the reconstruction function \( J \) in terms of an orthogonal matrix
-and the maximization of the variance and thereby the covariance of our
-observations encoded in the design/feature matrix \( \boldsymbol{X} \).
-
-
-
The proof
-for the other eigenvectors \( \boldsymbol{w}_1,\boldsymbol{w}_2,\dots \) can be
-established by applying the above arguments and using the fact that
-our basis of eigenvectors is orthogonal, see Murphy chapter
-12.2. The
-discussion in chapter 12.2 of Murphy's text has also a nice link with
-the Singular Value Decomposition theorem. For categorical data, see
-chapter 12.4 and discussion therein.
-
Principal Component Analysis (PCA) is by far the most popular dimensionality reduction algorithm.
-First it identifies the hyperplane that lies closest to the data, and then it projects the data onto it.
-
-
-
The following Python code uses NumPy’s svd() function to obtain all the principal components of the
-training set, then extracts the first two principal components. First we center the data using either pandas or our own code
-
-
-
-
-
-
-
-
-
importnumpyasnp
-importpandasaspd
-fromIPython.displayimport display
-np.random.seed(100)
-# setting up a 10 x 5 vanilla matrix
-rows =10
-cols =5
-X = np.random.randn(rows,cols)
-df = pd.DataFrame(X)
-# Pandas does the centering for us
-df = df -df.mean()
-display(df)
-
-# we center it ourselves
-X_centered = X - X.mean(axis=0)
-# Then check the difference between pandas and our own set up
-print(X_centered-df)
-#Now we do an SVD
-U, s, V = np.linalg.svd(X_centered)
-c1 = V.T[:, 0]
-c2 = V.T[:, 1]
-W2 = V.T[:, :2]
-X2D = X_centered.dot(W2)
-print(X2D)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PCA assumes that the dataset is centered around the origin. Scikit-Learn’s PCA classes take care of centering
-the data for you. However, if you implement PCA yourself (as in the preceding example), or if you use other libraries, don’t
-forget to center the data first.
-
-
-
Once you have identified all the principal components, you can reduce the dimensionality of the dataset
-down to \( d \) dimensions by projecting it onto the hyperplane defined by the first \( d \) principal components.
-Selecting this hyperplane ensures that the projection will preserve as much variance as possible.
-
-
-
-
-
-
-
-
-
W2 = V.T[:, :2]
-X2D = X_centered.dot(W2)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PCA and scikit-learn
-
-
Scikit-Learn’s PCA class implements PCA using SVD decomposition just like we did before. The
-following code applies PCA to reduce the dimensionality of the dataset down to two dimensions (note
-that it automatically takes care of centering the data):
-
-
-
-
-
-
-
-
-
#thereafter we do a PCA with Scikit-learn
-fromsklearn.decompositionimport PCA
-pca = PCA(n_components =2)
-X2D = pca.fit_transform(X)
-print(X2D)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
After fitting the PCA transformer to the dataset, you can access the principal components using the
-components variable (note that it contains the PCs as horizontal vectors, so, for example, the first
-principal component is equal to
-
-
-
-
-
-
-
-
-
pca.components_.T[:, 0]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Another very useful piece of information is the explained variance ratio of each principal component,
-available via the \( explained\_variance\_ratio \) variable. It indicates the proportion of the dataset’s
-variance that lies along the axis of each principal component.
-
-
-
-
Back to the Cancer Data
-
We can now repeat the above but applied to real data, in this case our breast cancer data.
-Here we compute performance scores on the training data using logistic regression.
-
-
-
-
-
-
-
-
-
importmatplotlib.pyplotasplt
-importnumpyasnp
-fromsklearn.model_selectionimport train_test_split
-fromsklearn.datasetsimport load_breast_cancer
-fromsklearn.linear_modelimport LogisticRegression
-cancer = load_breast_cancer()
-
-X_train, X_test, y_train, y_test = train_test_split(cancer.data,cancer.target,random_state=0)
-
-logreg = LogisticRegression()
-logreg.fit(X_train, y_train)
-print("Train set accuracy from Logistic Regression: {:.2f}".format(logreg.score(X_train,y_train)))
-# We scale the data
-fromsklearn.preprocessingimport StandardScaler
-scaler = StandardScaler()
-scaler.fit(X_train)
-X_train_scaled = scaler.transform(X_train)
-X_test_scaled = scaler.transform(X_test)
-# Then perform again a log reg fit
-logreg.fit(X_train_scaled, y_train)
-print("Train set accuracy scaled data: {:.2f}".format(logreg.score(X_train_scaled,y_train)))
-#thereafter we do a PCA with Scikit-learn
-fromsklearn.decompositionimport PCA
-pca = PCA(n_components =2)
-X2D_train = pca.fit_transform(X_train_scaled)
-# and finally compute the log reg fit and the score on the training data
-logreg.fit(X2D_train,y_train)
-print("Train set accuracy scaled and PCA data: {:.2f}".format(logreg.score(X2D_train,y_train)))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
We see that our training data after the PCA decomposition has a performance similar to the non-scaled data.
-
-
Instead of arbitrarily choosing the number of dimensions to reduce down to, it is generally preferable to
-choose the number of dimensions that add up to a sufficiently large portion of the variance (e.g., 95%).
-Unless, of course, you are reducing dimensionality for data visualization — in that case you will
-generally want to reduce the dimensionality down to 2 or 3.
-The following code computes PCA without reducing dimensionality, then computes the minimum number
-of dimensions required to preserve 95% of the training set’s variance:
-
You could then set \( n\_components=d \) and run PCA again. However, there is a much better option: instead
-of specifying the number of principal components you want to preserve, you can set \( n\_components \) to be
-a float between 0.0 and 1.0, indicating the ratio of variance you wish to preserve:
-
One problem with the preceding implementation of PCA is that it requires the whole training set to fit in
-memory in order for the SVD algorithm to run. Fortunately, Incremental PCA (IPCA) algorithms have
-been developed: you can split the training set into mini-batches and feed an IPCA algorithm one minibatch
-at a time. This is useful for large training sets, and also to apply PCA online (i.e., on the fly, as new
-instances arrive).
-
-
Randomized PCA
-
-
Scikit-Learn offers yet another option to perform PCA, called Randomized PCA. This is a stochastic
-algorithm that quickly finds an approximation of the first d principal components. Its computational
-complexity is \( O(m \times d^2)+O(d^3) \), instead of \( O(m \times n^2) + O(n^3) \), so it is dramatically faster than the
-previous algorithms when \( d \) is much smaller than \( n \).
-
-
Kernel PCA
-
-
The kernel trick is a mathematical technique that implicitly maps instances into a
-very high-dimensional space (called the feature space), enabling nonlinear classification and regression
-with Support Vector Machines. Recall that a linear decision boundary in the high-dimensional feature
-space corresponds to a complex nonlinear decision boundary in the original space.
-It turns out that the same trick can be applied to PCA, making it possible to perform complex nonlinear
-projections for dimensionality reduction. This is called Kernel PCA (kPCA). It is often good at
-preserving clusters of instances after projection, or sometimes even unrolling datasets that lie close to a
-twisted manifold.
-For example, the following code uses Scikit-Learn’s KernelPCA class to perform kPCA with an
-
There are many other dimensionality reduction techniques, several of which are available in Scikit-Learn.
-
-
Here are some of the most popular:
-
-
Multidimensional Scaling (MDS) reduces dimensionality while trying to preserve the distances between the instances.
-
Isomap creates a graph by connecting each instance to its nearest neighbors, then reduces dimensionality while trying to preserve the geodesic distances between the instances.
-
t-Distributed Stochastic Neighbor Embedding (t-SNE) reduces dimensionality while trying to keep similar instances close and dissimilar instances apart. It is mostly used for visualization, in particular to visualize clusters of instances in high-dimensional space (e.g., to visualize the MNIST images in 2D).
-
Linear Discriminant Analysis (LDA) is actually a classification algorithm, but during training it learns the most discriminative axes between the classes, and these axes can then be used to define a hyperplane onto which to project the data. The benefit is that the projection will keep classes as far apart as possible, so LDA is a good technique to reduce dimensionality before running another classification algorithm such as a Support Vector Machine (SVM) classifier discussed in the SVM lectures.
Convolutional neural networks (CNNs) were developed during the last
+decade of the previous century, with a focus on character recognition
+tasks. Nowadays, CNNs are a central element in the spectacular success
+of deep learning methods. The success in for example image
+classifications have made them a central tool for most machine
+learning practitioners.
+
+
+
CNNs are very similar to ordinary Neural Networks.
+They are made up of neurons that have learnable weights and
+biases. Each neuron receives some inputs, performs a dot product and
+optionally follows it with a non-linearity. The whole network still
+expresses a single differentiable score function: from the raw image
+pixels on one end to class scores at the other. And they still have a
+loss function (for example Softmax) on the last (fully-connected) layer
+and all the tips/tricks we developed for learning regular Neural
+Networks still apply (back propagation, gradient descent etc etc).
+
+
+
+
+
What is the Difference
+
+
CNN architectures make the explicit assumption that
+the inputs are images, which allows us to encode certain properties
+into the architecture. These then make the forward function more
+efficient to implement and vastly reduce the amount of parameters in
+the network.
+
Neural networks are defined as affine transformations, that is
+a vector is received as input and is multiplied with a matrix of so-called weights (our unknown paramters) to produce an
+output (to which a bias vector is usually added before passing the result
+through a nonlinear activation function). This is applicable to any type of input, be it an
+image, a sound clip or an unordered collection of features: whatever their
+dimensionality, their representation can always be flattened into a vector
+before the transformation.
+
+
+
+
+
Why CNNS for images, sound files, medical images from CT scans etc?
+
+
However, when we consider images, sound clips and many other similar kinds of data, these data have an intrinsic
+structure. More formally, they share these important properties:
+
+
+
They are stored as multi-dimensional arrays (think of the pixels of a figure) .
+
They feature one or more axes for which ordering matters (e.g., width and height axes for an image, time axis for a sound clip).
+
One axis, called the channel axis, is used to access different views of the data (e.g., the red, green and blue channels of a color image, or the left and right channels of a stereo audio track).
+
+
These properties are not exploited when an affine transformation is applied; in
+fact, all the axes are treated in the same way and the topological information
+is not taken into account. Still, taking advantage of the implicit structure of
+the data may prove very handy in solving some tasks, like computer vision and
+speech recognition, and in these cases it would be best to preserve it. This is
+where discrete convolutions come into play.
+
+
+
A discrete convolution is a linear transformation that preserves this notion of
+ordering. It is sparse (only a few input units contribute to a given output
+unit) and reuses parameters (the same weights are applied to multiple locations
+in the input).
+
+
+
+
+
Regular NNs don’t scale well to full images
+
+
As an example, consider
+an image of size \( 32\times 32\times 3 \) (32 wide, 32 high, 3 color channels), so a
+single fully-connected neuron in a first hidden layer of a regular
+Neural Network would have \( 32\times 32\times 3 = 3072 \) weights. This amount still
+seems manageable, but clearly this fully-connected structure does not
+scale to larger images. For example, an image of more respectable
+size, say \( 200\times 200\times 3 \), would lead to neurons that have
+\( 200\times 200\times 3 = 120,000 \) weights.
+
+
+
We could have
+several such neurons, and the parameters would add up quickly! Clearly,
+this full connectivity is wasteful and the huge number of parameters
+would quickly lead to possible overfitting.
+
+
+
+
+
+
Figure 1: A regular 3-layer Neural Network.
+
+
+
+
+
+
+
3D volumes of neurons
+
+
Convolutional Neural Networks take advantage of the fact that the
+input consists of images and they constrain the architecture in a more
+sensible way.
+
+
+
In particular, unlike a regular Neural Network, the
+layers of a CNN have neurons arranged in 3 dimensions: width,
+height, depth. (Note that the word depth here refers to the third
+dimension of an activation volume, not to the depth of a full Neural
+Network, which can refer to the total number of layers in a network.)
+
+
+
To understand it better, the above example of an image
+with an input volume of
+activations has dimensions \( 32\times 32\times 3 \) (width, height,
+depth respectively).
+
+
+
The neurons in a layer will
+only be connected to a small region of the layer before it, instead of
+all of the neurons in a fully-connected manner. Moreover, the final
+output layer could for this specific image have dimensions \( 1\times 1 \times 10 \),
+because by the
+end of the CNN architecture we will reduce the full image into a
+single vector of class scores, arranged along the depth
+dimension.
+
+
+
+
+
+
Figure 2: A CNN arranges its neurons in three dimensions (width, height, depth), as visualized in one of the layers. Every layer of a CNN transforms the 3D input volume to a 3D output volume of neuron activations. In this example, the red input layer holds the image, so its width and height would be the dimensions of the image, and the depth would be 3 (Red, Green, Blue channels).
+
+
+
+
+
+
+
Layers used to build CNNs
+
+
A simple CNN is a sequence of layers, and every layer of a CNN
+transforms one volume of activations to another through a
+differentiable function. We use three main types of layers to build
+CNN architectures: Convolutional Layer, Pooling Layer, and
+Fully-Connected Layer (exactly as seen in regular Neural Networks). We
+will stack these layers to form a full CNN architecture.
+
+
+
A simple CNN for image classification could have the architecture:
+
+
+
INPUT (\( 32\times 32 \times 3 \)) will hold the raw pixel values of the image, in this case an image of width 32, height 32, and with three color channels R,G,B.
+
CONV (convolutional )layer will compute the output of neurons that are connected to local regions in the input, each computing a dot product between their weights and a small region they are connected to in the input volume. This may result in volume such as \( [32\times 32\times 12] \) if we decided to use 12 filters.
+
RELU layer will apply an elementwise activation function, such as the \( max(0,x) \) thresholding at zero. This leaves the size of the volume unchanged (\( [32\times 32\times 12] \)).
+
POOL (pooling) layer will perform a downsampling operation along the spatial dimensions (width, height), resulting in volume such as \( [16\times 16\times 12] \).
+
FC (i.e. fully-connected) layer will compute the class scores, resulting in volume of size \( [1\times 1\times 10] \), where each of the 10 numbers correspond to a class score, such as among the 10 categories of the MNIST images we considered above . As with ordinary Neural Networks and as the name implies, each neuron in this layer will be connected to all the numbers in the previous volume.
+
+
+
+
+
Transforming images
+
+
CNNs transform the original image layer by layer from the original
+pixel values to the final class scores.
+
+
+
Observe that some layers contain
+parameters and other don’t. In particular, the CNN layers perform
+transformations that are a function of not only the activations in the
+input volume, but also of the parameters (the weights and biases of
+the neurons). On the other hand, the RELU/POOL layers will implement a
+fixed function. The parameters in the CONV/FC layers will be trained
+with gradient descent so that the class scores that the CNN computes
+are consistent with the labels in the training set for each image.
+
However, both standard feed forwards networks and CNNs perform well on data with unknown length.
+
The textbook by Goodfellow et al, see chapter 9 contains an in depth discussion as well.
+
-
This is where recurrent nueral networks (RNNs) come to our rescue.
+
+
Key Idea
+
+
A dense neural network is representd by an affine operation (like matrix-matrix multiplication) where all parameters are included.
+
+
The key idea in CNNs for say imaging is that in images neighbor pixels tend to be related! So we connect
+only neighboring neurons in the input instead of connecting all with the first hidden layer.
+
+
+
We say we perform a filtering (convolution is the mathematical operation).
+
+
+
+
Mathematics of CNNs
+
+
The mathematics of CNNs is based on the mathematical operation of
+convolution. In mathematics (in particular in functional analysis),
+convolution is represented by mathematical operation (integration,
+summation etc) on two function in order to produce a third function
+that expresses how the shape of one gets modified by the other.
+Convolution has a plethora of applications in a variety of disciplines, spanning from statistics to signal processing, computer vision, solutions of differential equations,linear algebra, engineering, and yes, machine learning.
+
+
+
Mathematically, convolution is defined as follows (one-dimensional example):
+Let us define a continuous function \( y(t) \) given by
+
+
+$$
+y(t) = \int x(a) w(t-a) da,
+$$
+
+
+
where \( x(a) \) represents a so-called input and \( w(t-a) \) is normally called the weight function or kernel.
+
+
The above integral is written in a more compact form as
Computing the inverse of the above convolution operations is known as deconvolution.
+
+
How can we use this? And what does it mean? Let us study some familiar examples first.
+
+
+
+
Convolution Examples: Polynomial multiplication
+
+
We have already met such an example in project 1 when we tried to set
+up the design matrix for a two-dimensional function. This was an
+example of polynomial multiplication. Let us recast such a problem in terms of the convolution operation.
+Let us look a the following polynomials to second and third order, respectively:
+
Computing polynomial products can be implemented efficiently if we rewrite the more brute force multiplications using convolution.
+We note first that the new coefficients are given as
+
Do you see a potential drawback with these equations?
+
+
+
+
A more efficient way of coding the above Convolution
+
+
Since we only have a finite number of \( \alpha \) and \( \beta \) values
+which are non-zero, we can rewrite the above convolution expressions
+as a matrix-vector multiplication
+
The process is commutative and we can easily see that we can rewrite the multiplication in terms of a matrix holding \( \beta \) and a vector holding \( \alpha \).
+In this case we have
+
Note that the use of these matrices is for mathematical purposes only and not implementation purposes.
+When implementing the above equation we do not encode (and allocate memory) the matrices explicitely.
+We rather code the convolutions in the minimal memory footprint that they require.
+
+
+
Does the number of floating point operations change here when we use the commutative property?
+
+
+
+
Convolution Examples: Principle of Superposition and Periodic Forces (Fourier Transforms)
+
+
For problems with so-called harmonic oscillations, given by for example the following differential equation
where \( F(t) \) is an applied external force acting on the system (often called a driving force), one can use the theory of Fourier transformations to find the solutions of this type of equations.
+
+
If one has several driving forces, \( F(t)=\sum_n F_n(t) \), one can find
+the particular solution to each \( F_n \), \( x_{pn}(t) \), and the particular
+solution for the entire driving force is then given by a series like
+
This is known as the principle of superposition. It only applies when
+the homogenous equation is linear. If there were an anharmonic term
+such as \( x^3 \) in the homogenous equation, then when one summed various
+solutions, \( x=(\sum_n x_n)^2 \), one would get cross
+terms. Superposition is especially useful when \( F(t) \) can be written
+as a sum of sinusoidal terms, because the solutions for each
+sinusoidal (sine or cosine) term is analytic.
+
+
+
Driving forces are often periodic, even when they are not
+sinusoidal. Periodicity implies that for some time \( \tau \)
+
One example of a non-sinusoidal periodic force is a square wave. Many
+components in electric circuits are non-linear, e.g. diodes, which
+makes many wave forms non-sinusoidal even when the circuits are being
+driven by purely sinusoidal sources.
+
+
+
+
+
Simple Code Example
+
+
The code here shows a typical example of such a square wave generated using the functionality included in the scipy Python package. We have used a period of \( \tau=0.2 \).
+
+
+
+
+
+
+
+
+
importnumpyasnp
+importmath
+fromscipyimport signal
+importmatplotlib.pyplotasplt
+
+# number of points
+n = 500
+# start and final times
+t0 = 0.0
+tn = 1.0
+# Period
+t = np.linspace(t0, tn, n, endpoint=False)
+SqrSignal = np.zeros(n)
+SqrSignal = 1.0+signal.square(2*np.pi*5*t)
+plt.plot(t, SqrSignal)
+plt.ylim(-0.5, 2.5)
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
For the sinusoidal example the
+period is \( \tau=2\pi/\omega \). However, higher harmonics can also
+satisfy the periodicity requirement. In general, any force that
+satisfies the periodicity requirement can be expressed as a sum over
+harmonics,
+
We can write down the answer for
+\( x_{pn}(t) \), by substituting \( f_n/m \) or \( g_n/m \) for \( F_0/m \). By
+writing each factor \( 2n\pi t/\tau \) as \( n\omega t \), with \( \omega\equiv
+2\pi/\tau \),
+
Because the forces have been applied for a long time, any non-zero
+damping eliminates the homogenous parts of the solution, so one need
+only consider the particular solution for each \( n \).
+
+
+
The problem is considered solved if one can find expressions for the
+coefficients \( f_n \) and \( g_n \), even though the solutions are expressed
+as an infinite sum. The coefficients can be extracted from the
+function \( F(t) \) by
+
To check the consistency of these expressions and to verify
+Eq. (4), one can insert the expansion of \( F(t) \) in
+Eq. (3) into the expression for the coefficients in
+Eq. (4) and see whether
+
Immediately, one can throw away all the terms with \( g_m \) because they
+convolute an even and an odd function. The term with \( f_0/2 \)
+disappears because \( \cos(n\omega t) \) is equally positive and negative
+over the interval and will integrate to zero. For all the terms
+\( f_m\cos(m\omega t) \) appearing in the sum, one can use angle addition
+formulas to see that \( \cos(m\omega t)\cos(n\omega
+t)=(1/2)(\cos[(m+n)\omega t]+\cos[(m-n)\omega t] \). This will integrate
+to zero unless \( m=n \). In that case the \( m=n \) term gives
+
The same method can be used to check for the consistency of \( g_n \).
+
+
+
+
Final words on Fourier Transforms
+
+
The code here uses the Fourier series applied to a
+square wave signal. The code here
+visualizes the various approximations given by Fourier series compared
+with a square wave with period \( T=0.2 \) (dimensionless time), width \( 0.1 \) and max value of the force \( F=2 \). We
+see that when we increase the number of components in the Fourier
+series, the Fourier series approximation gets closer and closer to the
+square wave signal.
+
+
+
+
+
+
+
+
+
+
importnumpyasnp
+importmath
+fromscipyimport signal
+importmatplotlib.pyplotasplt
+
+# number of points
+n = 500
+# start and final times
+t0 = 0.0
+tn = 1.0
+# Period
+T =0.2
+# Max value of square signal
+Fmax= 2.0
+# Width of signal
+Width = 0.1
+t = np.linspace(t0, tn, n, endpoint=False)
+SqrSignal = np.zeros(n)
+FourierSeriesSignal = np.zeros(n)
+SqrSignal = 1.0+signal.square(2*np.pi*5*t+np.pi*Width/T)
+a0 = Fmax*Width/T
+FourierSeriesSignal = a0
+Factor = 2.0*Fmax/np.pi
+for i inrange(1,500):
+ FourierSeriesSignal += Factor/(i)*np.sin(np.pi*i*Width/T)*np.cos(i*t*2*np.pi/T)
+plt.plot(t, SqrSignal)
+plt.plot(t, FourierSeriesSignal)
+plt.ylim(-0.5, 2.5)
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Two-dimensional Objects
+
+
We often use convolutions over more than one dimension at a time. If
+we have a two-dimensional image \( I \) as input, we can have a filter
+defined by a two-dimensional kernel \( K \). This leads to an output \( S \)
+
Normally the latter is more straightforward to implement in a machine elarning library since there is less variation in the range of values of \( m \) and \( n \).
+
+
+
+
Cross-Correlation
+
+
Many deep learning libraries implement cross-correlation instead of convolution
In feilds like signal processing (and imaging as well), one designs
+so-called filters. These filters are defined by the convolutions and
+are often hand-crafted. One may specify filters for smoothing, edge
+detection, frequency reshaping, and similar operations. However with
+neural networks the idea is to automatically learn the filters and use
+many of them in conjunction with non-linear operations (activation
+functions).
+
+
+
As an example consider a neural network operating on sound sequence
+data. Assume that we an input vector \( \boldsymbol{x} \) of length \( d=10^6 \). We
+construct then a neural network with onle hidden layer only with
+\( 10^4 \) nodes. This means that we will have a weight matrix with
+\( 10^4\times 10^6=10^{10} \) weights to be determined, together with \( 10^4 \) biases.
+
+
+
Assume furthermore that we have an output layer which is meant to train whether the sound sequence represents a human voice (true) or something else (false).
+It means that we have only one output node. But since this output node connects to \( 10^4 \) nodes in the hidden layer, there are in total \( 10^4 \) weights to be determined for the output layer, plus one bias. In total we have
+
In today’s architecture one can train such neural networks, however
+this is a huge number of parameters for the task at hand. In general,
+it is a very wasteful and inefficient use of dense matrices as
+parameters. Just as importantly, such trained network parameters are
+very specific for the type of input data on which they were trained
+and the network is not likely to generalize easily to variations in
+the input.
+
+
+
The main principles that justify convolutions is locality of
+information and repetion of patterns within the signal. Sound samples
+of the input in adjacent spots are much more likely to affect each
+other than those that are very far away. Similarly, sounds are
+repeated in multiple times in the signal. While slightly simplistic,
+reasoning about such a sound example demonstrates this. The same
+principles then apply to images and other similar data.
+
CNNs in more detail, building convolutional neural networks in Tensorflow and Keras
+
+
As discussed above, CNNs are neural networks built from the assumption that the inputs
+to the network are 2D images. This is important because the number of features or pixels in images
+grows very fast with the image size, and an enormous number of weights and biases are needed in order to build an accurate network.
+
+
+
As before, we still have our input, a hidden layer and an output. What's novel about convolutional networks
+are the convolutional and pooling layers stacked in pairs between the input and the hidden layer.
+In addition, the data is no longer represented as a 2D feature matrix, instead each input is a number of 2D
+matrices, typically 1 for each color dimension (Red, Green, Blue).
+
+
+
+
+
Setting it up
+
+
It means that to represent the entire
+dataset of images, we require a 4D matrix or tensor. This tensor has the dimensions:
+
The MNIST dataset consists of grayscale images with a pixel size of
+\( 28\times 28 \), meaning we require \( 28 \times 28 = 724 \) weights to each
+neuron in the first hidden layer.
+
+
+
If we were to analyze images of size \( 128\times 128 \) we would require
+\( 128 \times 128 = 16384 \) weights to each neuron. Even worse if we were
+dealing with color images, as most images are, we have an image matrix
+of size \( 128\times 128 \) for each color dimension (Red, Green, Blue),
+meaning 3 times the number of weights \( = 49152 \) are required for every
+single neuron in the first hidden layer.
+
+
+
+
+
Strong correlations
+
+
Images typically have strong local correlations, meaning that a small
+part of the image varies little from its neighboring regions. If for
+example we have an image of a blue car, we can roughly assume that a
+small blue part of the image is surrounded by other blue regions.
+
+
+
Therefore, instead of connecting every single pixel to a neuron in the
+first hidden layer, as we have previously done with deep neural
+networks, we can instead connect each neuron to a small part of the
+image (in all 3 RGB depth dimensions). The size of each small area is
+fixed, and known as a receptive.
+
+
+
+
+
Layers of a CNN
+
The layers of a convolutional neural network arrange neurons in 3D: width, height and depth.
+The input image is typically a square matrix of depth 3.
+
+
+
A convolution is performed on the image which outputs
+a 3D volume of neurons. The weights to the input are arranged in a number of 2D matrices, known as filters.
+
+
+
Each filter slides along the input image, taking the dot product
+between each small part of the image and the filter, in all depth
+dimensions. This is then passed through a non-linear function,
+typically the Rectified Linear (ReLu) function, which serves as the
+activation of the neurons in the first convolutional layer. This is
+further passed through a pooling layer, which reduces the size of the
+convolutional layer, e.g. by taking the maximum or average across some
+small regions, and this serves as input to the next convolutional
+layer.
+
+
+
+
+
Systematic reduction
+
+
By systematically reducing the size of the input volume, through
+convolution and pooling, the network should create representations of
+small parts of the input, and then from them assemble representations
+of larger areas. The final pooling layer is flattened to serve as
+input to a hidden layer, such that each neuron in the final pooling
+layer is connected to every single neuron in the hidden layer. This
+then serves as input to the output layer, e.g. a softmax output for
+classification.
+
+
+
+
+
Prerequisites: Collect and pre-process data
+
+
+
+
+
+
+
+
# import necessary packages
+importnumpyasnp
+importmatplotlib.pyplotasplt
+fromsklearnimport datasets
+
+
+# ensure the same random numbers appear every time
+np.random.seed(0)
+
+# display images in notebook
+%matplotlib inline
+plt.rcParams['figure.figsize'] = (12,12)
+
+
+# download MNIST dataset
+digits = datasets.load_digits()
+
+# define inputs and labels
+inputs = digits.images
+labels = digits.target
+
+# RGB images have a depth of 3
+# our images are grayscale so they should have a depth of 1
+inputs = inputs[:,:,:,np.newaxis]
+
+print("inputs = (n_inputs, pixel_width, pixel_height, depth) = " + str(inputs.shape))
+print("labels = (n_inputs) = " + str(labels.shape))
+
+
+# choose some random images to display
+n_inputs = len(inputs)
+indices = np.arange(n_inputs)
+random_indices = np.random.choice(indices, size=5)
+
+for i, image inenumerate(digits.images[random_indices]):
+ plt.subplot(1, 5, i+1)
+ plt.axis('off')
+ plt.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')
+ plt.title("Label: %d" % digits.target[random_indices[i]])
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Importing Keras and Tensorflow
+
+
+
+
+
+
+
+
fromtensorflow.kerasimport datasets, layers, models
+fromtensorflow.keras.layersimport Input
+fromtensorflow.keras.modelsimport Sequential #This allows appending layers to existing models
+fromtensorflow.keras.layersimport Dense #This allows defining the characteristics of a particular layer
+fromtensorflow.kerasimport optimizers #This allows using whichever optimiser we want (sgd,adam,RMSprop)
+fromtensorflow.kerasimport regularizers #This allows using whichever regularizer we want (l1,l2,l1_l2)
+fromtensorflow.keras.utilsimport to_categorical #This allows using categorical cross entropy as the cost function
+#from tensorflow.keras import Conv2D
+#from tensorflow.keras import MaxPooling2D
+#from tensorflow.keras import Flatten
+
+fromsklearn.model_selectionimport train_test_split
+
+# representation of labels
+labels = to_categorical(labels)
+
+# split into train and test data
+# one-liner from scikit-learn library
+train_size = 0.8
+test_size = 1 - train_size
+X_train, X_test, Y_train, Y_test = train_test_split(inputs, labels, train_size=train_size,
+ test_size=test_size)
+
The CIFAR10 dataset contains 60,000 color images in 10 classes, with
+6,000 images in each class. The dataset is divided into 50,000
+training images and 10,000 testing images. The classes are mutually
+exclusive and there is no overlap between them.
+
+
+
+
+
+
+
+
+
+
importtensorflowastf
+
+fromtensorflow.kerasimport datasets, layers, models
+importmatplotlib.pyplotasplt
+
+# We import the data set
+(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()
+
+# Normalize pixel values to be between 0 and 1 by dividing by 255.
+train_images, test_images = train_images / 255.0, test_images / 255.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Verifying the data set
+
+
To verify that the dataset looks correct, let's plot the first 25 images from the training set and display the class name below each image.
+
+
+
+
+
+
+
+
+
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
+ 'dog', 'frog', 'horse', 'ship', 'truck']
+
+plt.figure(figsize=(10,10))
+for i inrange(25):
+ plt.subplot(5,5,i+1)
+ plt.xticks([])
+ plt.yticks([])
+ plt.grid(False)
+ plt.imshow(train_images[i], cmap=plt.cm.binary)
+ # The CIFAR labels happen to be arrays,
+ # which is why you need the extra index
+ plt.xlabel(class_names[train_labels[i][0]])
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Set up the model
+
+
The 6 lines of code below define the convolutional base using a common pattern: a stack of Conv2D and MaxPooling2D layers.
+
+
As input, a CNN takes tensors of shape (image_height, image_width, color_channels), ignoring the batch size. If you are new to these dimensions, color_channels refers to (R,G,B). In this example, you will configure our CNN to process inputs of shape (32, 32, 3), which is the format of CIFAR images. You can do this by passing the argument input_shape to our first layer.
+
+
+
+
+
+
+
+
+
model = models.Sequential()
+model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
+model.add(layers.MaxPooling2D((2, 2)))
+model.add(layers.Conv2D(64, (3, 3), activation='relu'))
+model.add(layers.MaxPooling2D((2, 2)))
+model.add(layers.Conv2D(64, (3, 3), activation='relu'))
+
+# Let's display the architecture of our model so far.
+
+model.summary()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
You can see that the output of every Conv2D and MaxPooling2D layer is a 3D tensor of shape (height, width, channels). The width and height dimensions tend to shrink as you go deeper in the network. The number of output channels for each Conv2D layer is controlled by the first argument (e.g., 32 or 64). Typically, as the width and height shrink, you can afford (computationally) to add more output channels in each Conv2D layer.
+
+
+
+
Add Dense layers on top
+
+
To complete our model, you will feed the last output tensor from the
+convolutional base (of shape (4, 4, 64)) into one or more Dense layers
+to perform classification. Dense layers take vectors as input (which
+are 1D), while the current output is a 3D tensor. First, you will
+flatten (or unroll) the 3D output to 1D, then add one or more Dense
+layers on top. CIFAR has 10 output classes, so you use a final Dense
+layer with 10 outputs and a softmax activation.
+
+
+
+
+
+
+
+
+
+
model.add(layers.Flatten())
+model.add(layers.Dense(64, activation='relu'))
+model.add(layers.Dense(10))
+Here's the complete architecture of our model.
+
+model.summary()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
As you can see, our (4, 4, 64) outputs were flattened into vectors of shape (1024) before going through two Dense layers.
@@ -1191,7 +2547,7 @@ approximation of a partition function. In the case where
$$
\begin{equation}
\underset{d}{\mathrm{max}}v(\theta^{(g)}, \theta^{(d)})
-\tag{7}
+\tag{12}
\end{equation}
$$
Basic ideas of the Principal Component Analysis (PCA)
-
-
The principal component analysis deals with the problem of fitting a
-low-dimensional affine subspace \( S \) of dimension \( d \) much smaller than
-the total dimension \( D \) of the problem at hand (our data
-set). Mathematically it can be formulated as a statistical problem or
-a geometric problem. In our discussion of the theorem for the
-classical PCA, we will stay with a statistical approach.
-Historically, the PCA was first formulated in a statistical setting in order to estimate the principal component of a multivariate random variable.
-
-
-
We have a data set defined by a design/feature matrix \( \boldsymbol{X} \) (see below for its definition)
-
-
Each data point is determined by \( p \) extrinsic (measurement) variables
-
We may want to ask the following question: Are there fewer intrinsic variables (say \( d < < p \)) that still approximately describe the data?
-
If so, these intrinsic variables may tell us something important and finding these intrinsic variables is what dimension reduction methods do.
Introducing the Covariance and Correlation functions
-
-
Before we discuss the PCA theorem, we need to remind ourselves about
-the definition of the covariance and the correlation function. These are quantities
-
-
-
Suppose we have defined two vectors
-\( \hat{x} \) and \( \hat{y} \) with \( n \) elements each. The covariance matrix \( \boldsymbol{C} \) is defined as
-
The covariance takes values between zero and infinity and may thus
-lead to problems with loss of numerical precision for particularly
-large values. It is common to scale the covariance matrix by
-introducing instead the correlation matrix defined via the so-called
-correlation function
-
The correlation function is then given by values \( \mathrm{corr}[\boldsymbol{x},\boldsymbol{y}]
-\in [-1,1] \). This avoids eventual problems with too large values. We
-can then define the correlation matrix for the two vectors \( \boldsymbol{x} \)
-and \( \boldsymbol{y} \) as
-
In the above example this is the function we constructed using pandas.
-
-
-
-
Reminding ourselves about Linear Regression
-
In our derivation of the various regression algorithms like Ordinary Least Squares or Ridge regression
-we defined the design/feature matrix \( \boldsymbol{X} \) as
-
with \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \), with the predictors/features \( p \) refering to the column numbers and the
-entries \( n \) being the row elements.
-We can rewrite the design/feature matrix in terms of its column vectors as
-
With these definitions, we can now rewrite our \( 2\times 2 \)
-correlation/covariance matrix in terms of a moe general design/feature
-matrix \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \). This leads to a \( p\times p \)
-covariance matrix for the vectors \( \boldsymbol{x}_i \) with \( i=0,1,\dots,p-1 \)
-
The Numpy function np.cov calculates the covariance elements using
-the factor \( 1/(n-1) \) instead of \( 1/n \) since it assumes we do not have
-the exact mean values. The following simple function uses the
-np.vstack function which takes each vector of dimension \( 1\times n \)
-and produces a \( 2\times n \) matrix \( \boldsymbol{W} \)
-
which in turn is converted into into the \( 2\times 2 \) covariance matrix
-\( \boldsymbol{C} \) via the Numpy function np.cov(). We note that we can also calculate
-the mean value of each set of samples \( \boldsymbol{x} \) etc using the Numpy
-function np.mean(x). We can also extract the eigenvalues of the
-covariance matrix through the np.linalg.eig() function.
-
The previous example can be converted into the correlation matrix by
-simply scaling the matrix elements with the variances. We should also
-subtract the mean values for each column. This leads to the following
-code which sets up the correlations matrix for the previous example in
-a more brute force way. Here we scale the mean values for each column of the design matrix, calculate the relevant mean values and variances and then finally set up the \( 2\times 2 \) correlation matrix (since we have only two vectors).
-
-
-
-
-
-
-
-
-
-
importnumpyasnp
-n = 100
-# define two vectors
-x = np.random.random(size=n)
-y = 4+3*x+np.random.normal(size=n)
-#scaling the x and y vectors
-x = x - np.mean(x)
-y = y - np.mean(y)
-variance_x = np.sum(x@x)/n
-variance_y = np.sum(y@y)/n
-print(variance_x)
-print(variance_y)
-cov_xy = np.sum(x@y)/n
-cov_xx = np.sum(x@x)/n
-cov_yy = np.sum(y@y)/n
-C = np.zeros((2,2))
-C[0,0]= cov_xx/variance_x
-C[1,1]= cov_yy/variance_y
-C[0,1]= cov_xy/np.sqrt(variance_y*variance_x)
-C[1,0]= C[0,1]
-print(C)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
We see that the matrix elements along the diagonal are one as they
-should be and that the matrix is symmetric. Furthermore, diagonalizing
-this matrix we easily see that it is a positive definite matrix.
-
-
-
The above procedure with numpy can be made more compact if we use pandas.
-
-
-
-
Using Pandas
-
-
We whow here how we can set up the correlation matrix using pandas, as done in this simple code
We expand this model to the Franke function discussed above.
-
-
-
-
-
-
-
-
-
# Common imports
-importnumpyasnp
-importpandasaspd
-
-
-defFrankeFunction(x,y):
- term1 = 0.75*np.exp(-(0.25*(9*x-2)**2) - 0.25*((9*y-2)**2))
- term2 = 0.75*np.exp(-((9*x+1)**2)/49.0 - 0.1*(9*y+1))
- term3 = 0.5*np.exp(-(9*x-7)**2/4.0 - 0.25*((9*y-3)**2))
- term4 = -0.2*np.exp(-(9*x-4)**2 - (9*y-7)**2)
- return term1 + term2 + term3 + term4
-
-
-defcreate_X(x, y, n ):
- iflen(x.shape) > 1:
- x = np.ravel(x)
- y = np.ravel(y)
-
- N = len(x)
- l = int((n+1)*(n+2)/2) # Number of elements in beta
- X = np.ones((N,l))
-
- for i inrange(1,n+1):
- q = int((i)*(i+1)/2)
- for k inrange(i+1):
- X[:,q+k] = (x**(i-k))*(y**k)
-
- return X
-
-
-# Making meshgrid of datapoints and compute Franke's function
-n = 4
-N = 100
-x = np.sort(np.random.uniform(0, 1, N))
-y = np.sort(np.random.uniform(0, 1, N))
-z = FrankeFunction(x, y)
-X = create_X(x, y, n=n)
-
-Xpd = pd.DataFrame(X)
-# subtract the mean values and set up the covariance matrix
-Xpd = Xpd - Xpd.mean()
-covariance_matrix = Xpd.cov()
-print(covariance_matrix)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
We note here that the covariance is zero for the first rows and
-columns since all matrix elements in the design matrix were set to one
-(we are fitting the function in terms of a polynomial of degree \( n \)). We would however not include the intercept
-and wee can simply
-drop these elements and construct a correlation
-matrix without them by centering our matrix elements by subtracting the mean of each column.
-
-
-
-
-
Lnks with the Design Matrix
-
-
We can rewrite the covariance matrix in a more compact form in terms of the design/feature matrix \( \boldsymbol{X} \) as
Let us now assume that we can perform a series of orthogonal transformations where we employ some orthogonal matrices \( \boldsymbol{S} \).
-These matrices are defined as \( \boldsymbol{S}\in {\mathbb{R}}^{p\times p} \) and obey the orthogonality requirements \( \boldsymbol{S}\boldsymbol{S}^T=\boldsymbol{S}^T\boldsymbol{S}=\boldsymbol{I} \). The matrix can be written out in terms of the column vectors \( \boldsymbol{s}_i \) as \( \boldsymbol{S}=[\boldsymbol{s}_0,\boldsymbol{s}_1,\dots,\boldsymbol{s}_{p-1}] \) and \( \boldsymbol{s}_i \in {\mathbb{R}}^{p} \).
-
-
-
Assume also that there is a transformation \( \boldsymbol{S}^T\boldsymbol{C}[\boldsymbol{x}]\boldsymbol{S}=\boldsymbol{C}[\boldsymbol{y}] \) such that the new matrix \( \boldsymbol{C}[\boldsymbol{y}] \) is diagonal with elements \( [\lambda_0,\lambda_1,\lambda_2,\dots,\lambda_{p-1}] \).
In the derivation of the PCA theorem we will assume that the eigenvalues are ordered in descending order, that is
-\( \lambda_0 > \lambda_1 > \dots > \lambda_{p-1} \).
-
-
-
The eigenvalues tell us then how much we need to stretch the
-corresponding eigenvectors. Dimensions with large eigenvalues have
-thus large variations (large variance) and define therefore useful
-dimensions. The data points are more spread out in the direction of
-these eigenvectors. Smaller eigenvalues mean on the other hand that
-the corresponding eigenvectors are shrunk accordingly and the data
-points are tightly bunched together and there is not much variation in
-these specific directions. Hopefully then we could leave it out
-dimensions where the eigenvalues are very small. If \( p \) is very large,
-we could then aim at reducing \( p \) to \( l < < p \) and handle only \( l \)
-features/predictors.
-
-
-
-
-
The Algorithm before theorem
-
-
Here's how we would proceed in setting up the algorithm for the PCA, see also discussion below here.
-
-
Set up the datapoints for the design/feature matrix \( \boldsymbol{X} \) with \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \), with the predictors/features \( p \) referring to the column numbers and the entries \( n \) being the row elements.
Center the data by subtracting the mean value for each column. This leads to a new matrix \( \boldsymbol{X}\rightarrow \overline{\boldsymbol{X}} \).
-
Compute then the covariance/correlation matrix \( \mathbb{E}[\overline{\boldsymbol{X}}^T\overline{\boldsymbol{X}}] \).
-
Find the eigenpairs of \( \boldsymbol{C} \) with eigenvalues \( [\lambda_0,\lambda_1,\dots,\lambda_{p-1}] \) and eigenvectors \( [\boldsymbol{s}_0,\boldsymbol{s}_1,\dots,\boldsymbol{s}_{p-1}] \).
-
Order the eigenvalue (and the eigenvectors accordingly) in order of decreasing eigenvalues.
-
Keep only those \( l \) eigenvalues larger than a selected threshold value, discarding thus \( p-l \) features since we expect small variations in the data here.
-
-
-
-
-
Writing our own PCA code
-
-
We will use a simple example first with two-dimensional data
-drawn from a multivariate normal distribution with the following mean and covariance matrix (we have fixed these quantities but will play around with them below):
-
Note that the mean refers to each column of data.
-We will generate \( n = 10000 \) points \( X = \{ x_1, \ldots, x_N \} \) from
-this distribution, and store them in the \( 1000 \times 2 \) matrix \( \boldsymbol{X} \). This is our design matrix where we have forced the covariance and mean values to take specific values.
-
-
-
-
-
Implementing it
-
The following Python code aids in setting up the data and writing out the design matrix.
-Note that the function multivariate returns also the covariance discussed above and that it is defined by dividing by \( n-1 \) instead of \( n \).
-
Now we are going to implement the PCA algorithm. We will break it down into various substeps.
-
-
-
-
First Step
-
-
The first step of PCA is to compute the sample mean of the data and use it to center the data. Recall that the sample mean is
-
-$$
-\mu_n = \frac{1}{n} \sum_{i=1}^n x_i
-$$
-
-
-
and the mean-centered data \( \bar{X} = \{ \bar{x}_1, \ldots, \bar{x}_n \} \) takes the form
-
-$$
-\bar{x}_i = x_i - \mu_n.
-$$
-
-
-
When you are done with these steps, print out \( \mu_n \) to verify it is
-close to \( \mu \) and plot your mean centered data to verify it is
-centered at the origin!
-The following code elements perform these operations using pandas or using our own functionality for doing so. The latter, using numpy is rather simple through the mean() function.
-
-
-
-
-
-
-
-
-
df = pd.DataFrame(X)
-# Pandas does the centering for us
-df = df -df.mean()
-# we center it ourselves
-X_centered = X - X.mean(axis=0)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Scaling
-
Alternatively, we could use the functions we discussed
-earlier for scaling the data set. That is, we could have used the
-StandardScaler function in Scikit-Learn, a function which ensures
-that for each feature/predictor we study the mean value is zero and
-the variance is one (every column in the design/feature matrix). You
-would then not get the same results, since we divide by the
-variance. The diagonal covariance matrix elements will then be one,
-while the non-diagonal ones need to be divided by \( 2\sqrt{2} \) for our
-specific case.
-
-
-
-
-
Centered Data
-
-
Now we are going to use the mean centered data to compute the sample covariance of the data by using the following equation
where the data points \( x_i \in \mathbb{R}^p \) (here in this example \( p = 2 \)) are column vectors and \( x^T \) is the transpose of \( x \).
-We can write our own code or simply use either the functionaly of numpy or that of pandas, as follows
-
-
-
-
-
-
-
-
-
print(df.cov())
-print(np.cov(X_centered.T))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Note that the way we define the covariance matrix here has a factor \( n-1 \) instead of \( n \). This is included in the cov() function by numpy and pandas.
-Our own code here is not very elegant and asks for obvious improvements. It is tailored to this specific \( 2\times 2 \) covariance matrix.
-
-
-
-
-
-
-
-
-
# extract the relevant columns from the centered design matrix of dim n x 2
-x = X_centered[:,0]
-y = X_centered[:,1]
-Cov = np.zeros((2,2))
-Cov[0,1] = np.sum(x.T@y)/(n-1.0)
-Cov[0,0] = np.sum(x.T@x)/(n-1.0)
-Cov[1,1] = np.sum(y.T@y)/(n-1.0)
-Cov[1,0]= Cov[0,1]
-print("Centered covariance using own code")
-print(Cov)
-plt.plot(x, y, 'x')
-plt.axis('equal')
-plt.show()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Exploring
-
-
Depending on the number of points \( n \), we will get results that are close to the covariance values defined above.
-The plot shows how the data are clustered around a line with slope close to one. Is this expected? Try to change the covariance and the mean values. For example, try to make the variance of the first element much larger than that of the second diagonal element. Try also to shrink the covariance (the non-diagonal elements) and see how the data points are distributed.
-
-
-
-
-
Diagonalize the sample covariance matrix to obtain the principal components
-
-
Now we are ready to solve for the principal components! To do so we
-diagonalize the sample covariance matrix \( \Sigma \). We can use the
-function np.linalg.eig to do so. It will return the eigenvalues and
-eigenvectors of \( \Sigma \). Once we have these we can perform the
-following tasks:
-
-
-
-
We compute the percentage of the total variance captured by the first principal component
-
We plot the mean centered data and lines along the first and second principal components
-
Then we project the mean centered data onto the first and second principal components, and plot the projected data.
Collecting all these steps we can write our own PCA function and
-compare this with the functionality included in Scikit-Learn.
-
-
-
The code here outlines some of the elements we could include in the
-analysis. Feel free to extend upon this in order to address the above
-questions.
-
-
-
-
-
-
-
-
-
-
# diagonalize and obtain eigenvalues, not necessarily sorted
-EigValues, EigVectors = np.linalg.eig(Cov)
-# sort eigenvectors and eigenvalues
-#permute = EigValues.argsort()
-#EigValues = EigValues[permute]
-#EigVectors = EigVectors[:,permute]
-print("Eigenvalues of Covariance matrix")
-for i inrange(2):
- print(EigValues[i])
-FirstEigvector = EigVectors[:,0]
-SecondEigvector = EigVectors[:,1]
-print("First eigenvector")
-print(FirstEigvector)
-print("Second eigenvector")
-print(SecondEigvector)
-#thereafter we do a PCA with Scikit-learn
-fromsklearn.decompositionimport PCA
-pca = PCA(n_components = 2)
-X2Dsl = pca.fit_transform(X)
-print("Eigenvector of largest eigenvalue")
-print(pca.components_.T[:, 0])
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
This code does not contain all the above elements, but it shows how we can use Scikit-Learn to extract the eigenvector which corresponds to the largest eigenvalue. Try to address the questions we pose before the above code. Try also to change the values of the covariance matrix by making one of the diagonal elements much larger than the other. What do you observe then?
-
-
-
-
Classical PCA Theorem
-
-
We assume now that we have a design matrix \( \boldsymbol{X} \) which has been
-centered as discussed above. For the sake of simplicity we skip the
-overline symbol. The matrix is defined in terms of the various column
-vectors \( [\boldsymbol{x}_0,\boldsymbol{x}_1,\dots, \boldsymbol{x}_{p-1}] \) each with dimension
-\( \boldsymbol{x}\in {\mathbb{R}}^{n} \).
-
-
-
The PCA theorem states that minimizing the above reconstruction error
-corresponds to setting \( \boldsymbol{W}=\boldsymbol{S} \), the orthogonal matrix which
-diagonalizes the empirical covariance(correlation) matrix. The optimal
-low-dimensional encoding of the data is then given by a set of vectors
-\( \boldsymbol{z}_i \) with at most \( l \) vectors, with \( l < < p \), defined by the
-orthogonal projection of the data onto the columns spanned by the
-eigenvectors of the covariance(correlations matrix).
-
-
-
-
-
The PCA Theorem
-
-
To show the PCA theorem let us start with the assumption that there is one vector \( \boldsymbol{s}_0 \) which corresponds to a solution which minimized the reconstruction error \( J \). This is an orthogonal vector. It means that we now approximate the reconstruction error in terms of \( \boldsymbol{w}_0 \) and \( \boldsymbol{z}_0 \) as
-
-
We are almost there, we have obtained a relation between minimizing
-the reconstruction error and the variance and the covariance
-matrix. Minimizing the error is equivalent to maximizing the variance
-of the projected data.
-
-
-
We could trivially maximize the variance of the projection (and
-thereby minimize the error in the reconstruction function) by letting
-the norm-2 of \( \boldsymbol{w}_0 \) go to infinity. However, this norm since we
-want the matrix \( \boldsymbol{W} \) to be an orthogonal matrix, is constrained by
-\( \vert\vert \boldsymbol{w}_0 \vert\vert_2^2=1 \). Imposing this condition via a
-Lagrange multiplier we can then in turn maximize
-
The direction that maximizes the variance (or minimizes the construction error) is an eigenvector of the covariance matrix! If we left multiply with \( \boldsymbol{w}_0^T \) we have the variance of the projected data is
If we want to maximize the variance (minimize the construction error)
-we simply pick the eigenvector of the covariance matrix with the
-largest eigenvalue. This establishes the link between the minimization
-of the reconstruction function \( J \) in terms of an orthogonal matrix
-and the maximization of the variance and thereby the covariance of our
-observations encoded in the design/feature matrix \( \boldsymbol{X} \).
-
-
-
The proof
-for the other eigenvectors \( \boldsymbol{w}_1,\boldsymbol{w}_2,\dots \) can be
-established by applying the above arguments and using the fact that
-our basis of eigenvectors is orthogonal, see Murphy chapter
-12.2. The
-discussion in chapter 12.2 of Murphy's text has also a nice link with
-the Singular Value Decomposition theorem. For categorical data, see
-chapter 12.4 and discussion therein.
-
Principal Component Analysis (PCA) is by far the most popular dimensionality reduction algorithm.
-First it identifies the hyperplane that lies closest to the data, and then it projects the data onto it.
-
-
-
The following Python code uses NumPy’s svd() function to obtain all the principal components of the
-training set, then extracts the first two principal components. First we center the data using either pandas or our own code
-
-
-
-
-
-
-
-
-
importnumpyasnp
-importpandasaspd
-fromIPython.displayimport display
-np.random.seed(100)
-# setting up a 10 x 5 vanilla matrix
-rows = 10
-cols = 5
-X = np.random.randn(rows,cols)
-df = pd.DataFrame(X)
-# Pandas does the centering for us
-df = df -df.mean()
-display(df)
-
-# we center it ourselves
-X_centered = X - X.mean(axis=0)
-# Then check the difference between pandas and our own set up
-print(X_centered-df)
-#Now we do an SVD
-U, s, V = np.linalg.svd(X_centered)
-c1 = V.T[:, 0]
-c2 = V.T[:, 1]
-W2 = V.T[:, :2]
-X2D = X_centered.dot(W2)
-print(X2D)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PCA assumes that the dataset is centered around the origin. Scikit-Learn’s PCA classes take care of centering
-the data for you. However, if you implement PCA yourself (as in the preceding example), or if you use other libraries, don’t
-forget to center the data first.
-
-
-
Once you have identified all the principal components, you can reduce the dimensionality of the dataset
-down to \( d \) dimensions by projecting it onto the hyperplane defined by the first \( d \) principal components.
-Selecting this hyperplane ensures that the projection will preserve as much variance as possible.
-
-
-
-
-
-
-
-
-
W2 = V.T[:, :2]
-X2D = X_centered.dot(W2)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PCA and scikit-learn
-
-
Scikit-Learn’s PCA class implements PCA using SVD decomposition just like we did before. The
-following code applies PCA to reduce the dimensionality of the dataset down to two dimensions (note
-that it automatically takes care of centering the data):
-
-
-
-
-
-
-
-
-
#thereafter we do a PCA with Scikit-learn
-fromsklearn.decompositionimport PCA
-pca = PCA(n_components = 2)
-X2D = pca.fit_transform(X)
-print(X2D)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
After fitting the PCA transformer to the dataset, you can access the principal components using the
-components variable (note that it contains the PCs as horizontal vectors, so, for example, the first
-principal component is equal to
-
-
-
-
-
-
-
-
-
pca.components_.T[:, 0]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Another very useful piece of information is the explained variance ratio of each principal component,
-available via the \( explained\_variance\_ratio \) variable. It indicates the proportion of the dataset’s
-variance that lies along the axis of each principal component.
-
-
-
-
-
Back to the Cancer Data
-
We can now repeat the above but applied to real data, in this case our breast cancer data.
-Here we compute performance scores on the training data using logistic regression.
-
-
-
-
-
-
-
-
-
importmatplotlib.pyplotasplt
-importnumpyasnp
-fromsklearn.model_selectionimport train_test_split
-fromsklearn.datasetsimport load_breast_cancer
-fromsklearn.linear_modelimport LogisticRegression
-cancer = load_breast_cancer()
-
-X_train, X_test, y_train, y_test = train_test_split(cancer.data,cancer.target,random_state=0)
-
-logreg = LogisticRegression()
-logreg.fit(X_train, y_train)
-print("Train set accuracy from Logistic Regression: {:.2f}".format(logreg.score(X_train,y_train)))
-# We scale the data
-fromsklearn.preprocessingimport StandardScaler
-scaler = StandardScaler()
-scaler.fit(X_train)
-X_train_scaled = scaler.transform(X_train)
-X_test_scaled = scaler.transform(X_test)
-# Then perform again a log reg fit
-logreg.fit(X_train_scaled, y_train)
-print("Train set accuracy scaled data: {:.2f}".format(logreg.score(X_train_scaled,y_train)))
-#thereafter we do a PCA with Scikit-learn
-fromsklearn.decompositionimport PCA
-pca = PCA(n_components = 2)
-X2D_train = pca.fit_transform(X_train_scaled)
-# and finally compute the log reg fit and the score on the training data
-logreg.fit(X2D_train,y_train)
-print("Train set accuracy scaled and PCA data: {:.2f}".format(logreg.score(X2D_train,y_train)))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
We see that our training data after the PCA decomposition has a performance similar to the non-scaled data.
-
-
Instead of arbitrarily choosing the number of dimensions to reduce down to, it is generally preferable to
-choose the number of dimensions that add up to a sufficiently large portion of the variance (e.g., 95%).
-Unless, of course, you are reducing dimensionality for data visualization — in that case you will
-generally want to reduce the dimensionality down to 2 or 3.
-The following code computes PCA without reducing dimensionality, then computes the minimum number
-of dimensions required to preserve 95% of the training set’s variance:
-
You could then set \( n\_components=d \) and run PCA again. However, there is a much better option: instead
-of specifying the number of principal components you want to preserve, you can set \( n\_components \) to be
-a float between 0.0 and 1.0, indicating the ratio of variance you wish to preserve:
-
One problem with the preceding implementation of PCA is that it requires the whole training set to fit in
-memory in order for the SVD algorithm to run. Fortunately, Incremental PCA (IPCA) algorithms have
-been developed: you can split the training set into mini-batches and feed an IPCA algorithm one minibatch
-at a time. This is useful for large training sets, and also to apply PCA online (i.e., on the fly, as new
-instances arrive).
-
-
Randomized PCA
-
-
Scikit-Learn offers yet another option to perform PCA, called Randomized PCA. This is a stochastic
-algorithm that quickly finds an approximation of the first d principal components. Its computational
-complexity is \( O(m \times d^2)+O(d^3) \), instead of \( O(m \times n^2) + O(n^3) \), so it is dramatically faster than the
-previous algorithms when \( d \) is much smaller than \( n \).
-
-
Kernel PCA
-
-
The kernel trick is a mathematical technique that implicitly maps instances into a
-very high-dimensional space (called the feature space), enabling nonlinear classification and regression
-with Support Vector Machines. Recall that a linear decision boundary in the high-dimensional feature
-space corresponds to a complex nonlinear decision boundary in the original space.
-It turns out that the same trick can be applied to PCA, making it possible to perform complex nonlinear
-projections for dimensionality reduction. This is called Kernel PCA (kPCA). It is often good at
-preserving clusters of instances after projection, or sometimes even unrolling datasets that lie close to a
-twisted manifold.
-For example, the following code uses Scikit-Learn’s KernelPCA class to perform kPCA with an
-
There are many other dimensionality reduction techniques, several of which are available in Scikit-Learn.
-
-
Here are some of the most popular:
-
-
Multidimensional Scaling (MDS) reduces dimensionality while trying to preserve the distances between the instances.
-
Isomap creates a graph by connecting each instance to its nearest neighbors, then reduces dimensionality while trying to preserve the geodesic distances between the instances.
-
t-Distributed Stochastic Neighbor Embedding (t-SNE) reduces dimensionality while trying to keep similar instances close and dissimilar instances apart. It is mostly used for visualization, in particular to visualize clusters of instances in high-dimensional space (e.g., to visualize the MNIST images in 2D).
-
Linear Discriminant Analysis (LDA) is actually a classification algorithm, but during training it learns the most discriminative axes between the classes, and these axes can then be used to define a hyperplane onto which to project the data. The benefit is that the projection will keep classes as far apart as possible, so LDA is a good technique to reduce dimensionality before running another classification algorithm such as a Support Vector Machine (SVM) classifier discussed in the SVM lectures.
-
-
-
diff --git a/doc/pub/week43/html/week43-solarized.html b/doc/pub/week43/html/week43-solarized.html
index 36f0b0a43..d1ea1c8e7 100644
--- a/doc/pub/week43/html/week43-solarized.html
+++ b/doc/pub/week43/html/week43-solarized.html
@@ -64,7 +64,105 @@ div.toc p,a {
{'highest level': 2,
'sections': [('Plans for week 43', 2, None, 'plans-for-week-43'),
('Reading Recommendations', 2, None, 'reading-recommendations'),
+ ('Convolutional Neural Networks (recognizing images)',
+ 2,
+ None,
+ 'convolutional-neural-networks-recognizing-images'),
+ ('What is the Difference', 2, None, 'what-is-the-difference'),
+ ('Neural Networks vs CNNs', 2, None, 'neural-networks-vs-cnns'),
+ ('Why CNNS for images, sound files, medical images from CT scans '
+ 'etc?',
+ 2,
+ None,
+ 'why-cnns-for-images-sound-files-medical-images-from-ct-scans-etc'),
+ ('Regular NNs don’t scale well to full images',
+ 2,
+ None,
+ 'regular-nns-don-t-scale-well-to-full-images'),
+ ('3D volumes of neurons', 2, None, '3d-volumes-of-neurons'),
+ ('Layers used to build CNNs',
+ 2,
+ None,
+ 'layers-used-to-build-cnns'),
+ ('Transforming images', 2, None, 'transforming-images'),
('CNNs in brief', 2, None, 'cnns-in-brief'),
+ ('Key Idea', 2, None, 'key-idea'),
+ ('Mathematics of CNNs', 2, None, 'mathematics-of-cnns'),
+ ('Convolution Examples: Polynomial multiplication',
+ 2,
+ None,
+ 'convolution-examples-polynomial-multiplication'),
+ ('Efficient Polynomial Multiplication',
+ 2,
+ None,
+ 'efficient-polynomial-multiplication'),
+ ('A more efficient way of coding the above Convolution',
+ 2,
+ None,
+ 'a-more-efficient-way-of-coding-the-above-convolution'),
+ ('Convolution Examples: Principle of Superposition and Periodic '
+ 'Forces (Fourier Transforms)',
+ 2,
+ None,
+ 'convolution-examples-principle-of-superposition-and-periodic-forces-fourier-transforms'),
+ ('Principle of Superposition',
+ 2,
+ None,
+ 'principle-of-superposition'),
+ ('Simple Code Example', 2, None, 'simple-code-example'),
+ ('Wrapping up Fourier transforms',
+ 2,
+ None,
+ 'wrapping-up-fourier-transforms'),
+ ('Finding the Coefficients', 2, None, 'finding-the-coefficients'),
+ ('Final words on Fourier Transforms',
+ 2,
+ None,
+ 'final-words-on-fourier-transforms'),
+ ('Two-dimensional Objects', 2, None, 'two-dimensional-objects'),
+ ('Cross-Correlation', 2, None, 'cross-correlation'),
+ ('More on Dimensionalities', 2, None, 'more-on-dimensionalities'),
+ ('Further Dimensionality Remarks',
+ 2,
+ None,
+ 'further-dimensionality-remarks'),
+ ('CNNs in more detail, Lecture from IN5400',
+ 2,
+ None,
+ 'cnns-in-more-detail-lecture-from-in5400'),
+ ('CNNs in more detail, building convolutional neural networks in '
+ 'Tensorflow and Keras',
+ 2,
+ None,
+ 'cnns-in-more-detail-building-convolutional-neural-networks-in-tensorflow-and-keras'),
+ ('Setting it up', 2, None, 'setting-it-up'),
+ ('The MNIST dataset again', 2, None, 'the-mnist-dataset-again'),
+ ('Strong correlations', 2, None, 'strong-correlations'),
+ ('Layers of a CNN', 2, None, 'layers-of-a-cnn'),
+ ('Systematic reduction', 2, None, 'systematic-reduction'),
+ ('Prerequisites: Collect and pre-process data',
+ 2,
+ None,
+ 'prerequisites-collect-and-pre-process-data'),
+ ('Importing Keras and Tensorflow',
+ 2,
+ None,
+ 'importing-keras-and-tensorflow'),
+ ('Running with Keras', 2, None, 'running-with-keras'),
+ ('Final part', 2, None, 'final-part'),
+ ('Final visualization', 2, None, 'final-visualization'),
+ ('The CIFAR01 data set', 2, None, 'the-cifar01-data-set'),
+ ('Verifying the data set', 2, None, 'verifying-the-data-set'),
+ ('Set up the model', 2, None, 'set-up-the-model'),
+ ('Add Dense layers on top', 2, None, 'add-dense-layers-on-top'),
+ ('Compile and train the model',
+ 2,
+ None,
+ 'compile-and-train-the-model'),
+ ('Finally, evaluate the model',
+ 2,
+ None,
+ 'finally-evaluate-the-model'),
('Recurrent neural networks: Overarching view',
2,
None,
@@ -110,68 +208,7 @@ div.toc p,a {
('Interpolating Between MNIST Digits',
2,
None,
- 'interpolating-between-mnist-digits'),
- ('Basic ideas of the Principal Component Analysis (PCA)',
- 2,
- None,
- 'basic-ideas-of-the-principal-component-analysis-pca'),
- ('Introducing the Covariance and Correlation functions',
- 2,
- None,
- 'introducing-the-covariance-and-correlation-functions'),
- ('More on the covariance', 2, None, 'more-on-the-covariance'),
- ('Reminding ourselves about Linear Regression',
- 2,
- None,
- 'reminding-ourselves-about-linear-regression'),
- ('Simple Example', 2, None, 'simple-example'),
- ('The Correlation Matrix', 2, None, 'the-correlation-matrix'),
- ('Numpy Functionality', 2, None, 'numpy-functionality'),
- ('Correlation Matrix again', 2, None, 'correlation-matrix-again'),
- ('Using Pandas', 2, None, 'using-pandas'),
- ('And then the Franke Function',
- 2,
- None,
- 'and-then-the-franke-function'),
- ('Lnks with the Design Matrix',
- 2,
- None,
- 'lnks-with-the-design-matrix'),
- ('Computing the Expectation Values',
- 2,
- None,
- 'computing-the-expectation-values'),
- ('Towards the PCA theorem', 2, None, 'towards-the-pca-theorem'),
- ('More on the PCA Theorem', 2, None, 'more-on-the-pca-theorem'),
- ('The Algorithm before the Theorem',
- 2,
- None,
- 'the-algorithm-before-the-theorem'),
- ('Writing our own PCA code', 2, None, 'writing-our-own-pca-code'),
- ('Implementing it', 2, None, 'implementing-it'),
- ('First Step', 2, None, 'first-step'),
- ('Scaling', 2, None, 'scaling'),
- ('Centered Data', 2, None, 'centered-data'),
- ('Exploring', 2, None, 'exploring'),
- ('Diagonalize the sample covariance matrix to obtain the '
- 'principal components',
- 2,
- None,
- 'diagonalize-the-sample-covariance-matrix-to-obtain-the-principal-components'),
- ('Collecting all Steps', 2, None, 'collecting-all-steps'),
- ('Classical PCA Theorem', 2, None, 'classical-pca-theorem'),
- ('The PCA Theorem', 2, None, 'the-pca-theorem'),
- ('Geometric Interpretation and link with Singular Value '
- 'Decomposition',
- 2,
- None,
- 'geometric-interpretation-and-link-with-singular-value-decomposition'),
- ('PCA and scikit-learn', 2, None, 'pca-and-scikit-learn'),
- ('Back to the Cancer Data', 2, None, 'back-to-the-cancer-data'),
- ('Incremental PCA', 2, None, 'incremental-pca'),
- ('Randomized PCA', 3, None, 'randomized-pca'),
- ('Kernel PCA', 3, None, 'kernel-pca'),
- ('Other techniques', 2, None, 'other-techniques')]}
+ 'interpolating-between-mnist-digits')]}
end of tocinfo -->
@@ -192,7 +229,7 @@ MathJax.Hub.Config({
-
ATITLE: Week 43: Deep Learning: Recurrent Neural Networks and other Deep Learning Methods. Principal Component analysis
+
ATITLE: Week 43: Deep Learning: Convolutional Neural Networks and Recurrent Neural Networks
@@ -207,7 +244,7 @@ MathJax.Hub.Config({
-
Oct 24, 2022
+
Oct 26, 2022
@@ -216,8 +253,8 @@ MathJax.Hub.Config({
Plans for week 43
-
Thursday: Convolutional Neural Networks, basic elements and
-
Friday: Recurrent Neural Networks and other Deep learning methods, Generalized Adversarial Neural Networ and autoencoders
+
Thursday: Convolutional Neural Networks (CNN)
+
Friday: Recurrent Neural Networks (RNN)
Excellent lectures on CNNs and RNNs
@@ -243,10 +280,207 @@ MathJax.Hub.Config({
Reading Recommendations
-
-
Goodfellow et al, chapter 10 on Recurrent NNs, chapters 11 and 12 on various practicalities around deep learning are also recommended.
Convolutional neural networks (CNNs) were developed during the last
+decade of the previous century, with a focus on character recognition
+tasks. Nowadays, CNNs are a central element in the spectacular success
+of deep learning methods. The success in for example image
+classifications have made them a central tool for most machine
+learning practitioners.
+
+
+
CNNs are very similar to ordinary Neural Networks.
+They are made up of neurons that have learnable weights and
+biases. Each neuron receives some inputs, performs a dot product and
+optionally follows it with a non-linearity. The whole network still
+expresses a single differentiable score function: from the raw image
+pixels on one end to class scores at the other. And they still have a
+loss function (for example Softmax) on the last (fully-connected) layer
+and all the tips/tricks we developed for learning regular Neural
+Networks still apply (back propagation, gradient descent etc etc).
+
+
+
+
What is the Difference
+
+
CNN architectures make the explicit assumption that
+the inputs are images, which allows us to encode certain properties
+into the architecture. These then make the forward function more
+efficient to implement and vastly reduce the amount of parameters in
+the network.
+
Neural networks are defined as affine transformations, that is
+a vector is received as input and is multiplied with a matrix of so-called weights (our unknown paramters) to produce an
+output (to which a bias vector is usually added before passing the result
+through a nonlinear activation function). This is applicable to any type of input, be it an
+image, a sound clip or an unordered collection of features: whatever their
+dimensionality, their representation can always be flattened into a vector
+before the transformation.
+
+
+
+
Why CNNS for images, sound files, medical images from CT scans etc?
+
+
However, when we consider images, sound clips and many other similar kinds of data, these data have an intrinsic
+structure. More formally, they share these important properties:
+
+
+
They are stored as multi-dimensional arrays (think of the pixels of a figure) .
+
They feature one or more axes for which ordering matters (e.g., width and height axes for an image, time axis for a sound clip).
+
One axis, called the channel axis, is used to access different views of the data (e.g., the red, green and blue channels of a color image, or the left and right channels of a stereo audio track).
+
These properties are not exploited when an affine transformation is applied; in
+fact, all the axes are treated in the same way and the topological information
+is not taken into account. Still, taking advantage of the implicit structure of
+the data may prove very handy in solving some tasks, like computer vision and
+speech recognition, and in these cases it would be best to preserve it. This is
+where discrete convolutions come into play.
+
+
+
A discrete convolution is a linear transformation that preserves this notion of
+ordering. It is sparse (only a few input units contribute to a given output
+unit) and reuses parameters (the same weights are applied to multiple locations
+in the input).
+
+
+
+
Regular NNs don’t scale well to full images
+
+
As an example, consider
+an image of size \( 32\times 32\times 3 \) (32 wide, 32 high, 3 color channels), so a
+single fully-connected neuron in a first hidden layer of a regular
+Neural Network would have \( 32\times 32\times 3 = 3072 \) weights. This amount still
+seems manageable, but clearly this fully-connected structure does not
+scale to larger images. For example, an image of more respectable
+size, say \( 200\times 200\times 3 \), would lead to neurons that have
+\( 200\times 200\times 3 = 120,000 \) weights.
+
+
+
We could have
+several such neurons, and the parameters would add up quickly! Clearly,
+this full connectivity is wasteful and the huge number of parameters
+would quickly lead to possible overfitting.
+
+
+
+
+
+
Figure 1: A regular 3-layer Neural Network.
+
+
+
+
+
+
3D volumes of neurons
+
+
Convolutional Neural Networks take advantage of the fact that the
+input consists of images and they constrain the architecture in a more
+sensible way.
+
+
+
In particular, unlike a regular Neural Network, the
+layers of a CNN have neurons arranged in 3 dimensions: width,
+height, depth. (Note that the word depth here refers to the third
+dimension of an activation volume, not to the depth of a full Neural
+Network, which can refer to the total number of layers in a network.)
+
+
+
To understand it better, the above example of an image
+with an input volume of
+activations has dimensions \( 32\times 32\times 3 \) (width, height,
+depth respectively).
+
+
+
The neurons in a layer will
+only be connected to a small region of the layer before it, instead of
+all of the neurons in a fully-connected manner. Moreover, the final
+output layer could for this specific image have dimensions \( 1\times 1 \times 10 \),
+because by the
+end of the CNN architecture we will reduce the full image into a
+single vector of class scores, arranged along the depth
+dimension.
+
+
+
+
+
+
Figure 2: A CNN arranges its neurons in three dimensions (width, height, depth), as visualized in one of the layers. Every layer of a CNN transforms the 3D input volume to a 3D output volume of neuron activations. In this example, the red input layer holds the image, so its width and height would be the dimensions of the image, and the depth would be 3 (Red, Green, Blue channels).
+
+
+
+
+
+
Layers used to build CNNs
+
+
A simple CNN is a sequence of layers, and every layer of a CNN
+transforms one volume of activations to another through a
+differentiable function. We use three main types of layers to build
+CNN architectures: Convolutional Layer, Pooling Layer, and
+Fully-Connected Layer (exactly as seen in regular Neural Networks). We
+will stack these layers to form a full CNN architecture.
+
+
+
A simple CNN for image classification could have the architecture:
+
+
+
INPUT (\( 32\times 32 \times 3 \)) will hold the raw pixel values of the image, in this case an image of width 32, height 32, and with three color channels R,G,B.
+
CONV (convolutional )layer will compute the output of neurons that are connected to local regions in the input, each computing a dot product between their weights and a small region they are connected to in the input volume. This may result in volume such as \( [32\times 32\times 12] \) if we decided to use 12 filters.
+
RELU layer will apply an elementwise activation function, such as the \( max(0,x) \) thresholding at zero. This leaves the size of the volume unchanged (\( [32\times 32\times 12] \)).
+
POOL (pooling) layer will perform a downsampling operation along the spatial dimensions (width, height), resulting in volume such as \( [16\times 16\times 12] \).
+
FC (i.e. fully-connected) layer will compute the class scores, resulting in volume of size \( [1\times 1\times 10] \), where each of the 10 numbers correspond to a class score, such as among the 10 categories of the MNIST images we considered above . As with ordinary Neural Networks and as the name implies, each neuron in this layer will be connected to all the numbers in the previous volume.
+
+
+
Transforming images
+
+
CNNs transform the original image layer by layer from the original
+pixel values to the final class scores.
+
+
+
Observe that some layers contain
+parameters and other don’t. In particular, the CNN layers perform
+transformations that are a function of not only the activations in the
+input volume, but also of the parameters (the weights and biases of
+the neurons). On the other hand, the RELU/POOL layers will implement a
+fixed function. The parameters in the CONV/FC layers will be trained
+with gradient descent so that the class scores that the CNN computes
+are consistent with the labels in the training set for each image.
+
However, both standard feed forwards networks and CNNs perform well on data with unknown length.
+
The textbook by Goodfellow et al, see chapter 9 contains an in depth discussion as well.
+
+
+
Key Idea
+
+
A dense neural network is representd by an affine operation (like matrix-matrix multiplication) where all parameters are included.
+
+
The key idea in CNNs for say imaging is that in images neighbor pixels tend to be related! So we connect
+only neighboring neurons in the input instead of connecting all with the first hidden layer.
+
+
+
We say we perform a filtering (convolution is the mathematical operation).
+
+
+
Mathematics of CNNs
+
+
The mathematics of CNNs is based on the mathematical operation of
+convolution. In mathematics (in particular in functional analysis),
+convolution is represented by mathematical operation (integration,
+summation etc) on two function in order to produce a third function
+that expresses how the shape of one gets modified by the other.
+Convolution has a plethora of applications in a variety of disciplines, spanning from statistics to signal processing, computer vision, solutions of differential equations,linear algebra, engineering, and yes, machine learning.
+
+
+
Mathematically, convolution is defined as follows (one-dimensional example):
+Let us define a continuous function \( y(t) \) given by
+
+$$
+y(t) = \int x(a) w(t-a) da,
+$$
+
+
where \( x(a) \) represents a so-called input and \( w(t-a) \) is normally called the weight function or kernel.
+
+
The above integral is written in a more compact form as
Computing the inverse of the above convolution operations is known as deconvolution.
+
+
How can we use this? And what does it mean? Let us study some familiar examples first.
+
+
+
Convolution Examples: Polynomial multiplication
+
+
We have already met such an example in project 1 when we tried to set
+up the design matrix for a two-dimensional function. This was an
+example of polynomial multiplication. Let us recast such a problem in terms of the convolution operation.
+Let us look a the following polynomials to second and third order, respectively:
+
Computing polynomial products can be implemented efficiently if we rewrite the more brute force multiplications using convolution.
+We note first that the new coefficients are given as
+
Do you see a potential drawback with these equations?
+
+
+
A more efficient way of coding the above Convolution
+
+
Since we only have a finite number of \( \alpha \) and \( \beta \) values
+which are non-zero, we can rewrite the above convolution expressions
+as a matrix-vector multiplication
+
The process is commutative and we can easily see that we can rewrite the multiplication in terms of a matrix holding \( \beta \) and a vector holding \( \alpha \).
+In this case we have
+
Note that the use of these matrices is for mathematical purposes only and not implementation purposes.
+When implementing the above equation we do not encode (and allocate memory) the matrices explicitely.
+We rather code the convolutions in the minimal memory footprint that they require.
+
+
+
Does the number of floating point operations change here when we use the commutative property?
+
+
+
Convolution Examples: Principle of Superposition and Periodic Forces (Fourier Transforms)
+
+
For problems with so-called harmonic oscillations, given by for example the following differential equation
where \( F(t) \) is an applied external force acting on the system (often called a driving force), one can use the theory of Fourier transformations to find the solutions of this type of equations.
+
+
If one has several driving forces, \( F(t)=\sum_n F_n(t) \), one can find
+the particular solution to each \( F_n \), \( x_{pn}(t) \), and the particular
+solution for the entire driving force is then given by a series like
+
This is known as the principle of superposition. It only applies when
+the homogenous equation is linear. If there were an anharmonic term
+such as \( x^3 \) in the homogenous equation, then when one summed various
+solutions, \( x=(\sum_n x_n)^2 \), one would get cross
+terms. Superposition is especially useful when \( F(t) \) can be written
+as a sum of sinusoidal terms, because the solutions for each
+sinusoidal (sine or cosine) term is analytic.
+
+
+
Driving forces are often periodic, even when they are not
+sinusoidal. Periodicity implies that for some time \( \tau \)
+
One example of a non-sinusoidal periodic force is a square wave. Many
+components in electric circuits are non-linear, e.g. diodes, which
+makes many wave forms non-sinusoidal even when the circuits are being
+driven by purely sinusoidal sources.
+
+
+
+
Simple Code Example
+
+
The code here shows a typical example of such a square wave generated using the functionality included in the scipy Python package. We have used a period of \( \tau=0.2 \).
+
+
+
+
+
+
+
+
+
importnumpyasnp
+importmath
+fromscipyimport signal
+importmatplotlib.pyplotasplt
+
+# number of points
+n = 500
+# start and final times
+t0 = 0.0
+tn = 1.0
+# Period
+t = np.linspace(t0, tn, n, endpoint=False)
+SqrSignal = np.zeros(n)
+SqrSignal = 1.0+signal.square(2*np.pi*5*t)
+plt.plot(t, SqrSignal)
+plt.ylim(-0.5, 2.5)
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
For the sinusoidal example the
+period is \( \tau=2\pi/\omega \). However, higher harmonics can also
+satisfy the periodicity requirement. In general, any force that
+satisfies the periodicity requirement can be expressed as a sum over
+harmonics,
+
We can write down the answer for
+\( x_{pn}(t) \), by substituting \( f_n/m \) or \( g_n/m \) for \( F_0/m \). By
+writing each factor \( 2n\pi t/\tau \) as \( n\omega t \), with \( \omega\equiv
+2\pi/\tau \),
+
Because the forces have been applied for a long time, any non-zero
+damping eliminates the homogenous parts of the solution, so one need
+only consider the particular solution for each \( n \).
+
+
+
The problem is considered solved if one can find expressions for the
+coefficients \( f_n \) and \( g_n \), even though the solutions are expressed
+as an infinite sum. The coefficients can be extracted from the
+function \( F(t) \) by
+
To check the consistency of these expressions and to verify
+Eq. \eqref{eq:fourierdef2}, one can insert the expansion of \( F(t) \) in
+Eq. \eqref{eq:fourierdef1} into the expression for the coefficients in
+Eq. \eqref{eq:fourierdef2} and see whether
+
Immediately, one can throw away all the terms with \( g_m \) because they
+convolute an even and an odd function. The term with \( f_0/2 \)
+disappears because \( \cos(n\omega t) \) is equally positive and negative
+over the interval and will integrate to zero. For all the terms
+\( f_m\cos(m\omega t) \) appearing in the sum, one can use angle addition
+formulas to see that \( \cos(m\omega t)\cos(n\omega
+t)=(1/2)(\cos[(m+n)\omega t]+\cos[(m-n)\omega t] \). This will integrate
+to zero unless \( m=n \). In that case the \( m=n \) term gives
+
The same method can be used to check for the consistency of \( g_n \).
+
+
+
Final words on Fourier Transforms
+
+
The code here uses the Fourier series applied to a
+square wave signal. The code here
+visualizes the various approximations given by Fourier series compared
+with a square wave with period \( T=0.2 \) (dimensionless time), width \( 0.1 \) and max value of the force \( F=2 \). We
+see that when we increase the number of components in the Fourier
+series, the Fourier series approximation gets closer and closer to the
+square wave signal.
+
+
+
+
+
+
+
+
+
+
importnumpyasnp
+importmath
+fromscipyimport signal
+importmatplotlib.pyplotasplt
+
+# number of points
+n = 500
+# start and final times
+t0 = 0.0
+tn = 1.0
+# Period
+T =0.2
+# Max value of square signal
+Fmax= 2.0
+# Width of signal
+Width = 0.1
+t = np.linspace(t0, tn, n, endpoint=False)
+SqrSignal = np.zeros(n)
+FourierSeriesSignal = np.zeros(n)
+SqrSignal = 1.0+signal.square(2*np.pi*5*t+np.pi*Width/T)
+a0 = Fmax*Width/T
+FourierSeriesSignal = a0
+Factor = 2.0*Fmax/np.pi
+for i inrange(1,500):
+ FourierSeriesSignal += Factor/(i)*np.sin(np.pi*i*Width/T)*np.cos(i*t*2*np.pi/T)
+plt.plot(t, SqrSignal)
+plt.plot(t, FourierSeriesSignal)
+plt.ylim(-0.5, 2.5)
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Two-dimensional Objects
+
+
We often use convolutions over more than one dimension at a time. If
+we have a two-dimensional image \( I \) as input, we can have a filter
+defined by a two-dimensional kernel \( K \). This leads to an output \( S \)
+
Normally the latter is more straightforward to implement in a machine elarning library since there is less variation in the range of values of \( m \) and \( n \).
+
+
+
Cross-Correlation
+
+
Many deep learning libraries implement cross-correlation instead of convolution
In feilds like signal processing (and imaging as well), one designs
+so-called filters. These filters are defined by the convolutions and
+are often hand-crafted. One may specify filters for smoothing, edge
+detection, frequency reshaping, and similar operations. However with
+neural networks the idea is to automatically learn the filters and use
+many of them in conjunction with non-linear operations (activation
+functions).
+
+
+
As an example consider a neural network operating on sound sequence
+data. Assume that we an input vector \( \boldsymbol{x} \) of length \( d=10^6 \). We
+construct then a neural network with onle hidden layer only with
+\( 10^4 \) nodes. This means that we will have a weight matrix with
+\( 10^4\times 10^6=10^{10} \) weights to be determined, together with \( 10^4 \) biases.
+
+
+
Assume furthermore that we have an output layer which is meant to train whether the sound sequence represents a human voice (true) or something else (false).
+It means that we have only one output node. But since this output node connects to \( 10^4 \) nodes in the hidden layer, there are in total \( 10^4 \) weights to be determined for the output layer, plus one bias. In total we have
+
In today’s architecture one can train such neural networks, however
+this is a huge number of parameters for the task at hand. In general,
+it is a very wasteful and inefficient use of dense matrices as
+parameters. Just as importantly, such trained network parameters are
+very specific for the type of input data on which they were trained
+and the network is not likely to generalize easily to variations in
+the input.
+
+
+
The main principles that justify convolutions is locality of
+information and repetion of patterns within the signal. Sound samples
+of the input in adjacent spots are much more likely to affect each
+other than those that are very far away. Similarly, sounds are
+repeated in multiple times in the signal. While slightly simplistic,
+reasoning about such a sound example demonstrates this. The same
+principles then apply to images and other similar data.
+
CNNs in more detail, building convolutional neural networks in Tensorflow and Keras
+
+
As discussed above, CNNs are neural networks built from the assumption that the inputs
+to the network are 2D images. This is important because the number of features or pixels in images
+grows very fast with the image size, and an enormous number of weights and biases are needed in order to build an accurate network.
+
+
+
As before, we still have our input, a hidden layer and an output. What's novel about convolutional networks
+are the convolutional and pooling layers stacked in pairs between the input and the hidden layer.
+In addition, the data is no longer represented as a 2D feature matrix, instead each input is a number of 2D
+matrices, typically 1 for each color dimension (Red, Green, Blue).
+
+
+
+
Setting it up
+
+
It means that to represent the entire
+dataset of images, we require a 4D matrix or tensor. This tensor has the dimensions:
+
The MNIST dataset consists of grayscale images with a pixel size of
+\( 28\times 28 \), meaning we require \( 28 \times 28 = 724 \) weights to each
+neuron in the first hidden layer.
+
+
+
If we were to analyze images of size \( 128\times 128 \) we would require
+\( 128 \times 128 = 16384 \) weights to each neuron. Even worse if we were
+dealing with color images, as most images are, we have an image matrix
+of size \( 128\times 128 \) for each color dimension (Red, Green, Blue),
+meaning 3 times the number of weights \( = 49152 \) are required for every
+single neuron in the first hidden layer.
+
+
+
+
+
Strong correlations
+
+
Images typically have strong local correlations, meaning that a small
+part of the image varies little from its neighboring regions. If for
+example we have an image of a blue car, we can roughly assume that a
+small blue part of the image is surrounded by other blue regions.
+
+
+
Therefore, instead of connecting every single pixel to a neuron in the
+first hidden layer, as we have previously done with deep neural
+networks, we can instead connect each neuron to a small part of the
+image (in all 3 RGB depth dimensions). The size of each small area is
+fixed, and known as a receptive.
+
+
+
+
+
Layers of a CNN
+
The layers of a convolutional neural network arrange neurons in 3D: width, height and depth.
+The input image is typically a square matrix of depth 3.
+
+
+
A convolution is performed on the image which outputs
+a 3D volume of neurons. The weights to the input are arranged in a number of 2D matrices, known as filters.
+
+
+
Each filter slides along the input image, taking the dot product
+between each small part of the image and the filter, in all depth
+dimensions. This is then passed through a non-linear function,
+typically the Rectified Linear (ReLu) function, which serves as the
+activation of the neurons in the first convolutional layer. This is
+further passed through a pooling layer, which reduces the size of the
+convolutional layer, e.g. by taking the maximum or average across some
+small regions, and this serves as input to the next convolutional
+layer.
+
+
+
+
Systematic reduction
+
+
By systematically reducing the size of the input volume, through
+convolution and pooling, the network should create representations of
+small parts of the input, and then from them assemble representations
+of larger areas. The final pooling layer is flattened to serve as
+input to a hidden layer, such that each neuron in the final pooling
+layer is connected to every single neuron in the hidden layer. This
+then serves as input to the output layer, e.g. a softmax output for
+classification.
+
+
+
+
+
Prerequisites: Collect and pre-process data
+
+
+
+
+
+
+
+
# import necessary packages
+importnumpyasnp
+importmatplotlib.pyplotasplt
+fromsklearnimport datasets
+
+
+# ensure the same random numbers appear every time
+np.random.seed(0)
+
+# display images in notebook
+%matplotlib inline
+plt.rcParams['figure.figsize'] = (12,12)
+
+
+# download MNIST dataset
+digits = datasets.load_digits()
+
+# define inputs and labels
+inputs = digits.images
+labels = digits.target
+
+# RGB images have a depth of 3
+# our images are grayscale so they should have a depth of 1
+inputs = inputs[:,:,:,np.newaxis]
+
+print("inputs = (n_inputs, pixel_width, pixel_height, depth) = " + str(inputs.shape))
+print("labels = (n_inputs) = " + str(labels.shape))
+
+
+# choose some random images to display
+n_inputs = len(inputs)
+indices = np.arange(n_inputs)
+random_indices = np.random.choice(indices, size=5)
+
+for i, image inenumerate(digits.images[random_indices]):
+ plt.subplot(1, 5, i+1)
+ plt.axis('off')
+ plt.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')
+ plt.title("Label: %d" % digits.target[random_indices[i]])
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Importing Keras and Tensorflow
+
+
+
+
+
+
+
+
fromtensorflow.kerasimport datasets, layers, models
+fromtensorflow.keras.layersimport Input
+fromtensorflow.keras.modelsimport Sequential #This allows appending layers to existing models
+fromtensorflow.keras.layersimport Dense #This allows defining the characteristics of a particular layer
+fromtensorflow.kerasimport optimizers #This allows using whichever optimiser we want (sgd,adam,RMSprop)
+fromtensorflow.kerasimport regularizers #This allows using whichever regularizer we want (l1,l2,l1_l2)
+fromtensorflow.keras.utilsimport to_categorical #This allows using categorical cross entropy as the cost function
+#from tensorflow.keras import Conv2D
+#from tensorflow.keras import MaxPooling2D
+#from tensorflow.keras import Flatten
+
+fromsklearn.model_selectionimport train_test_split
+
+# representation of labels
+labels = to_categorical(labels)
+
+# split into train and test data
+# one-liner from scikit-learn library
+train_size = 0.8
+test_size = 1 - train_size
+X_train, X_test, Y_train, Y_test = train_test_split(inputs, labels, train_size=train_size,
+ test_size=test_size)
+
The CIFAR10 dataset contains 60,000 color images in 10 classes, with
+6,000 images in each class. The dataset is divided into 50,000
+training images and 10,000 testing images. The classes are mutually
+exclusive and there is no overlap between them.
+
+
+
+
+
+
+
+
+
+
importtensorflowastf
+
+fromtensorflow.kerasimport datasets, layers, models
+importmatplotlib.pyplotasplt
+
+# We import the data set
+(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()
+
+# Normalize pixel values to be between 0 and 1 by dividing by 255.
+train_images, test_images = train_images / 255.0, test_images / 255.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Verifying the data set
+
+
To verify that the dataset looks correct, let's plot the first 25 images from the training set and display the class name below each image.
+
+
+
+
+
+
+
+
+
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
+ 'dog', 'frog', 'horse', 'ship', 'truck']
+
+plt.figure(figsize=(10,10))
+for i inrange(25):
+ plt.subplot(5,5,i+1)
+ plt.xticks([])
+ plt.yticks([])
+ plt.grid(False)
+ plt.imshow(train_images[i], cmap=plt.cm.binary)
+ # The CIFAR labels happen to be arrays,
+ # which is why you need the extra index
+ plt.xlabel(class_names[train_labels[i][0]])
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Set up the model
+
+
The 6 lines of code below define the convolutional base using a common pattern: a stack of Conv2D and MaxPooling2D layers.
+
+
As input, a CNN takes tensors of shape (image_height, image_width, color_channels), ignoring the batch size. If you are new to these dimensions, color_channels refers to (R,G,B). In this example, you will configure our CNN to process inputs of shape (32, 32, 3), which is the format of CIFAR images. You can do this by passing the argument input_shape to our first layer.
+
+
+
+
+
+
+
+
+
model = models.Sequential()
+model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
+model.add(layers.MaxPooling2D((2, 2)))
+model.add(layers.Conv2D(64, (3, 3), activation='relu'))
+model.add(layers.MaxPooling2D((2, 2)))
+model.add(layers.Conv2D(64, (3, 3), activation='relu'))
+
+# Let's display the architecture of our model so far.
+
+model.summary()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
You can see that the output of every Conv2D and MaxPooling2D layer is a 3D tensor of shape (height, width, channels). The width and height dimensions tend to shrink as you go deeper in the network. The number of output channels for each Conv2D layer is controlled by the first argument (e.g., 32 or 64). Typically, as the width and height shrink, you can afford (computationally) to add more output channels in each Conv2D layer.
+
+
+
Add Dense layers on top
+
+
To complete our model, you will feed the last output tensor from the
+convolutional base (of shape (4, 4, 64)) into one or more Dense layers
+to perform classification. Dense layers take vectors as input (which
+are 1D), while the current output is a 3D tensor. First, you will
+flatten (or unroll) the 3D output to 1D, then add one or more Dense
+layers on top. CIFAR has 10 output classes, so you use a final Dense
+layer with 10 outputs and a softmax activation.
+
+
+
+
+
+
+
+
+
+
model.add(layers.Flatten())
+model.add(layers.Dense(64, activation='relu'))
+model.add(layers.Dense(10))
+Here's the complete architecture of our model.
+
+model.summary()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
As you can see, our (4, 4, 64) outputs were flattened into vectors of shape (1024) before going through two Dense layers.
@@ -1092,7 +2410,7 @@ samples
$$
\begin{equation}
x = g(z; \theta^{(g)})
-\label{_auto1}
+\label{_auto4}
\end{equation}
$$
@@ -1109,7 +2427,7 @@ value given by
$$
\begin{equation}
d(x; \theta^{(d)})
-\label{_auto2}
+\label{_auto5}
\end{equation}
$$
@@ -1122,7 +2440,7 @@ which a function
$$
\begin{equation}
v(\theta^{(g)}, \theta^{(d)})
-\label{_auto3}
+\label{_auto6}
\end{equation}
$$
@@ -1133,7 +2451,7 @@ conjugate reward
$$
\begin{equation}
-v(\theta^{(g)}, \theta^{(d)})
-\label{_auto4}
+\label{_auto7}
\end{equation}
$$
@@ -1168,7 +2486,7 @@ $$
\begin{equation}
g^* = \underset{g}{\mathrm{argmin}}\hspace{2pt}
\underset{d}{\mathrm{max}}v(\theta^{(g)}, \theta^{(d)})
-\label{_auto5}
+\label{_auto8}
\end{equation}
$$
@@ -1178,7 +2496,7 @@ $$
v(\theta^{(g)}, \theta^{(d)}) = \mathbb{E}_{x\sim p_\mathrm{data}}\log d(x)
+ \mathbb{E}_{x\sim p_\mathrm{model}}
\log (1 - d(x))
-\label{_auto6}
+\label{_auto9}
\end{equation}
$$
@@ -1189,7 +2507,7 @@ approximation of a partition function. In the case where
$$
\begin{equation}
\underset{d}{\mathrm{max}}v(\theta^{(g)}, \theta^{(d)})
-\label{_auto7}
+\label{_auto10}
\end{equation}
$$
@@ -2145,1207 +3463,6 @@ plot_results(results, plot_number)
-
-
Basic ideas of the Principal Component Analysis (PCA)
-
-
The principal component analysis deals with the problem of fitting a
-low-dimensional affine subspace \( S \) of dimension \( d \) much smaller than
-the total dimension \( D \) of the problem at hand (our data
-set). Mathematically it can be formulated as a statistical problem or
-a geometric problem. In our discussion of the theorem for the
-classical PCA, we will stay with a statistical approach.
-Historically, the PCA was first formulated in a statistical setting in order to estimate the principal component of a multivariate random variable.
-
-
-
We have a data set defined by a design/feature matrix \( \boldsymbol{X} \) (see below for its definition)
-
-
Each data point is determined by \( p \) extrinsic (measurement) variables
-
We may want to ask the following question: Are there fewer intrinsic variables (say \( d < < p \)) that still approximately describe the data?
-
If so, these intrinsic variables may tell us something important and finding these intrinsic variables is what dimension reduction methods do.
Introducing the Covariance and Correlation functions
-
-
Before we discuss the PCA theorem, we need to remind ourselves about
-the definition of the covariance and the correlation function. These are quantities
-
-
-
Suppose we have defined two vectors
-\( \hat{x} \) and \( \hat{y} \) with \( n \) elements each. The covariance matrix \( \boldsymbol{C} \) is defined as
-
The covariance takes values between zero and infinity and may thus
-lead to problems with loss of numerical precision for particularly
-large values. It is common to scale the covariance matrix by
-introducing instead the correlation matrix defined via the so-called
-correlation function
-
The correlation function is then given by values \( \mathrm{corr}[\boldsymbol{x},\boldsymbol{y}]
-\in [-1,1] \). This avoids eventual problems with too large values. We
-can then define the correlation matrix for the two vectors \( \boldsymbol{x} \)
-and \( \boldsymbol{y} \) as
-
In the above example this is the function we constructed using pandas.
-
-
-
Reminding ourselves about Linear Regression
-
In our derivation of the various regression algorithms like Ordinary Least Squares or Ridge regression
-we defined the design/feature matrix \( \boldsymbol{X} \) as
-
with \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \), with the predictors/features \( p \) refering to the column numbers and the
-entries \( n \) being the row elements.
-We can rewrite the design/feature matrix in terms of its column vectors as
-
With these definitions, we can now rewrite our \( 2\times 2 \)
-correlation/covariance matrix in terms of a moe general design/feature
-matrix \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \). This leads to a \( p\times p \)
-covariance matrix for the vectors \( \boldsymbol{x}_i \) with \( i=0,1,\dots,p-1 \)
-
The Numpy function np.cov calculates the covariance elements using
-the factor \( 1/(n-1) \) instead of \( 1/n \) since it assumes we do not have
-the exact mean values. The following simple function uses the
-np.vstack function which takes each vector of dimension \( 1\times n \)
-and produces a \( 2\times n \) matrix \( \boldsymbol{W} \)
-
which in turn is converted into into the \( 2\times 2 \) covariance matrix
-\( \boldsymbol{C} \) via the Numpy function np.cov(). We note that we can also calculate
-the mean value of each set of samples \( \boldsymbol{x} \) etc using the Numpy
-function np.mean(x). We can also extract the eigenvalues of the
-covariance matrix through the np.linalg.eig() function.
-
The previous example can be converted into the correlation matrix by
-simply scaling the matrix elements with the variances. We should also
-subtract the mean values for each column. This leads to the following
-code which sets up the correlations matrix for the previous example in
-a more brute force way. Here we scale the mean values for each column of the design matrix, calculate the relevant mean values and variances and then finally set up the \( 2\times 2 \) correlation matrix (since we have only two vectors).
-
-
-
-
-
-
-
-
-
-
importnumpyasnp
-n = 100
-# define two vectors
-x = np.random.random(size=n)
-y = 4+3*x+np.random.normal(size=n)
-#scaling the x and y vectors
-x = x - np.mean(x)
-y = y - np.mean(y)
-variance_x = np.sum(x@x)/n
-variance_y = np.sum(y@y)/n
-print(variance_x)
-print(variance_y)
-cov_xy = np.sum(x@y)/n
-cov_xx = np.sum(x@x)/n
-cov_yy = np.sum(y@y)/n
-C = np.zeros((2,2))
-C[0,0]= cov_xx/variance_x
-C[1,1]= cov_yy/variance_y
-C[0,1]= cov_xy/np.sqrt(variance_y*variance_x)
-C[1,0]= C[0,1]
-print(C)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
We see that the matrix elements along the diagonal are one as they
-should be and that the matrix is symmetric. Furthermore, diagonalizing
-this matrix we easily see that it is a positive definite matrix.
-
-
-
The above procedure with numpy can be made more compact if we use pandas.
-
-
-
Using Pandas
-
-
We whow here how we can set up the correlation matrix using pandas, as done in this simple code
We expand this model to the Franke function discussed above.
-
-
-
-
-
-
-
-
-
# Common imports
-importnumpyasnp
-importpandasaspd
-
-
-defFrankeFunction(x,y):
- term1 = 0.75*np.exp(-(0.25*(9*x-2)**2) - 0.25*((9*y-2)**2))
- term2 = 0.75*np.exp(-((9*x+1)**2)/49.0 - 0.1*(9*y+1))
- term3 = 0.5*np.exp(-(9*x-7)**2/4.0 - 0.25*((9*y-3)**2))
- term4 = -0.2*np.exp(-(9*x-4)**2 - (9*y-7)**2)
- return term1 + term2 + term3 + term4
-
-
-defcreate_X(x, y, n ):
- iflen(x.shape) > 1:
- x = np.ravel(x)
- y = np.ravel(y)
-
- N = len(x)
- l = int((n+1)*(n+2)/2) # Number of elements in beta
- X = np.ones((N,l))
-
- for i inrange(1,n+1):
- q = int((i)*(i+1)/2)
- for k inrange(i+1):
- X[:,q+k] = (x**(i-k))*(y**k)
-
- return X
-
-
-# Making meshgrid of datapoints and compute Franke's function
-n = 4
-N = 100
-x = np.sort(np.random.uniform(0, 1, N))
-y = np.sort(np.random.uniform(0, 1, N))
-z = FrankeFunction(x, y)
-X = create_X(x, y, n=n)
-
-Xpd = pd.DataFrame(X)
-# subtract the mean values and set up the covariance matrix
-Xpd = Xpd - Xpd.mean()
-covariance_matrix = Xpd.cov()
-print(covariance_matrix)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
We note here that the covariance is zero for the first rows and
-columns since all matrix elements in the design matrix were set to one
-(we are fitting the function in terms of a polynomial of degree \( n \)). We would however not include the intercept
-and wee can simply
-drop these elements and construct a correlation
-matrix without them by centering our matrix elements by subtracting the mean of each column.
-
-
-
-
Lnks with the Design Matrix
-
-
We can rewrite the covariance matrix in a more compact form in terms of the design/feature matrix \( \boldsymbol{X} \) as
where we wrote $$\boldsymbol{C}[\boldsymbol{x}_0,\boldsymbol{x}_1] = \boldsymbol{C}[\boldsymbol{x}]$$ to indicate that this the covariance of the vectors \( \boldsymbol{x} \) of the design/feature matrix \( \boldsymbol{X} \).
-
-
It is easy to generalize this to a matrix \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \).
-
-
-
Towards the PCA theorem
-
-
We have that the covariance matrix (the correlation matrix involves a simple rescaling) is given as
Let us now assume that we can perform a series of orthogonal transformations where we employ some orthogonal matrices \( \boldsymbol{S} \).
-These matrices are defined as \( \boldsymbol{S}\in {\mathbb{R}}^{p\times p} \) and obey the orthogonality requirements \( \boldsymbol{S}\boldsymbol{S}^T=\boldsymbol{S}^T\boldsymbol{S}=\boldsymbol{I} \). The matrix can be written out in terms of the column vectors \( \boldsymbol{s}_i \) as \( \boldsymbol{S}=[\boldsymbol{s}_0,\boldsymbol{s}_1,\dots,\boldsymbol{s}_{p-1}] \) and \( \boldsymbol{s}_i \in {\mathbb{R}}^{p} \).
-
-
-
Assume also that there is a transformation \( \boldsymbol{S}^T\boldsymbol{C}[\boldsymbol{x}]\boldsymbol{S}=\boldsymbol{C}[\boldsymbol{y}] \) such that the new matrix \( \boldsymbol{C}[\boldsymbol{y}] \) is diagonal with elements \( [\lambda_0,\lambda_1,\lambda_2,\dots,\lambda_{p-1}] \).
In the derivation of the PCA theorem we will assume that the eigenvalues are ordered in descending order, that is
-\( \lambda_0 > \lambda_1 > \dots > \lambda_{p-1} \).
-
-
-
The eigenvalues tell us then how much we need to stretch the
-corresponding eigenvectors. Dimensions with large eigenvalues have
-thus large variations (large variance) and define therefore useful
-dimensions. The data points are more spread out in the direction of
-these eigenvectors. Smaller eigenvalues mean on the other hand that
-the corresponding eigenvectors are shrunk accordingly and the data
-points are tightly bunched together and there is not much variation in
-these specific directions. Hopefully then we could leave it out
-dimensions where the eigenvalues are very small. If \( p \) is very large,
-we could then aim at reducing \( p \) to \( l < < p \) and handle only \( l \)
-features/predictors.
-
-
-
-
The Algorithm before theorem
-
-
Here's how we would proceed in setting up the algorithm for the PCA, see also discussion below here.
-
-
Set up the datapoints for the design/feature matrix \( \boldsymbol{X} \) with \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \), with the predictors/features \( p \) referring to the column numbers and the entries \( n \) being the row elements.
Center the data by subtracting the mean value for each column. This leads to a new matrix \( \boldsymbol{X}\rightarrow \overline{\boldsymbol{X}} \).
-
Compute then the covariance/correlation matrix \( \mathbb{E}[\overline{\boldsymbol{X}}^T\overline{\boldsymbol{X}}] \).
-
Find the eigenpairs of \( \boldsymbol{C} \) with eigenvalues \( [\lambda_0,\lambda_1,\dots,\lambda_{p-1}] \) and eigenvectors \( [\boldsymbol{s}_0,\boldsymbol{s}_1,\dots,\boldsymbol{s}_{p-1}] \).
-
Order the eigenvalue (and the eigenvectors accordingly) in order of decreasing eigenvalues.
-
Keep only those \( l \) eigenvalues larger than a selected threshold value, discarding thus \( p-l \) features since we expect small variations in the data here.
-
-
-
Writing our own PCA code
-
-
We will use a simple example first with two-dimensional data
-drawn from a multivariate normal distribution with the following mean and covariance matrix (we have fixed these quantities but will play around with them below):
-
Note that the mean refers to each column of data.
-We will generate \( n = 10000 \) points \( X = \{ x_1, \ldots, x_N \} \) from
-this distribution, and store them in the \( 1000 \times 2 \) matrix \( \boldsymbol{X} \). This is our design matrix where we have forced the covariance and mean values to take specific values.
-
-
-
-
Implementing it
-
The following Python code aids in setting up the data and writing out the design matrix.
-Note that the function multivariate returns also the covariance discussed above and that it is defined by dividing by \( n-1 \) instead of \( n \).
-
Now we are going to implement the PCA algorithm. We will break it down into various substeps.
-
-
-
First Step
-
-
The first step of PCA is to compute the sample mean of the data and use it to center the data. Recall that the sample mean is
-$$
-\mu_n = \frac{1}{n} \sum_{i=1}^n x_i
-$$
-
-
and the mean-centered data \( \bar{X} = \{ \bar{x}_1, \ldots, \bar{x}_n \} \) takes the form
-$$
-\bar{x}_i = x_i - \mu_n.
-$$
-
-
When you are done with these steps, print out \( \mu_n \) to verify it is
-close to \( \mu \) and plot your mean centered data to verify it is
-centered at the origin!
-The following code elements perform these operations using pandas or using our own functionality for doing so. The latter, using numpy is rather simple through the mean() function.
-
-
-
-
-
-
-
-
-
df = pd.DataFrame(X)
-# Pandas does the centering for us
-df = df -df.mean()
-# we center it ourselves
-X_centered = X - X.mean(axis=0)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Scaling
-
Alternatively, we could use the functions we discussed
-earlier for scaling the data set. That is, we could have used the
-StandardScaler function in Scikit-Learn, a function which ensures
-that for each feature/predictor we study the mean value is zero and
-the variance is one (every column in the design/feature matrix). You
-would then not get the same results, since we divide by the
-variance. The diagonal covariance matrix elements will then be one,
-while the non-diagonal ones need to be divided by \( 2\sqrt{2} \) for our
-specific case.
-
-
-
-
Centered Data
-
-
Now we are going to use the mean centered data to compute the sample covariance of the data by using the following equation
where the data points \( x_i \in \mathbb{R}^p \) (here in this example \( p = 2 \)) are column vectors and \( x^T \) is the transpose of \( x \).
-We can write our own code or simply use either the functionaly of numpy or that of pandas, as follows
-
-
-
-
-
-
-
-
-
print(df.cov())
-print(np.cov(X_centered.T))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Note that the way we define the covariance matrix here has a factor \( n-1 \) instead of \( n \). This is included in the cov() function by numpy and pandas.
-Our own code here is not very elegant and asks for obvious improvements. It is tailored to this specific \( 2\times 2 \) covariance matrix.
-
-
-
-
-
-
-
-
-
# extract the relevant columns from the centered design matrix of dim n x 2
-x = X_centered[:,0]
-y = X_centered[:,1]
-Cov = np.zeros((2,2))
-Cov[0,1] = np.sum(x.T@y)/(n-1.0)
-Cov[0,0] = np.sum(x.T@x)/(n-1.0)
-Cov[1,1] = np.sum(y.T@y)/(n-1.0)
-Cov[1,0]= Cov[0,1]
-print("Centered covariance using own code")
-print(Cov)
-plt.plot(x, y, 'x')
-plt.axis('equal')
-plt.show()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Exploring
-
-
Depending on the number of points \( n \), we will get results that are close to the covariance values defined above.
-The plot shows how the data are clustered around a line with slope close to one. Is this expected? Try to change the covariance and the mean values. For example, try to make the variance of the first element much larger than that of the second diagonal element. Try also to shrink the covariance (the non-diagonal elements) and see how the data points are distributed.
-
-
-
-
Diagonalize the sample covariance matrix to obtain the principal components
-
-
Now we are ready to solve for the principal components! To do so we
-diagonalize the sample covariance matrix \( \Sigma \). We can use the
-function np.linalg.eig to do so. It will return the eigenvalues and
-eigenvectors of \( \Sigma \). Once we have these we can perform the
-following tasks:
-
-
-
-
We compute the percentage of the total variance captured by the first principal component
-
We plot the mean centered data and lines along the first and second principal components
-
Then we project the mean centered data onto the first and second principal components, and plot the projected data.
Collecting all these steps we can write our own PCA function and
-compare this with the functionality included in Scikit-Learn.
-
-
-
The code here outlines some of the elements we could include in the
-analysis. Feel free to extend upon this in order to address the above
-questions.
-
-
-
-
-
-
-
-
-
-
# diagonalize and obtain eigenvalues, not necessarily sorted
-EigValues, EigVectors = np.linalg.eig(Cov)
-# sort eigenvectors and eigenvalues
-#permute = EigValues.argsort()
-#EigValues = EigValues[permute]
-#EigVectors = EigVectors[:,permute]
-print("Eigenvalues of Covariance matrix")
-for i inrange(2):
- print(EigValues[i])
-FirstEigvector = EigVectors[:,0]
-SecondEigvector = EigVectors[:,1]
-print("First eigenvector")
-print(FirstEigvector)
-print("Second eigenvector")
-print(SecondEigvector)
-#thereafter we do a PCA with Scikit-learn
-fromsklearn.decompositionimport PCA
-pca = PCA(n_components = 2)
-X2Dsl = pca.fit_transform(X)
-print("Eigenvector of largest eigenvalue")
-print(pca.components_.T[:, 0])
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
This code does not contain all the above elements, but it shows how we can use Scikit-Learn to extract the eigenvector which corresponds to the largest eigenvalue. Try to address the questions we pose before the above code. Try also to change the values of the covariance matrix by making one of the diagonal elements much larger than the other. What do you observe then?
-
-
-
Classical PCA Theorem
-
-
We assume now that we have a design matrix \( \boldsymbol{X} \) which has been
-centered as discussed above. For the sake of simplicity we skip the
-overline symbol. The matrix is defined in terms of the various column
-vectors \( [\boldsymbol{x}_0,\boldsymbol{x}_1,\dots, \boldsymbol{x}_{p-1}] \) each with dimension
-\( \boldsymbol{x}\in {\mathbb{R}}^{n} \).
-
-
-
The PCA theorem states that minimizing the above reconstruction error
-corresponds to setting \( \boldsymbol{W}=\boldsymbol{S} \), the orthogonal matrix which
-diagonalizes the empirical covariance(correlation) matrix. The optimal
-low-dimensional encoding of the data is then given by a set of vectors
-\( \boldsymbol{z}_i \) with at most \( l \) vectors, with \( l < < p \), defined by the
-orthogonal projection of the data onto the columns spanned by the
-eigenvectors of the covariance(correlations matrix).
-
-
-
-
The PCA Theorem
-
-
To show the PCA theorem let us start with the assumption that there is one vector \( \boldsymbol{s}_0 \) which corresponds to a solution which minimized the reconstruction error \( J \). This is an orthogonal vector. It means that we now approximate the reconstruction error in terms of \( \boldsymbol{w}_0 \) and \( \boldsymbol{z}_0 \) as
-
-
We are almost there, we have obtained a relation between minimizing
-the reconstruction error and the variance and the covariance
-matrix. Minimizing the error is equivalent to maximizing the variance
-of the projected data.
-
-
-
We could trivially maximize the variance of the projection (and
-thereby minimize the error in the reconstruction function) by letting
-the norm-2 of \( \boldsymbol{w}_0 \) go to infinity. However, this norm since we
-want the matrix \( \boldsymbol{W} \) to be an orthogonal matrix, is constrained by
-\( \vert\vert \boldsymbol{w}_0 \vert\vert_2^2=1 \). Imposing this condition via a
-Lagrange multiplier we can then in turn maximize
-
The direction that maximizes the variance (or minimizes the construction error) is an eigenvector of the covariance matrix! If we left multiply with \( \boldsymbol{w}_0^T \) we have the variance of the projected data is
If we want to maximize the variance (minimize the construction error)
-we simply pick the eigenvector of the covariance matrix with the
-largest eigenvalue. This establishes the link between the minimization
-of the reconstruction function \( J \) in terms of an orthogonal matrix
-and the maximization of the variance and thereby the covariance of our
-observations encoded in the design/feature matrix \( \boldsymbol{X} \).
-
-
-
The proof
-for the other eigenvectors \( \boldsymbol{w}_1,\boldsymbol{w}_2,\dots \) can be
-established by applying the above arguments and using the fact that
-our basis of eigenvectors is orthogonal, see Murphy chapter
-12.2. The
-discussion in chapter 12.2 of Murphy's text has also a nice link with
-the Singular Value Decomposition theorem. For categorical data, see
-chapter 12.4 and discussion therein.
-
Principal Component Analysis (PCA) is by far the most popular dimensionality reduction algorithm.
-First it identifies the hyperplane that lies closest to the data, and then it projects the data onto it.
-
-
-
The following Python code uses NumPy’s svd() function to obtain all the principal components of the
-training set, then extracts the first two principal components. First we center the data using either pandas or our own code
-
-
-
-
-
-
-
-
-
importnumpyasnp
-importpandasaspd
-fromIPython.displayimport display
-np.random.seed(100)
-# setting up a 10 x 5 vanilla matrix
-rows = 10
-cols = 5
-X = np.random.randn(rows,cols)
-df = pd.DataFrame(X)
-# Pandas does the centering for us
-df = df -df.mean()
-display(df)
-
-# we center it ourselves
-X_centered = X - X.mean(axis=0)
-# Then check the difference between pandas and our own set up
-print(X_centered-df)
-#Now we do an SVD
-U, s, V = np.linalg.svd(X_centered)
-c1 = V.T[:, 0]
-c2 = V.T[:, 1]
-W2 = V.T[:, :2]
-X2D = X_centered.dot(W2)
-print(X2D)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PCA assumes that the dataset is centered around the origin. Scikit-Learn’s PCA classes take care of centering
-the data for you. However, if you implement PCA yourself (as in the preceding example), or if you use other libraries, don’t
-forget to center the data first.
-
-
-
Once you have identified all the principal components, you can reduce the dimensionality of the dataset
-down to \( d \) dimensions by projecting it onto the hyperplane defined by the first \( d \) principal components.
-Selecting this hyperplane ensures that the projection will preserve as much variance as possible.
-
-
-
-
-
-
-
-
-
W2 = V.T[:, :2]
-X2D = X_centered.dot(W2)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PCA and scikit-learn
-
-
Scikit-Learn’s PCA class implements PCA using SVD decomposition just like we did before. The
-following code applies PCA to reduce the dimensionality of the dataset down to two dimensions (note
-that it automatically takes care of centering the data):
-
-
-
-
-
-
-
-
-
#thereafter we do a PCA with Scikit-learn
-fromsklearn.decompositionimport PCA
-pca = PCA(n_components = 2)
-X2D = pca.fit_transform(X)
-print(X2D)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
After fitting the PCA transformer to the dataset, you can access the principal components using the
-components variable (note that it contains the PCs as horizontal vectors, so, for example, the first
-principal component is equal to
-
-
-
-
-
-
-
-
-
pca.components_.T[:, 0]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Another very useful piece of information is the explained variance ratio of each principal component,
-available via the \( explained\_variance\_ratio \) variable. It indicates the proportion of the dataset’s
-variance that lies along the axis of each principal component.
-
-
-
-
Back to the Cancer Data
-
We can now repeat the above but applied to real data, in this case our breast cancer data.
-Here we compute performance scores on the training data using logistic regression.
-
-
-
-
-
-
-
-
-
importmatplotlib.pyplotasplt
-importnumpyasnp
-fromsklearn.model_selectionimport train_test_split
-fromsklearn.datasetsimport load_breast_cancer
-fromsklearn.linear_modelimport LogisticRegression
-cancer = load_breast_cancer()
-
-X_train, X_test, y_train, y_test = train_test_split(cancer.data,cancer.target,random_state=0)
-
-logreg = LogisticRegression()
-logreg.fit(X_train, y_train)
-print("Train set accuracy from Logistic Regression: {:.2f}".format(logreg.score(X_train,y_train)))
-# We scale the data
-fromsklearn.preprocessingimport StandardScaler
-scaler = StandardScaler()
-scaler.fit(X_train)
-X_train_scaled = scaler.transform(X_train)
-X_test_scaled = scaler.transform(X_test)
-# Then perform again a log reg fit
-logreg.fit(X_train_scaled, y_train)
-print("Train set accuracy scaled data: {:.2f}".format(logreg.score(X_train_scaled,y_train)))
-#thereafter we do a PCA with Scikit-learn
-fromsklearn.decompositionimport PCA
-pca = PCA(n_components = 2)
-X2D_train = pca.fit_transform(X_train_scaled)
-# and finally compute the log reg fit and the score on the training data
-logreg.fit(X2D_train,y_train)
-print("Train set accuracy scaled and PCA data: {:.2f}".format(logreg.score(X2D_train,y_train)))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
We see that our training data after the PCA decomposition has a performance similar to the non-scaled data.
-
-
Instead of arbitrarily choosing the number of dimensions to reduce down to, it is generally preferable to
-choose the number of dimensions that add up to a sufficiently large portion of the variance (e.g., 95%).
-Unless, of course, you are reducing dimensionality for data visualization — in that case you will
-generally want to reduce the dimensionality down to 2 or 3.
-The following code computes PCA without reducing dimensionality, then computes the minimum number
-of dimensions required to preserve 95% of the training set’s variance:
-
You could then set \( n\_components=d \) and run PCA again. However, there is a much better option: instead
-of specifying the number of principal components you want to preserve, you can set \( n\_components \) to be
-a float between 0.0 and 1.0, indicating the ratio of variance you wish to preserve:
-
One problem with the preceding implementation of PCA is that it requires the whole training set to fit in
-memory in order for the SVD algorithm to run. Fortunately, Incremental PCA (IPCA) algorithms have
-been developed: you can split the training set into mini-batches and feed an IPCA algorithm one minibatch
-at a time. This is useful for large training sets, and also to apply PCA online (i.e., on the fly, as new
-instances arrive).
-
-
Randomized PCA
-
-
Scikit-Learn offers yet another option to perform PCA, called Randomized PCA. This is a stochastic
-algorithm that quickly finds an approximation of the first d principal components. Its computational
-complexity is \( O(m \times d^2)+O(d^3) \), instead of \( O(m \times n^2) + O(n^3) \), so it is dramatically faster than the
-previous algorithms when \( d \) is much smaller than \( n \).
-
-
Kernel PCA
-
-
The kernel trick is a mathematical technique that implicitly maps instances into a
-very high-dimensional space (called the feature space), enabling nonlinear classification and regression
-with Support Vector Machines. Recall that a linear decision boundary in the high-dimensional feature
-space corresponds to a complex nonlinear decision boundary in the original space.
-It turns out that the same trick can be applied to PCA, making it possible to perform complex nonlinear
-projections for dimensionality reduction. This is called Kernel PCA (kPCA). It is often good at
-preserving clusters of instances after projection, or sometimes even unrolling datasets that lie close to a
-twisted manifold.
-For example, the following code uses Scikit-Learn’s KernelPCA class to perform kPCA with an
-
There are many other dimensionality reduction techniques, several of which are available in Scikit-Learn.
-
-
Here are some of the most popular:
-
-
Multidimensional Scaling (MDS) reduces dimensionality while trying to preserve the distances between the instances.
-
Isomap creates a graph by connecting each instance to its nearest neighbors, then reduces dimensionality while trying to preserve the geodesic distances between the instances.
-
t-Distributed Stochastic Neighbor Embedding (t-SNE) reduces dimensionality while trying to keep similar instances close and dissimilar instances apart. It is mostly used for visualization, in particular to visualize clusters of instances in high-dimensional space (e.g., to visualize the MNIST images in 2D).
-
Linear Discriminant Analysis (LDA) is actually a classification algorithm, but during training it learns the most discriminative axes between the classes, and these axes can then be used to define a hyperplane onto which to project the data. The benefit is that the projection will keep classes as far apart as possible, so LDA is a good technique to reduce dimensionality before running another classification algorithm such as a Support Vector Machine (SVM) classifier discussed in the SVM lectures.
Convolutional neural networks (CNNs) were developed during the last
+decade of the previous century, with a focus on character recognition
+tasks. Nowadays, CNNs are a central element in the spectacular success
+of deep learning methods. The success in for example image
+classifications have made them a central tool for most machine
+learning practitioners.
+
+
+
CNNs are very similar to ordinary Neural Networks.
+They are made up of neurons that have learnable weights and
+biases. Each neuron receives some inputs, performs a dot product and
+optionally follows it with a non-linearity. The whole network still
+expresses a single differentiable score function: from the raw image
+pixels on one end to class scores at the other. And they still have a
+loss function (for example Softmax) on the last (fully-connected) layer
+and all the tips/tricks we developed for learning regular Neural
+Networks still apply (back propagation, gradient descent etc etc).
+
+
+
+
What is the Difference
+
+
CNN architectures make the explicit assumption that
+the inputs are images, which allows us to encode certain properties
+into the architecture. These then make the forward function more
+efficient to implement and vastly reduce the amount of parameters in
+the network.
+
Neural networks are defined as affine transformations, that is
+a vector is received as input and is multiplied with a matrix of so-called weights (our unknown paramters) to produce an
+output (to which a bias vector is usually added before passing the result
+through a nonlinear activation function). This is applicable to any type of input, be it an
+image, a sound clip or an unordered collection of features: whatever their
+dimensionality, their representation can always be flattened into a vector
+before the transformation.
+
+
+
+
Why CNNS for images, sound files, medical images from CT scans etc?
+
+
However, when we consider images, sound clips and many other similar kinds of data, these data have an intrinsic
+structure. More formally, they share these important properties:
+
+
+
They are stored as multi-dimensional arrays (think of the pixels of a figure) .
+
They feature one or more axes for which ordering matters (e.g., width and height axes for an image, time axis for a sound clip).
+
One axis, called the channel axis, is used to access different views of the data (e.g., the red, green and blue channels of a color image, or the left and right channels of a stereo audio track).
+
These properties are not exploited when an affine transformation is applied; in
+fact, all the axes are treated in the same way and the topological information
+is not taken into account. Still, taking advantage of the implicit structure of
+the data may prove very handy in solving some tasks, like computer vision and
+speech recognition, and in these cases it would be best to preserve it. This is
+where discrete convolutions come into play.
+
+
+
A discrete convolution is a linear transformation that preserves this notion of
+ordering. It is sparse (only a few input units contribute to a given output
+unit) and reuses parameters (the same weights are applied to multiple locations
+in the input).
+
+
+
+
Regular NNs don’t scale well to full images
+
+
As an example, consider
+an image of size \( 32\times 32\times 3 \) (32 wide, 32 high, 3 color channels), so a
+single fully-connected neuron in a first hidden layer of a regular
+Neural Network would have \( 32\times 32\times 3 = 3072 \) weights. This amount still
+seems manageable, but clearly this fully-connected structure does not
+scale to larger images. For example, an image of more respectable
+size, say \( 200\times 200\times 3 \), would lead to neurons that have
+\( 200\times 200\times 3 = 120,000 \) weights.
+
+
+
We could have
+several such neurons, and the parameters would add up quickly! Clearly,
+this full connectivity is wasteful and the huge number of parameters
+would quickly lead to possible overfitting.
+
+
+
+
+
+
Figure 1: A regular 3-layer Neural Network.
+
+
+
+
+
+
3D volumes of neurons
+
+
Convolutional Neural Networks take advantage of the fact that the
+input consists of images and they constrain the architecture in a more
+sensible way.
+
+
+
In particular, unlike a regular Neural Network, the
+layers of a CNN have neurons arranged in 3 dimensions: width,
+height, depth. (Note that the word depth here refers to the third
+dimension of an activation volume, not to the depth of a full Neural
+Network, which can refer to the total number of layers in a network.)
+
+
+
To understand it better, the above example of an image
+with an input volume of
+activations has dimensions \( 32\times 32\times 3 \) (width, height,
+depth respectively).
+
+
+
The neurons in a layer will
+only be connected to a small region of the layer before it, instead of
+all of the neurons in a fully-connected manner. Moreover, the final
+output layer could for this specific image have dimensions \( 1\times 1 \times 10 \),
+because by the
+end of the CNN architecture we will reduce the full image into a
+single vector of class scores, arranged along the depth
+dimension.
+
+
+
+
+
+
Figure 2: A CNN arranges its neurons in three dimensions (width, height, depth), as visualized in one of the layers. Every layer of a CNN transforms the 3D input volume to a 3D output volume of neuron activations. In this example, the red input layer holds the image, so its width and height would be the dimensions of the image, and the depth would be 3 (Red, Green, Blue channels).
+
+
+
+
+
+
Layers used to build CNNs
+
+
A simple CNN is a sequence of layers, and every layer of a CNN
+transforms one volume of activations to another through a
+differentiable function. We use three main types of layers to build
+CNN architectures: Convolutional Layer, Pooling Layer, and
+Fully-Connected Layer (exactly as seen in regular Neural Networks). We
+will stack these layers to form a full CNN architecture.
+
+
+
A simple CNN for image classification could have the architecture:
+
+
+
INPUT (\( 32\times 32 \times 3 \)) will hold the raw pixel values of the image, in this case an image of width 32, height 32, and with three color channels R,G,B.
+
CONV (convolutional )layer will compute the output of neurons that are connected to local regions in the input, each computing a dot product between their weights and a small region they are connected to in the input volume. This may result in volume such as \( [32\times 32\times 12] \) if we decided to use 12 filters.
+
RELU layer will apply an elementwise activation function, such as the \( max(0,x) \) thresholding at zero. This leaves the size of the volume unchanged (\( [32\times 32\times 12] \)).
+
POOL (pooling) layer will perform a downsampling operation along the spatial dimensions (width, height), resulting in volume such as \( [16\times 16\times 12] \).
+
FC (i.e. fully-connected) layer will compute the class scores, resulting in volume of size \( [1\times 1\times 10] \), where each of the 10 numbers correspond to a class score, such as among the 10 categories of the MNIST images we considered above . As with ordinary Neural Networks and as the name implies, each neuron in this layer will be connected to all the numbers in the previous volume.
+
+
+
Transforming images
+
+
CNNs transform the original image layer by layer from the original
+pixel values to the final class scores.
+
+
+
Observe that some layers contain
+parameters and other don’t. In particular, the CNN layers perform
+transformations that are a function of not only the activations in the
+input volume, but also of the parameters (the weights and biases of
+the neurons). On the other hand, the RELU/POOL layers will implement a
+fixed function. The parameters in the CONV/FC layers will be trained
+with gradient descent so that the class scores that the CNN computes
+are consistent with the labels in the training set for each image.
+
However, both standard feed forwards networks and CNNs perform well on data with unknown length.
+
The textbook by Goodfellow et al, see chapter 9 contains an in depth discussion as well.
+
+
+
Key Idea
+
+
A dense neural network is representd by an affine operation (like matrix-matrix multiplication) where all parameters are included.
+
+
The key idea in CNNs for say imaging is that in images neighbor pixels tend to be related! So we connect
+only neighboring neurons in the input instead of connecting all with the first hidden layer.
+
+
+
We say we perform a filtering (convolution is the mathematical operation).
+
+
+
Mathematics of CNNs
+
+
The mathematics of CNNs is based on the mathematical operation of
+convolution. In mathematics (in particular in functional analysis),
+convolution is represented by mathematical operation (integration,
+summation etc) on two function in order to produce a third function
+that expresses how the shape of one gets modified by the other.
+Convolution has a plethora of applications in a variety of disciplines, spanning from statistics to signal processing, computer vision, solutions of differential equations,linear algebra, engineering, and yes, machine learning.
+
+
+
Mathematically, convolution is defined as follows (one-dimensional example):
+Let us define a continuous function \( y(t) \) given by
+
+$$
+y(t) = \int x(a) w(t-a) da,
+$$
+
+
where \( x(a) \) represents a so-called input and \( w(t-a) \) is normally called the weight function or kernel.
+
+
The above integral is written in a more compact form as
Computing the inverse of the above convolution operations is known as deconvolution.
+
+
How can we use this? And what does it mean? Let us study some familiar examples first.
+
+
+
Convolution Examples: Polynomial multiplication
+
+
We have already met such an example in project 1 when we tried to set
+up the design matrix for a two-dimensional function. This was an
+example of polynomial multiplication. Let us recast such a problem in terms of the convolution operation.
+Let us look a the following polynomials to second and third order, respectively:
+
Computing polynomial products can be implemented efficiently if we rewrite the more brute force multiplications using convolution.
+We note first that the new coefficients are given as
+
Do you see a potential drawback with these equations?
+
+
+
A more efficient way of coding the above Convolution
+
+
Since we only have a finite number of \( \alpha \) and \( \beta \) values
+which are non-zero, we can rewrite the above convolution expressions
+as a matrix-vector multiplication
+
The process is commutative and we can easily see that we can rewrite the multiplication in terms of a matrix holding \( \beta \) and a vector holding \( \alpha \).
+In this case we have
+
Note that the use of these matrices is for mathematical purposes only and not implementation purposes.
+When implementing the above equation we do not encode (and allocate memory) the matrices explicitely.
+We rather code the convolutions in the minimal memory footprint that they require.
+
+
+
Does the number of floating point operations change here when we use the commutative property?
+
+
+
Convolution Examples: Principle of Superposition and Periodic Forces (Fourier Transforms)
+
+
For problems with so-called harmonic oscillations, given by for example the following differential equation
where \( F(t) \) is an applied external force acting on the system (often called a driving force), one can use the theory of Fourier transformations to find the solutions of this type of equations.
+
+
If one has several driving forces, \( F(t)=\sum_n F_n(t) \), one can find
+the particular solution to each \( F_n \), \( x_{pn}(t) \), and the particular
+solution for the entire driving force is then given by a series like
+
This is known as the principle of superposition. It only applies when
+the homogenous equation is linear. If there were an anharmonic term
+such as \( x^3 \) in the homogenous equation, then when one summed various
+solutions, \( x=(\sum_n x_n)^2 \), one would get cross
+terms. Superposition is especially useful when \( F(t) \) can be written
+as a sum of sinusoidal terms, because the solutions for each
+sinusoidal (sine or cosine) term is analytic.
+
+
+
Driving forces are often periodic, even when they are not
+sinusoidal. Periodicity implies that for some time \( \tau \)
+
One example of a non-sinusoidal periodic force is a square wave. Many
+components in electric circuits are non-linear, e.g. diodes, which
+makes many wave forms non-sinusoidal even when the circuits are being
+driven by purely sinusoidal sources.
+
+
+
+
Simple Code Example
+
+
The code here shows a typical example of such a square wave generated using the functionality included in the scipy Python package. We have used a period of \( \tau=0.2 \).
+
+
+
+
+
+
+
+
+
importnumpyasnp
+importmath
+fromscipyimport signal
+importmatplotlib.pyplotasplt
+
+# number of points
+n =500
+# start and final times
+t0 =0.0
+tn =1.0
+# Period
+t = np.linspace(t0, tn, n, endpoint=False)
+SqrSignal = np.zeros(n)
+SqrSignal =1.0+signal.square(2*np.pi*5*t)
+plt.plot(t, SqrSignal)
+plt.ylim(-0.5, 2.5)
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
For the sinusoidal example the
+period is \( \tau=2\pi/\omega \). However, higher harmonics can also
+satisfy the periodicity requirement. In general, any force that
+satisfies the periodicity requirement can be expressed as a sum over
+harmonics,
+
We can write down the answer for
+\( x_{pn}(t) \), by substituting \( f_n/m \) or \( g_n/m \) for \( F_0/m \). By
+writing each factor \( 2n\pi t/\tau \) as \( n\omega t \), with \( \omega\equiv
+2\pi/\tau \),
+
Because the forces have been applied for a long time, any non-zero
+damping eliminates the homogenous parts of the solution, so one need
+only consider the particular solution for each \( n \).
+
+
+
The problem is considered solved if one can find expressions for the
+coefficients \( f_n \) and \( g_n \), even though the solutions are expressed
+as an infinite sum. The coefficients can be extracted from the
+function \( F(t) \) by
+
To check the consistency of these expressions and to verify
+Eq. \eqref{eq:fourierdef2}, one can insert the expansion of \( F(t) \) in
+Eq. \eqref{eq:fourierdef1} into the expression for the coefficients in
+Eq. \eqref{eq:fourierdef2} and see whether
+
Immediately, one can throw away all the terms with \( g_m \) because they
+convolute an even and an odd function. The term with \( f_0/2 \)
+disappears because \( \cos(n\omega t) \) is equally positive and negative
+over the interval and will integrate to zero. For all the terms
+\( f_m\cos(m\omega t) \) appearing in the sum, one can use angle addition
+formulas to see that \( \cos(m\omega t)\cos(n\omega
+t)=(1/2)(\cos[(m+n)\omega t]+\cos[(m-n)\omega t] \). This will integrate
+to zero unless \( m=n \). In that case the \( m=n \) term gives
+
The same method can be used to check for the consistency of \( g_n \).
+
+
+
Final words on Fourier Transforms
+
+
The code here uses the Fourier series applied to a
+square wave signal. The code here
+visualizes the various approximations given by Fourier series compared
+with a square wave with period \( T=0.2 \) (dimensionless time), width \( 0.1 \) and max value of the force \( F=2 \). We
+see that when we increase the number of components in the Fourier
+series, the Fourier series approximation gets closer and closer to the
+square wave signal.
+
+
+
+
+
+
+
+
+
+
importnumpyasnp
+importmath
+fromscipyimport signal
+importmatplotlib.pyplotasplt
+
+# number of points
+n =500
+# start and final times
+t0 =0.0
+tn =1.0
+# Period
+T =0.2
+# Max value of square signal
+Fmax=2.0
+# Width of signal
+Width =0.1
+t = np.linspace(t0, tn, n, endpoint=False)
+SqrSignal = np.zeros(n)
+FourierSeriesSignal = np.zeros(n)
+SqrSignal =1.0+signal.square(2*np.pi*5*t+np.pi*Width/T)
+a0 = Fmax*Width/T
+FourierSeriesSignal = a0
+Factor =2.0*Fmax/np.pi
+for i inrange(1,500):
+ FourierSeriesSignal += Factor/(i)*np.sin(np.pi*i*Width/T)*np.cos(i*t*2*np.pi/T)
+plt.plot(t, SqrSignal)
+plt.plot(t, FourierSeriesSignal)
+plt.ylim(-0.5, 2.5)
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Two-dimensional Objects
+
+
We often use convolutions over more than one dimension at a time. If
+we have a two-dimensional image \( I \) as input, we can have a filter
+defined by a two-dimensional kernel \( K \). This leads to an output \( S \)
+
Normally the latter is more straightforward to implement in a machine elarning library since there is less variation in the range of values of \( m \) and \( n \).
+
+
+
Cross-Correlation
+
+
Many deep learning libraries implement cross-correlation instead of convolution
In feilds like signal processing (and imaging as well), one designs
+so-called filters. These filters are defined by the convolutions and
+are often hand-crafted. One may specify filters for smoothing, edge
+detection, frequency reshaping, and similar operations. However with
+neural networks the idea is to automatically learn the filters and use
+many of them in conjunction with non-linear operations (activation
+functions).
+
+
+
As an example consider a neural network operating on sound sequence
+data. Assume that we an input vector \( \boldsymbol{x} \) of length \( d=10^6 \). We
+construct then a neural network with onle hidden layer only with
+\( 10^4 \) nodes. This means that we will have a weight matrix with
+\( 10^4\times 10^6=10^{10} \) weights to be determined, together with \( 10^4 \) biases.
+
+
+
Assume furthermore that we have an output layer which is meant to train whether the sound sequence represents a human voice (true) or something else (false).
+It means that we have only one output node. But since this output node connects to \( 10^4 \) nodes in the hidden layer, there are in total \( 10^4 \) weights to be determined for the output layer, plus one bias. In total we have
+
In today’s architecture one can train such neural networks, however
+this is a huge number of parameters for the task at hand. In general,
+it is a very wasteful and inefficient use of dense matrices as
+parameters. Just as importantly, such trained network parameters are
+very specific for the type of input data on which they were trained
+and the network is not likely to generalize easily to variations in
+the input.
+
+
+
The main principles that justify convolutions is locality of
+information and repetion of patterns within the signal. Sound samples
+of the input in adjacent spots are much more likely to affect each
+other than those that are very far away. Similarly, sounds are
+repeated in multiple times in the signal. While slightly simplistic,
+reasoning about such a sound example demonstrates this. The same
+principles then apply to images and other similar data.
+
CNNs in more detail, building convolutional neural networks in Tensorflow and Keras
+
+
As discussed above, CNNs are neural networks built from the assumption that the inputs
+to the network are 2D images. This is important because the number of features or pixels in images
+grows very fast with the image size, and an enormous number of weights and biases are needed in order to build an accurate network.
+
+
+
As before, we still have our input, a hidden layer and an output. What's novel about convolutional networks
+are the convolutional and pooling layers stacked in pairs between the input and the hidden layer.
+In addition, the data is no longer represented as a 2D feature matrix, instead each input is a number of 2D
+matrices, typically 1 for each color dimension (Red, Green, Blue).
+
+
+
+
Setting it up
+
+
It means that to represent the entire
+dataset of images, we require a 4D matrix or tensor. This tensor has the dimensions:
+
The MNIST dataset consists of grayscale images with a pixel size of
+\( 28\times 28 \), meaning we require \( 28 \times 28 = 724 \) weights to each
+neuron in the first hidden layer.
+
+
+
If we were to analyze images of size \( 128\times 128 \) we would require
+\( 128 \times 128 = 16384 \) weights to each neuron. Even worse if we were
+dealing with color images, as most images are, we have an image matrix
+of size \( 128\times 128 \) for each color dimension (Red, Green, Blue),
+meaning 3 times the number of weights \( = 49152 \) are required for every
+single neuron in the first hidden layer.
+
+
+
+
+
Strong correlations
+
+
Images typically have strong local correlations, meaning that a small
+part of the image varies little from its neighboring regions. If for
+example we have an image of a blue car, we can roughly assume that a
+small blue part of the image is surrounded by other blue regions.
+
+
+
Therefore, instead of connecting every single pixel to a neuron in the
+first hidden layer, as we have previously done with deep neural
+networks, we can instead connect each neuron to a small part of the
+image (in all 3 RGB depth dimensions). The size of each small area is
+fixed, and known as a receptive.
+
+
+
+
+
Layers of a CNN
+
The layers of a convolutional neural network arrange neurons in 3D: width, height and depth.
+The input image is typically a square matrix of depth 3.
+
+
+
A convolution is performed on the image which outputs
+a 3D volume of neurons. The weights to the input are arranged in a number of 2D matrices, known as filters.
+
+
+
Each filter slides along the input image, taking the dot product
+between each small part of the image and the filter, in all depth
+dimensions. This is then passed through a non-linear function,
+typically the Rectified Linear (ReLu) function, which serves as the
+activation of the neurons in the first convolutional layer. This is
+further passed through a pooling layer, which reduces the size of the
+convolutional layer, e.g. by taking the maximum or average across some
+small regions, and this serves as input to the next convolutional
+layer.
+
+
+
+
Systematic reduction
+
+
By systematically reducing the size of the input volume, through
+convolution and pooling, the network should create representations of
+small parts of the input, and then from them assemble representations
+of larger areas. The final pooling layer is flattened to serve as
+input to a hidden layer, such that each neuron in the final pooling
+layer is connected to every single neuron in the hidden layer. This
+then serves as input to the output layer, e.g. a softmax output for
+classification.
+
+
+
+
+
Prerequisites: Collect and pre-process data
+
+
+
+
+
+
+
+
# import necessary packages
+importnumpyasnp
+importmatplotlib.pyplotasplt
+fromsklearnimport datasets
+
+
+# ensure the same random numbers appear every time
+np.random.seed(0)
+
+# display images in notebook
+%matplotlib inline
+plt.rcParams['figure.figsize'] = (12,12)
+
+
+# download MNIST dataset
+digits = datasets.load_digits()
+
+# define inputs and labels
+inputs = digits.images
+labels = digits.target
+
+# RGB images have a depth of 3
+# our images are grayscale so they should have a depth of 1
+inputs = inputs[:,:,:,np.newaxis]
+
+print("inputs = (n_inputs, pixel_width, pixel_height, depth) = "+str(inputs.shape))
+print("labels = (n_inputs) = "+str(labels.shape))
+
+
+# choose some random images to display
+n_inputs =len(inputs)
+indices = np.arange(n_inputs)
+random_indices = np.random.choice(indices, size=5)
+
+for i, image inenumerate(digits.images[random_indices]):
+ plt.subplot(1, 5, i+1)
+ plt.axis('off')
+ plt.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')
+ plt.title("Label: %d"% digits.target[random_indices[i]])
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Importing Keras and Tensorflow
+
+
+
+
+
+
+
+
fromtensorflow.kerasimport datasets, layers, models
+fromtensorflow.keras.layersimport Input
+fromtensorflow.keras.modelsimport Sequential #This allows appending layers to existing models
+fromtensorflow.keras.layersimport Dense #This allows defining the characteristics of a particular layer
+fromtensorflow.kerasimport optimizers #This allows using whichever optimiser we want (sgd,adam,RMSprop)
+fromtensorflow.kerasimport regularizers #This allows using whichever regularizer we want (l1,l2,l1_l2)
+fromtensorflow.keras.utilsimport to_categorical #This allows using categorical cross entropy as the cost function
+#from tensorflow.keras import Conv2D
+#from tensorflow.keras import MaxPooling2D
+#from tensorflow.keras import Flatten
+
+fromsklearn.model_selectionimport train_test_split
+
+# representation of labels
+labels = to_categorical(labels)
+
+# split into train and test data
+# one-liner from scikit-learn library
+train_size =0.8
+test_size =1- train_size
+X_train, X_test, Y_train, Y_test = train_test_split(inputs, labels, train_size=train_size,
+ test_size=test_size)
+
The CIFAR10 dataset contains 60,000 color images in 10 classes, with
+6,000 images in each class. The dataset is divided into 50,000
+training images and 10,000 testing images. The classes are mutually
+exclusive and there is no overlap between them.
+
+
+
+
+
+
+
+
+
+
importtensorflowastf
+
+fromtensorflow.kerasimport datasets, layers, models
+importmatplotlib.pyplotasplt
+
+# We import the data set
+(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()
+
+# Normalize pixel values to be between 0 and 1 by dividing by 255.
+train_images, test_images = train_images /255.0, test_images /255.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Verifying the data set
+
+
To verify that the dataset looks correct, let's plot the first 25 images from the training set and display the class name below each image.
+
+
+
+
+
+
+
+
+
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
+ 'dog', 'frog', 'horse', 'ship', 'truck']
+
+plt.figure(figsize=(10,10))
+for i inrange(25):
+ plt.subplot(5,5,i+1)
+ plt.xticks([])
+ plt.yticks([])
+ plt.grid(False)
+ plt.imshow(train_images[i], cmap=plt.cm.binary)
+ # The CIFAR labels happen to be arrays,
+ # which is why you need the extra index
+ plt.xlabel(class_names[train_labels[i][0]])
+plt.show()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Set up the model
+
+
The 6 lines of code below define the convolutional base using a common pattern: a stack of Conv2D and MaxPooling2D layers.
+
+
As input, a CNN takes tensors of shape (image_height, image_width, color_channels), ignoring the batch size. If you are new to these dimensions, color_channels refers to (R,G,B). In this example, you will configure our CNN to process inputs of shape (32, 32, 3), which is the format of CIFAR images. You can do this by passing the argument input_shape to our first layer.
+
+
+
+
+
+
+
+
+
model = models.Sequential()
+model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
+model.add(layers.MaxPooling2D((2, 2)))
+model.add(layers.Conv2D(64, (3, 3), activation='relu'))
+model.add(layers.MaxPooling2D((2, 2)))
+model.add(layers.Conv2D(64, (3, 3), activation='relu'))
+
+# Let's display the architecture of our model so far.
+
+model.summary()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
You can see that the output of every Conv2D and MaxPooling2D layer is a 3D tensor of shape (height, width, channels). The width and height dimensions tend to shrink as you go deeper in the network. The number of output channels for each Conv2D layer is controlled by the first argument (e.g., 32 or 64). Typically, as the width and height shrink, you can afford (computationally) to add more output channels in each Conv2D layer.
+
+
+
Add Dense layers on top
+
+
To complete our model, you will feed the last output tensor from the
+convolutional base (of shape (4, 4, 64)) into one or more Dense layers
+to perform classification. Dense layers take vectors as input (which
+are 1D), while the current output is a 3D tensor. First, you will
+flatten (or unroll) the 3D output to 1D, then add one or more Dense
+layers on top. CIFAR has 10 output classes, so you use a final Dense
+layer with 10 outputs and a softmax activation.
+
+
+
+
+
+
+
+
+
+
model.add(layers.Flatten())
+model.add(layers.Dense(64, activation='relu'))
+model.add(layers.Dense(10))
+Here's the complete architecture of our model.
+
+model.summary()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
As you can see, our (4, 4, 64) outputs were flattened into vectors of shape (1024) before going through two Dense layers.
@@ -1169,7 +2487,7 @@ samples
$$
\begin{equation}
x = g(z; \theta^{(g)})
-\label{_auto1}
+\label{_auto4}
\end{equation}
$$
@@ -1186,7 +2504,7 @@ value given by
$$
\begin{equation}
d(x; \theta^{(d)})
-\label{_auto2}
+\label{_auto5}
\end{equation}
$$
@@ -1199,7 +2517,7 @@ which a function
$$
\begin{equation}
v(\theta^{(g)}, \theta^{(d)})
-\label{_auto3}
+\label{_auto6}
\end{equation}
$$
@@ -1210,7 +2528,7 @@ conjugate reward
$$
\begin{equation}
-v(\theta^{(g)}, \theta^{(d)})
-\label{_auto4}
+\label{_auto7}
\end{equation}
$$
@@ -1245,7 +2563,7 @@ $$
\begin{equation}
g^* = \underset{g}{\mathrm{argmin}}\hspace{2pt}
\underset{d}{\mathrm{max}}v(\theta^{(g)}, \theta^{(d)})
-\label{_auto5}
+\label{_auto8}
\end{equation}
$$
@@ -1255,7 +2573,7 @@ $$
v(\theta^{(g)}, \theta^{(d)}) = \mathbb{E}_{x\sim p_\mathrm{data}}\log d(x)
+ \mathbb{E}_{x\sim p_\mathrm{model}}
\log (1 - d(x))
-\label{_auto6}
+\label{_auto9}
\end{equation}
$$
@@ -1266,7 +2584,7 @@ approximation of a partition function. In the case where
$$
\begin{equation}
\underset{d}{\mathrm{max}}v(\theta^{(g)}, \theta^{(d)})
-\label{_auto7}
+\label{_auto10}
\end{equation}
$$
@@ -2222,1207 +3540,6 @@ plot_results(results, plot_number)
-
-
Basic ideas of the Principal Component Analysis (PCA)
-
-
The principal component analysis deals with the problem of fitting a
-low-dimensional affine subspace \( S \) of dimension \( d \) much smaller than
-the total dimension \( D \) of the problem at hand (our data
-set). Mathematically it can be formulated as a statistical problem or
-a geometric problem. In our discussion of the theorem for the
-classical PCA, we will stay with a statistical approach.
-Historically, the PCA was first formulated in a statistical setting in order to estimate the principal component of a multivariate random variable.
-
-
-
We have a data set defined by a design/feature matrix \( \boldsymbol{X} \) (see below for its definition)
-
-
Each data point is determined by \( p \) extrinsic (measurement) variables
-
We may want to ask the following question: Are there fewer intrinsic variables (say \( d < < p \)) that still approximately describe the data?
-
If so, these intrinsic variables may tell us something important and finding these intrinsic variables is what dimension reduction methods do.
Introducing the Covariance and Correlation functions
-
-
Before we discuss the PCA theorem, we need to remind ourselves about
-the definition of the covariance and the correlation function. These are quantities
-
-
-
Suppose we have defined two vectors
-\( \hat{x} \) and \( \hat{y} \) with \( n \) elements each. The covariance matrix \( \boldsymbol{C} \) is defined as
-
The covariance takes values between zero and infinity and may thus
-lead to problems with loss of numerical precision for particularly
-large values. It is common to scale the covariance matrix by
-introducing instead the correlation matrix defined via the so-called
-correlation function
-
The correlation function is then given by values \( \mathrm{corr}[\boldsymbol{x},\boldsymbol{y}]
-\in [-1,1] \). This avoids eventual problems with too large values. We
-can then define the correlation matrix for the two vectors \( \boldsymbol{x} \)
-and \( \boldsymbol{y} \) as
-
In the above example this is the function we constructed using pandas.
-
-
-
Reminding ourselves about Linear Regression
-
In our derivation of the various regression algorithms like Ordinary Least Squares or Ridge regression
-we defined the design/feature matrix \( \boldsymbol{X} \) as
-
with \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \), with the predictors/features \( p \) refering to the column numbers and the
-entries \( n \) being the row elements.
-We can rewrite the design/feature matrix in terms of its column vectors as
-
With these definitions, we can now rewrite our \( 2\times 2 \)
-correlation/covariance matrix in terms of a moe general design/feature
-matrix \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \). This leads to a \( p\times p \)
-covariance matrix for the vectors \( \boldsymbol{x}_i \) with \( i=0,1,\dots,p-1 \)
-
The Numpy function np.cov calculates the covariance elements using
-the factor \( 1/(n-1) \) instead of \( 1/n \) since it assumes we do not have
-the exact mean values. The following simple function uses the
-np.vstack function which takes each vector of dimension \( 1\times n \)
-and produces a \( 2\times n \) matrix \( \boldsymbol{W} \)
-
which in turn is converted into into the \( 2\times 2 \) covariance matrix
-\( \boldsymbol{C} \) via the Numpy function np.cov(). We note that we can also calculate
-the mean value of each set of samples \( \boldsymbol{x} \) etc using the Numpy
-function np.mean(x). We can also extract the eigenvalues of the
-covariance matrix through the np.linalg.eig() function.
-
The previous example can be converted into the correlation matrix by
-simply scaling the matrix elements with the variances. We should also
-subtract the mean values for each column. This leads to the following
-code which sets up the correlations matrix for the previous example in
-a more brute force way. Here we scale the mean values for each column of the design matrix, calculate the relevant mean values and variances and then finally set up the \( 2\times 2 \) correlation matrix (since we have only two vectors).
-
-
-
-
-
-
-
-
-
-
importnumpyasnp
-n =100
-# define two vectors
-x = np.random.random(size=n)
-y =4+3*x+np.random.normal(size=n)
-#scaling the x and y vectors
-x = x - np.mean(x)
-y = y - np.mean(y)
-variance_x = np.sum(x@x)/n
-variance_y = np.sum(y@y)/n
-print(variance_x)
-print(variance_y)
-cov_xy = np.sum(x@y)/n
-cov_xx = np.sum(x@x)/n
-cov_yy = np.sum(y@y)/n
-C = np.zeros((2,2))
-C[0,0]= cov_xx/variance_x
-C[1,1]= cov_yy/variance_y
-C[0,1]= cov_xy/np.sqrt(variance_y*variance_x)
-C[1,0]= C[0,1]
-print(C)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
We see that the matrix elements along the diagonal are one as they
-should be and that the matrix is symmetric. Furthermore, diagonalizing
-this matrix we easily see that it is a positive definite matrix.
-
-
-
The above procedure with numpy can be made more compact if we use pandas.
-
-
-
Using Pandas
-
-
We whow here how we can set up the correlation matrix using pandas, as done in this simple code
We expand this model to the Franke function discussed above.
-
-
-
-
-
-
-
-
-
# Common imports
-importnumpyasnp
-importpandasaspd
-
-
-defFrankeFunction(x,y):
- term1 =0.75*np.exp(-(0.25*(9*x-2)**2) -0.25*((9*y-2)**2))
- term2 =0.75*np.exp(-((9*x+1)**2)/49.0-0.1*(9*y+1))
- term3 =0.5*np.exp(-(9*x-7)**2/4.0-0.25*((9*y-3)**2))
- term4 =-0.2*np.exp(-(9*x-4)**2- (9*y-7)**2)
- return term1 + term2 + term3 + term4
-
-
-defcreate_X(x, y, n ):
- iflen(x.shape) >1:
- x = np.ravel(x)
- y = np.ravel(y)
-
- N =len(x)
- l =int((n+1)*(n+2)/2) # Number of elements in beta
- X = np.ones((N,l))
-
- for i inrange(1,n+1):
- q =int((i)*(i+1)/2)
- for k inrange(i+1):
- X[:,q+k] = (x**(i-k))*(y**k)
-
- return X
-
-
-# Making meshgrid of datapoints and compute Franke's function
-n =4
-N =100
-x = np.sort(np.random.uniform(0, 1, N))
-y = np.sort(np.random.uniform(0, 1, N))
-z = FrankeFunction(x, y)
-X = create_X(x, y, n=n)
-
-Xpd = pd.DataFrame(X)
-# subtract the mean values and set up the covariance matrix
-Xpd = Xpd - Xpd.mean()
-covariance_matrix = Xpd.cov()
-print(covariance_matrix)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
We note here that the covariance is zero for the first rows and
-columns since all matrix elements in the design matrix were set to one
-(we are fitting the function in terms of a polynomial of degree \( n \)). We would however not include the intercept
-and wee can simply
-drop these elements and construct a correlation
-matrix without them by centering our matrix elements by subtracting the mean of each column.
-
-
-
-
Lnks with the Design Matrix
-
-
We can rewrite the covariance matrix in a more compact form in terms of the design/feature matrix \( \boldsymbol{X} \) as
where we wrote $$\boldsymbol{C}[\boldsymbol{x}_0,\boldsymbol{x}_1] = \boldsymbol{C}[\boldsymbol{x}]$$ to indicate that this the covariance of the vectors \( \boldsymbol{x} \) of the design/feature matrix \( \boldsymbol{X} \).
-
-
It is easy to generalize this to a matrix \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \).
-
-
-
Towards the PCA theorem
-
-
We have that the covariance matrix (the correlation matrix involves a simple rescaling) is given as
Let us now assume that we can perform a series of orthogonal transformations where we employ some orthogonal matrices \( \boldsymbol{S} \).
-These matrices are defined as \( \boldsymbol{S}\in {\mathbb{R}}^{p\times p} \) and obey the orthogonality requirements \( \boldsymbol{S}\boldsymbol{S}^T=\boldsymbol{S}^T\boldsymbol{S}=\boldsymbol{I} \). The matrix can be written out in terms of the column vectors \( \boldsymbol{s}_i \) as \( \boldsymbol{S}=[\boldsymbol{s}_0,\boldsymbol{s}_1,\dots,\boldsymbol{s}_{p-1}] \) and \( \boldsymbol{s}_i \in {\mathbb{R}}^{p} \).
-
-
-
Assume also that there is a transformation \( \boldsymbol{S}^T\boldsymbol{C}[\boldsymbol{x}]\boldsymbol{S}=\boldsymbol{C}[\boldsymbol{y}] \) such that the new matrix \( \boldsymbol{C}[\boldsymbol{y}] \) is diagonal with elements \( [\lambda_0,\lambda_1,\lambda_2,\dots,\lambda_{p-1}] \).
In the derivation of the PCA theorem we will assume that the eigenvalues are ordered in descending order, that is
-\( \lambda_0 > \lambda_1 > \dots > \lambda_{p-1} \).
-
-
-
The eigenvalues tell us then how much we need to stretch the
-corresponding eigenvectors. Dimensions with large eigenvalues have
-thus large variations (large variance) and define therefore useful
-dimensions. The data points are more spread out in the direction of
-these eigenvectors. Smaller eigenvalues mean on the other hand that
-the corresponding eigenvectors are shrunk accordingly and the data
-points are tightly bunched together and there is not much variation in
-these specific directions. Hopefully then we could leave it out
-dimensions where the eigenvalues are very small. If \( p \) is very large,
-we could then aim at reducing \( p \) to \( l < < p \) and handle only \( l \)
-features/predictors.
-
-
-
-
The Algorithm before theorem
-
-
Here's how we would proceed in setting up the algorithm for the PCA, see also discussion below here.
-
-
Set up the datapoints for the design/feature matrix \( \boldsymbol{X} \) with \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \), with the predictors/features \( p \) referring to the column numbers and the entries \( n \) being the row elements.
Center the data by subtracting the mean value for each column. This leads to a new matrix \( \boldsymbol{X}\rightarrow \overline{\boldsymbol{X}} \).
-
Compute then the covariance/correlation matrix \( \mathbb{E}[\overline{\boldsymbol{X}}^T\overline{\boldsymbol{X}}] \).
-
Find the eigenpairs of \( \boldsymbol{C} \) with eigenvalues \( [\lambda_0,\lambda_1,\dots,\lambda_{p-1}] \) and eigenvectors \( [\boldsymbol{s}_0,\boldsymbol{s}_1,\dots,\boldsymbol{s}_{p-1}] \).
-
Order the eigenvalue (and the eigenvectors accordingly) in order of decreasing eigenvalues.
-
Keep only those \( l \) eigenvalues larger than a selected threshold value, discarding thus \( p-l \) features since we expect small variations in the data here.
-
-
-
Writing our own PCA code
-
-
We will use a simple example first with two-dimensional data
-drawn from a multivariate normal distribution with the following mean and covariance matrix (we have fixed these quantities but will play around with them below):
-
Note that the mean refers to each column of data.
-We will generate \( n = 10000 \) points \( X = \{ x_1, \ldots, x_N \} \) from
-this distribution, and store them in the \( 1000 \times 2 \) matrix \( \boldsymbol{X} \). This is our design matrix where we have forced the covariance and mean values to take specific values.
-
-
-
-
Implementing it
-
The following Python code aids in setting up the data and writing out the design matrix.
-Note that the function multivariate returns also the covariance discussed above and that it is defined by dividing by \( n-1 \) instead of \( n \).
-
Now we are going to implement the PCA algorithm. We will break it down into various substeps.
-
-
-
First Step
-
-
The first step of PCA is to compute the sample mean of the data and use it to center the data. Recall that the sample mean is
-$$
-\mu_n = \frac{1}{n} \sum_{i=1}^n x_i
-$$
-
-
and the mean-centered data \( \bar{X} = \{ \bar{x}_1, \ldots, \bar{x}_n \} \) takes the form
-$$
-\bar{x}_i = x_i - \mu_n.
-$$
-
-
When you are done with these steps, print out \( \mu_n \) to verify it is
-close to \( \mu \) and plot your mean centered data to verify it is
-centered at the origin!
-The following code elements perform these operations using pandas or using our own functionality for doing so. The latter, using numpy is rather simple through the mean() function.
-
-
-
-
-
-
-
-
-
df = pd.DataFrame(X)
-# Pandas does the centering for us
-df = df -df.mean()
-# we center it ourselves
-X_centered = X - X.mean(axis=0)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Scaling
-
Alternatively, we could use the functions we discussed
-earlier for scaling the data set. That is, we could have used the
-StandardScaler function in Scikit-Learn, a function which ensures
-that for each feature/predictor we study the mean value is zero and
-the variance is one (every column in the design/feature matrix). You
-would then not get the same results, since we divide by the
-variance. The diagonal covariance matrix elements will then be one,
-while the non-diagonal ones need to be divided by \( 2\sqrt{2} \) for our
-specific case.
-
-
-
-
Centered Data
-
-
Now we are going to use the mean centered data to compute the sample covariance of the data by using the following equation
where the data points \( x_i \in \mathbb{R}^p \) (here in this example \( p = 2 \)) are column vectors and \( x^T \) is the transpose of \( x \).
-We can write our own code or simply use either the functionaly of numpy or that of pandas, as follows
-
-
-
-
-
-
-
-
-
print(df.cov())
-print(np.cov(X_centered.T))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Note that the way we define the covariance matrix here has a factor \( n-1 \) instead of \( n \). This is included in the cov() function by numpy and pandas.
-Our own code here is not very elegant and asks for obvious improvements. It is tailored to this specific \( 2\times 2 \) covariance matrix.
-
-
-
-
-
-
-
-
-
# extract the relevant columns from the centered design matrix of dim n x 2
-x = X_centered[:,0]
-y = X_centered[:,1]
-Cov = np.zeros((2,2))
-Cov[0,1] = np.sum(x.T@y)/(n-1.0)
-Cov[0,0] = np.sum(x.T@x)/(n-1.0)
-Cov[1,1] = np.sum(y.T@y)/(n-1.0)
-Cov[1,0]= Cov[0,1]
-print("Centered covariance using own code")
-print(Cov)
-plt.plot(x, y, 'x')
-plt.axis('equal')
-plt.show()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Exploring
-
-
Depending on the number of points \( n \), we will get results that are close to the covariance values defined above.
-The plot shows how the data are clustered around a line with slope close to one. Is this expected? Try to change the covariance and the mean values. For example, try to make the variance of the first element much larger than that of the second diagonal element. Try also to shrink the covariance (the non-diagonal elements) and see how the data points are distributed.
-
-
-
-
Diagonalize the sample covariance matrix to obtain the principal components
-
-
Now we are ready to solve for the principal components! To do so we
-diagonalize the sample covariance matrix \( \Sigma \). We can use the
-function np.linalg.eig to do so. It will return the eigenvalues and
-eigenvectors of \( \Sigma \). Once we have these we can perform the
-following tasks:
-
-
-
-
We compute the percentage of the total variance captured by the first principal component
-
We plot the mean centered data and lines along the first and second principal components
-
Then we project the mean centered data onto the first and second principal components, and plot the projected data.
Collecting all these steps we can write our own PCA function and
-compare this with the functionality included in Scikit-Learn.
-
-
-
The code here outlines some of the elements we could include in the
-analysis. Feel free to extend upon this in order to address the above
-questions.
-
-
-
-
-
-
-
-
-
-
# diagonalize and obtain eigenvalues, not necessarily sorted
-EigValues, EigVectors = np.linalg.eig(Cov)
-# sort eigenvectors and eigenvalues
-#permute = EigValues.argsort()
-#EigValues = EigValues[permute]
-#EigVectors = EigVectors[:,permute]
-print("Eigenvalues of Covariance matrix")
-for i inrange(2):
- print(EigValues[i])
-FirstEigvector = EigVectors[:,0]
-SecondEigvector = EigVectors[:,1]
-print("First eigenvector")
-print(FirstEigvector)
-print("Second eigenvector")
-print(SecondEigvector)
-#thereafter we do a PCA with Scikit-learn
-fromsklearn.decompositionimport PCA
-pca = PCA(n_components =2)
-X2Dsl = pca.fit_transform(X)
-print("Eigenvector of largest eigenvalue")
-print(pca.components_.T[:, 0])
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
This code does not contain all the above elements, but it shows how we can use Scikit-Learn to extract the eigenvector which corresponds to the largest eigenvalue. Try to address the questions we pose before the above code. Try also to change the values of the covariance matrix by making one of the diagonal elements much larger than the other. What do you observe then?
-
-
-
Classical PCA Theorem
-
-
We assume now that we have a design matrix \( \boldsymbol{X} \) which has been
-centered as discussed above. For the sake of simplicity we skip the
-overline symbol. The matrix is defined in terms of the various column
-vectors \( [\boldsymbol{x}_0,\boldsymbol{x}_1,\dots, \boldsymbol{x}_{p-1}] \) each with dimension
-\( \boldsymbol{x}\in {\mathbb{R}}^{n} \).
-
-
-
The PCA theorem states that minimizing the above reconstruction error
-corresponds to setting \( \boldsymbol{W}=\boldsymbol{S} \), the orthogonal matrix which
-diagonalizes the empirical covariance(correlation) matrix. The optimal
-low-dimensional encoding of the data is then given by a set of vectors
-\( \boldsymbol{z}_i \) with at most \( l \) vectors, with \( l < < p \), defined by the
-orthogonal projection of the data onto the columns spanned by the
-eigenvectors of the covariance(correlations matrix).
-
-
-
-
The PCA Theorem
-
-
To show the PCA theorem let us start with the assumption that there is one vector \( \boldsymbol{s}_0 \) which corresponds to a solution which minimized the reconstruction error \( J \). This is an orthogonal vector. It means that we now approximate the reconstruction error in terms of \( \boldsymbol{w}_0 \) and \( \boldsymbol{z}_0 \) as
-
-
We are almost there, we have obtained a relation between minimizing
-the reconstruction error and the variance and the covariance
-matrix. Minimizing the error is equivalent to maximizing the variance
-of the projected data.
-
-
-
We could trivially maximize the variance of the projection (and
-thereby minimize the error in the reconstruction function) by letting
-the norm-2 of \( \boldsymbol{w}_0 \) go to infinity. However, this norm since we
-want the matrix \( \boldsymbol{W} \) to be an orthogonal matrix, is constrained by
-\( \vert\vert \boldsymbol{w}_0 \vert\vert_2^2=1 \). Imposing this condition via a
-Lagrange multiplier we can then in turn maximize
-
The direction that maximizes the variance (or minimizes the construction error) is an eigenvector of the covariance matrix! If we left multiply with \( \boldsymbol{w}_0^T \) we have the variance of the projected data is
If we want to maximize the variance (minimize the construction error)
-we simply pick the eigenvector of the covariance matrix with the
-largest eigenvalue. This establishes the link between the minimization
-of the reconstruction function \( J \) in terms of an orthogonal matrix
-and the maximization of the variance and thereby the covariance of our
-observations encoded in the design/feature matrix \( \boldsymbol{X} \).
-
-
-
The proof
-for the other eigenvectors \( \boldsymbol{w}_1,\boldsymbol{w}_2,\dots \) can be
-established by applying the above arguments and using the fact that
-our basis of eigenvectors is orthogonal, see Murphy chapter
-12.2. The
-discussion in chapter 12.2 of Murphy's text has also a nice link with
-the Singular Value Decomposition theorem. For categorical data, see
-chapter 12.4 and discussion therein.
-
Principal Component Analysis (PCA) is by far the most popular dimensionality reduction algorithm.
-First it identifies the hyperplane that lies closest to the data, and then it projects the data onto it.
-
-
-
The following Python code uses NumPy’s svd() function to obtain all the principal components of the
-training set, then extracts the first two principal components. First we center the data using either pandas or our own code
-
-
-
-
-
-
-
-
-
importnumpyasnp
-importpandasaspd
-fromIPython.displayimport display
-np.random.seed(100)
-# setting up a 10 x 5 vanilla matrix
-rows =10
-cols =5
-X = np.random.randn(rows,cols)
-df = pd.DataFrame(X)
-# Pandas does the centering for us
-df = df -df.mean()
-display(df)
-
-# we center it ourselves
-X_centered = X - X.mean(axis=0)
-# Then check the difference between pandas and our own set up
-print(X_centered-df)
-#Now we do an SVD
-U, s, V = np.linalg.svd(X_centered)
-c1 = V.T[:, 0]
-c2 = V.T[:, 1]
-W2 = V.T[:, :2]
-X2D = X_centered.dot(W2)
-print(X2D)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PCA assumes that the dataset is centered around the origin. Scikit-Learn’s PCA classes take care of centering
-the data for you. However, if you implement PCA yourself (as in the preceding example), or if you use other libraries, don’t
-forget to center the data first.
-
-
-
Once you have identified all the principal components, you can reduce the dimensionality of the dataset
-down to \( d \) dimensions by projecting it onto the hyperplane defined by the first \( d \) principal components.
-Selecting this hyperplane ensures that the projection will preserve as much variance as possible.
-
-
-
-
-
-
-
-
-
W2 = V.T[:, :2]
-X2D = X_centered.dot(W2)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PCA and scikit-learn
-
-
Scikit-Learn’s PCA class implements PCA using SVD decomposition just like we did before. The
-following code applies PCA to reduce the dimensionality of the dataset down to two dimensions (note
-that it automatically takes care of centering the data):
-
-
-
-
-
-
-
-
-
#thereafter we do a PCA with Scikit-learn
-fromsklearn.decompositionimport PCA
-pca = PCA(n_components =2)
-X2D = pca.fit_transform(X)
-print(X2D)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
After fitting the PCA transformer to the dataset, you can access the principal components using the
-components variable (note that it contains the PCs as horizontal vectors, so, for example, the first
-principal component is equal to
-
-
-
-
-
-
-
-
-
pca.components_.T[:, 0]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Another very useful piece of information is the explained variance ratio of each principal component,
-available via the \( explained\_variance\_ratio \) variable. It indicates the proportion of the dataset’s
-variance that lies along the axis of each principal component.
-
-
-
-
Back to the Cancer Data
-
We can now repeat the above but applied to real data, in this case our breast cancer data.
-Here we compute performance scores on the training data using logistic regression.
-
-
-
-
-
-
-
-
-
importmatplotlib.pyplotasplt
-importnumpyasnp
-fromsklearn.model_selectionimport train_test_split
-fromsklearn.datasetsimport load_breast_cancer
-fromsklearn.linear_modelimport LogisticRegression
-cancer = load_breast_cancer()
-
-X_train, X_test, y_train, y_test = train_test_split(cancer.data,cancer.target,random_state=0)
-
-logreg = LogisticRegression()
-logreg.fit(X_train, y_train)
-print("Train set accuracy from Logistic Regression: {:.2f}".format(logreg.score(X_train,y_train)))
-# We scale the data
-fromsklearn.preprocessingimport StandardScaler
-scaler = StandardScaler()
-scaler.fit(X_train)
-X_train_scaled = scaler.transform(X_train)
-X_test_scaled = scaler.transform(X_test)
-# Then perform again a log reg fit
-logreg.fit(X_train_scaled, y_train)
-print("Train set accuracy scaled data: {:.2f}".format(logreg.score(X_train_scaled,y_train)))
-#thereafter we do a PCA with Scikit-learn
-fromsklearn.decompositionimport PCA
-pca = PCA(n_components =2)
-X2D_train = pca.fit_transform(X_train_scaled)
-# and finally compute the log reg fit and the score on the training data
-logreg.fit(X2D_train,y_train)
-print("Train set accuracy scaled and PCA data: {:.2f}".format(logreg.score(X2D_train,y_train)))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
We see that our training data after the PCA decomposition has a performance similar to the non-scaled data.
-
-
Instead of arbitrarily choosing the number of dimensions to reduce down to, it is generally preferable to
-choose the number of dimensions that add up to a sufficiently large portion of the variance (e.g., 95%).
-Unless, of course, you are reducing dimensionality for data visualization — in that case you will
-generally want to reduce the dimensionality down to 2 or 3.
-The following code computes PCA without reducing dimensionality, then computes the minimum number
-of dimensions required to preserve 95% of the training set’s variance:
-
You could then set \( n\_components=d \) and run PCA again. However, there is a much better option: instead
-of specifying the number of principal components you want to preserve, you can set \( n\_components \) to be
-a float between 0.0 and 1.0, indicating the ratio of variance you wish to preserve:
-
One problem with the preceding implementation of PCA is that it requires the whole training set to fit in
-memory in order for the SVD algorithm to run. Fortunately, Incremental PCA (IPCA) algorithms have
-been developed: you can split the training set into mini-batches and feed an IPCA algorithm one minibatch
-at a time. This is useful for large training sets, and also to apply PCA online (i.e., on the fly, as new
-instances arrive).
-
-
Randomized PCA
-
-
Scikit-Learn offers yet another option to perform PCA, called Randomized PCA. This is a stochastic
-algorithm that quickly finds an approximation of the first d principal components. Its computational
-complexity is \( O(m \times d^2)+O(d^3) \), instead of \( O(m \times n^2) + O(n^3) \), so it is dramatically faster than the
-previous algorithms when \( d \) is much smaller than \( n \).
-
-
Kernel PCA
-
-
The kernel trick is a mathematical technique that implicitly maps instances into a
-very high-dimensional space (called the feature space), enabling nonlinear classification and regression
-with Support Vector Machines. Recall that a linear decision boundary in the high-dimensional feature
-space corresponds to a complex nonlinear decision boundary in the original space.
-It turns out that the same trick can be applied to PCA, making it possible to perform complex nonlinear
-projections for dimensionality reduction. This is called Kernel PCA (kPCA). It is often good at
-preserving clusters of instances after projection, or sometimes even unrolling datasets that lie close to a
-twisted manifold.
-For example, the following code uses Scikit-Learn’s KernelPCA class to perform kPCA with an
-
There are many other dimensionality reduction techniques, several of which are available in Scikit-Learn.
-
-
Here are some of the most popular:
-
-
Multidimensional Scaling (MDS) reduces dimensionality while trying to preserve the distances between the instances.
-
Isomap creates a graph by connecting each instance to its nearest neighbors, then reduces dimensionality while trying to preserve the geodesic distances between the instances.
-
t-Distributed Stochastic Neighbor Embedding (t-SNE) reduces dimensionality while trying to keep similar instances close and dissimilar instances apart. It is mostly used for visualization, in particular to visualize clusters of instances in high-dimensional space (e.g., to visualize the MNIST images in 2D).
-
Linear Discriminant Analysis (LDA) is actually a classification algorithm, but during training it learns the most discriminative axes between the classes, and these axes can then be used to define a hyperplane onto which to project the data. The benefit is that the projection will keep classes as far apart as possible, so LDA is a good technique to reduce dimensionality before running another classification algorithm such as a Support Vector Machine (SVM) classifier discussed in the SVM lectures.