Deadline: January 20, 9pm.
Late Penalty: See Syllabus
TAs: Andrew Jung
Welcome to the first assignment of APS360! This assignment is a warm up to get you used to the programming environment used in the course, and also to help you review and renew your knowledge of Python and relevant Python libraries. The assignment must be done individually. Please recall that the University of Toronto plagarism rules apply.
By the end of this assignment, you should be able to:
numpy
.matplotlib
.Submit a PDF file containing all your code, outputs, and write-up from parts 1-4. Do not submit any other files produced by your code.
Completing this assignment using Jupyter Notebook is highly recommended
(though not necessarily for all subsequent assignments). If you are using
Jupyter Notebook, you can export a PDF file using the menu option
File -> Download As -> PDF via LaTeX (pdf)
Your first step is to set up your development environment. We'll be using the Anaconda distribution of Python 3.6. Following the instructions to install Python3.6, PyCharm, Jupyter Notebook:
https://www.cs.toronto.edu/~lczhang/360/files/install.pdf
To prepare for the rest of the assignment, the preparatory readings in section 2 of the installation instructions are very helpful.
The purpose of this section is to get you used to the basics of Python, including working with functions, numbers, lists, and strings.
Write a function sum_of_squares
that computes the sum of squares up to n
.
def sum_of_squares(n):
"""Return the sum (1 + 2^2 + 3^2 + ... + n^2)
Precondition: n > 0, type(n) == int
>>> sum_of_squares(3)
14
>>> sum_of_squares(1)
1
"""
Write a function word_lengths
that takes a sentence (string), computes the length of each word in that sentence, and returns the length of each word in a list. You can
assume that words are always separated by a space character " "
.
Hint: recall the str.split
function in Python.
If you arenot sure how this function works, try
typing help(str.split)
into a Python shell, or checkout https://docs.python.org/3.6/library/stdtypes.html#str.split
help(str.split)
def word_lengths(sentence):
"""Return a list containing the length of each word in
sentence.
>>> word_lengths("welcome to APS360!")
[7, 2, 7]
>>> word_lengths("machine learning is so cool")
[7, 8, 2, 2, 4]
"""
In this part of the assignment, you'll be manipulating arrays
usign NumPy. Normally, we use the shorter name np
to represent
the package numpy
.
import numpy as np
Load the file matrix.csv
into a variable called matrix
using the function np.loadtxt
. Make sure that matrix.csv
is in the same file folder as this notebook.
matrix = None
matrix
Load the file vector.npy
into a variable called vector
using the function np.load
. As before, make sure that vector.npy
is in the same file folder as this notebook.
vector = None
vector
Perform matrix multiplication output = matrix x vector
by using
for loops to iterate through the columns and rows.
Do not use any builtin NumPy functions.
Hint: be mindful of the dimension of output
output = None
output
Save the output
variable into a csv
file called output_forloop.csv
using the function numpy.savetxt
.
Perform matrix multiplication output2 = matrix x vector
by using
the function numpy.dot
.
We will never actually write code as in
part(c), not only because numpy.dot
is more concise and easier to read/write, but also performance-wise numpy.dot
is much faster (it is written in C and highly optimized).
In general, we will avoid for loops in our code.
output2 = None
output2
Save the output2
variable into a csv
file called output_dot.npy
using the function numpy.save
.
As a way to test for consistency, show that the two outputs match.
A callable object is any object that can be called like a function.
In Python, any object whose class has a __call__
method will be callable.
For example, we can define an AddBias
class that is initialized with a value val
. When the object of the Adder class is called with input
, it will return the sum of val
and input
:
class AddBias(object):
def __init__(self, val):
self.val = val
def __call__(self, input):
return self.val + input
add4 = AddBias(4)
add4(3)
# AddBias works with numpy arrays as well
add1 = AddBias(1)
add1(np.array([3,4,5]))
Create a callable object class ElementwiseMultiply
that is initialized with weight
, which is a numpy array (with 1-dimension).
When called on input
of the same shape as weight
, the object will output an elementwise product of input
and weight
. For example, the 1st element in the output will be a product of the first element of input
and first element of weight
. If the input
and weight
have different shape, do not return anything.
Create a callable object class LeakyRelu
that is initialized
with alpha
, which is a scalar value.
When called on input
, which may be a NumPy array,
the object will output:
To obtain full marks, do not use any for-loops to implement this class.
Create a callable object class Compose
that is initialized with layers
, which is a list of callable objects each taking in one argument when called. For example, layers
can be something like [add1, add4]
that we created above. Each add1
and add4
take in one argument. When Compose
object is called on a single argument, the object will output a composition of object calls in layers
, in the order given in layers
(e.g. add1
will be called first and then add4
will be called after using the result from add1
call)
Run the below code and include the output in your report.
weight_1 = np.array([1, 2, 3, 4])
weight_2 = np.array([-1, -2, -3, -4])
bias_1 = 3
bias_2 = -2
alpha = 0.1
elem_mult_1 = ElementwiseMultiply(weight_1)
add_bias_1 = AddBias(bias_1)
leaky_relu = LeakyRelu(alpha)
elem_mult_2 = ElementwiseMultiply(weight_2)
add_bias_2 = AddBias(bias_2)
layers = Compose([elem_mult_1,
add_bias_1,
leaky_relu,
elem_mult_2,
add_bias_2,
leaky_relu])
input = np.array([10, 5, -5, -10])
print("Input: ", input)
output = layers(input)
print("Output:", output)
A picture or image can be represented as a NumPy array of “pixels”, with dimensions H × W × C, where H is the height of the image, W is the width of the image, and C is the number of colour channels. Typically we will use an image with channels that give the the Red, Green, and Blue “level” of each pixel, which is referred to with the short form RGB.
You will write Python code to load an image, and perform several array manipulations to the image and visualize their effects. You’ll need the file dog_mochi.png
from the same place you downloaded this assignment. Save the output images in the same directory as the Jupyter Notebook.
import matplotlib.pyplot as plt
Load the image dog_mochi.png
into the variable img
using the pyplot.imread
function.
This is a photograph of a dog whose name is Mochi.
img = None
Use the function plt.imshow
to visualize img
.
This function will also show the coordinate system used to identify pixels. The origin is at the top left corner, and the first dimension indicates the Y (row) direction, and the second dimension indicates the X (column) dimension.
What is the pixel coordinate of Mochi's eye? Show the value of each of the 3 channels on a pixel cooresponding to Mochi's eye.
The value for each channel in the original image ranges from 0 (darkest) to 255 (lightest). However, when loading an image through Matplotlib, this range will be scaled to be from 0 (darkest) to 1 (brightest) instead, and will be a real number, rather than an integer.
Modify the image by adding a constant value of 0.25 to each pixel in the img
and
store the result in the variable img_add
. Note that, since the range for the pixels
needs to be between [0, 1], you will also need to clip img_add to be in the range [0, 1]
using numpy.clip
. Clipping sets any value that is outside of the desired range to the
closest endpoint. Display the image using plt.imshow
.
img_add = None
From the original image, create three images that separate out the three colour channels (red, green and blue).
Hint: First create an array initialized with zeros, then copy over the specific channel’s 2D content from img.
Crop the image to only show Mochis face. Your image should be square. Display the image.
Finally, save the image from part (f) using plt.imsave
as the filename dog_name.png
.