# ELE 435-535 Computational HW 1

### Due: 9/24/2018 11:59 PM

### Importing required Python packages


```python
# Import additional packages if needed.
import numpy as np
import matplotlib.pyplot as plt

%matplotlib inline
```

### Part 1: Getting started with Numpy 

1) Create a 5 x 5 array (A) with random values sampled from Gaussian distribution with zero mean and unit variance. Then print A. Suggestion: numpy has a built-in command for generating random arrays.


```python
A = np.random.normal(size=(5,5))
print(A)
```

    [[ 1.0962995  -1.16635206 -1.95787855  0.80142373 -0.66514612]
     [ 0.57335642  1.44546877  0.48090909 -1.47049494  1.19950587]
     [-1.52292185 -0.82099908 -0.35427914  1.35306041 -1.51084116]
     [ 0.94896773  0.31924362 -0.29705941  2.65454975 -2.35267673]
     [ 0.67286711 -1.17590121  0.70063041  1.75015252 -1.02967792]]


2) Set the element in the $2^{nd}$ row and $3^{rd}$ column of A to be 1 and print the result. Suggestion: check out how to index the elements of a numpy array.


```python
A[1][2] = 1
print(A)
```

    [[ 1.0962995  -1.16635206 -1.95787855  0.80142373 -0.66514612]
     [ 0.57335642  1.44546877  1.         -1.47049494  1.19950587]
     [-1.52292185 -0.82099908 -0.35427914  1.35306041 -1.51084116]
     [ 0.94896773  0.31924362 -0.29705941  2.65454975 -2.35267673]
     [ 0.67286711 -1.17590121  0.70063041  1.75015252 -1.02967792]]


3) Create a 5 x 5 identity array (B) and print it. Suggestion: numpy has a built in command for generating identity matrices.


```python
B = np.eye(5)
print(B)
```

    [[1. 0. 0. 0. 0.]
     [0. 1. 0. 0. 0.]
     [0. 0. 1. 0. 0.]
     [0. 0. 0. 1. 0.]
     [0. 0. 0. 0. 1.]]


4) Set the values below the diagonal of B to be 1,2,3,4. Then, print the result. Suggestion: you can use a for loop.


```python
for i in range(4):
    B[i + 1][i] = i + 1
print(B)
```

    [[1. 0. 0. 0. 0.]
     [1. 1. 0. 0. 0.]
     [0. 2. 1. 0. 0.]
     [0. 0. 3. 1. 0.]
     [0. 0. 0. 4. 1.]]


5) Multiply A and B (matrix multiplication, not point-wise multiplication) to create C (note that A and B are 2D arrays, not matrices). Suggestion: numpy hasd a built-in command for matrix multiplication.


```python
C = np.matmul(A, B)
print(C)
```

    [[-0.07005256 -5.08210916  0.44639264 -1.85916076 -0.66514612]
     [ 2.01882519  3.44546877 -3.41148482  3.32752855  1.19950587]
     [-2.34392093 -1.52955737  3.70490208 -4.69030425 -1.51084116]
     [ 1.26821135 -0.2748752   7.66658983 -6.75615717 -2.35267673]
     [-0.5030341   0.22535961  5.95108797 -2.36855917 -1.02967792]]


6) Create a new array D according to the formula below:
\begin{equation}
D = \sum_{i=1}^5 A_i*B_i \hspace{10mm} (A_i: i^{th} \hspace{3mm} column \hspace{3mm} of \hspace{3mm} A, \hspace{3mm} B_i: i^{th} \hspace{3mm} row \hspace{3mm} of \hspace{3mm} B)   \\
\end{equation}


```python
D = np.zeros(shape=(5, 5))
AT = np.transpose(A)

for i in range(5):
    Ai = np.reshape(np.transpose(AT[i]), (5,1))
    Bi = np.reshape(B[i], (1,5))
    D += np.matmul(Ai, Bi)

print(D)
```

    [[-0.07005256 -5.08210916  0.44639264 -1.85916076 -0.66514612]
     [ 2.01882519  3.44546877 -3.41148482  3.32752855  1.19950587]
     [-2.34392093 -1.52955737  3.70490208 -4.69030425 -1.51084116]
     [ 1.26821135 -0.2748752   7.66658983 -6.75615717 -2.35267673]
     [-0.5030341   0.22535961  5.95108797 -2.36855917 -1.02967792]]


7) Verify that C and D are equal. Suggestion: a==b checks equality.


```python
# There were some floating point errors from the order of operations
print(np.isclose(C, D))

# To convince ourselves, we print out the delta between C and D
print(C - D)
```

    [[ True  True  True  True  True]
     [ True  True  True  True  True]
     [ True  True  True  True  True]
     [ True  True  True  True  True]
     [ True  True  True  True  True]]
    [[ 0.00000000e+00  0.00000000e+00 -1.11022302e-16  0.00000000e+00
       0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
       0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
       0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
       0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00 -8.88178420e-16  0.00000000e+00
       0.00000000e+00]]


### Part 2: Implementation of nearest class mean classifier

In this part, you will implement nearest class mean classifier using the MNIST dataset for handwritten digits. These are 28 x 28  2D grayscale images of hand written digits. When you load the given file MNISTcwtrain1000.npy, you will get a 784 x 10000 numpy array, which you are to use as the training samples and another 784 x 1000 array (from MNISTcwtest100.npy) which is to be used as test samples. You can find more information on http://yann.lecun.com/exdb/mnist/.

Each column in the training and test arrays are 784-pixel (784 = 28 * 28) column-wise vectorized images of handwritten digits (digits 0~9). For the training array, the first 1000 columns are column-wise vectorized images of the digit 0, the next 1000 columns are images of digit 1, and so on up to the last 1000 columns which are images of digit 9. Similarly, for the test array, the first 100 columns are vectorized images of digit 0, the next 100 columns correspond to digit 1, etc.

1) Load the MNISTcwtrain1000.npy (training examples) and MNISTcwtest100.npy (test examples). Cast the resulting arrays to 'uint8 (unsigned integers of 8-bits)' format.


```python
train = np.load("MNISTcwtrain1000.npy")
test = np.load("MNISTcwtest100.npy")

train = train.astype("uint8")
test = test.astype("uint8")
```

2) Print the dimensions of training data and test data.


```python
print(np.shape(train))
print(np.shape(test))
```

    (784, 10000)
    (784, 1000)


3) Compute the mean vector of each digit of training examples (mean of the first 1000 columns of training examples corresponds to digit 0, mean of the next 1000 columns corresponds to digit 1, etc.)


```python
means = np.mean(np.reshape(train, (784, 10, 1000)), axis = 2)
print(np.shape(means))
```

    (784, 10)


4) Using the function below, convert the mean-vector of each digit (computed from part (3)) into a 28 x 28, 2D-array and plot the corresponding two dimensional images (using 'imshow').  


```python
# Function that converts a 1D vectorized image into a (nr x nc) 2D array
means_t = np.transpose(means)
means_img = np.zeros((10, 28, 28))

def unpackcw(x,nr,nc):
    A = x.reshape(nc,nr)
    return A.T

for i in range(len(means_t)):
    means_img[i] = unpackcw(means_t[i], 28, 28)
```


```python
plt.figure(figsize=(20, 10))
columns = 5
for i, image in enumerate(means_img):
    plt.subplot(3, 5, i + 1)
    plt.imshow(image)
```

5) Using vector-means from part (3), implement the nearest class mean classifier. What are the training and test accuracies?


```python
train_t = np.transpose(train)
test_t = np.transpose(test)

def predict(data, centroids):
    dist = np.sum(np.square(centroids - data), 1)
    return np.argmin(dist)

def accuracy(data, centroids):
    correct = 0
    examples_per_class = len(data) / 10
    for i in range(len(data)):
        if predict(data[i], centroids) == i // examples_per_class:
            correct += 1
    
    return correct / len(data)

print(accuracy(train_t, means_t))
print(accuracy(test_t, means_t))
```

    0.8038
    0.767



```python

```

200304d19a83231e08a9d885c0f0f244557b2228
ipynb
Jupyter Notebook
hw1/Daniel_Suo_HW1.ipynb
danielsuo/cos535
c388cd40b9c45ca784950391c610fe6425fc30dd
MIT
hw1/Daniel_Suo_HW1.ipynb
danielsuo/cos535
c388cd40b9c45ca784950391c610fe6425fc30dd
MIT
hw1/Daniel_Suo_HW1.ipynb
danielsuo/cos535
c388cd40b9c45ca784950391c610fe6425fc30dd
MIT
Qwen/Qwen-72B
1. YES
2. YES