Skip to content

Commit 3b288f6

Browse files
committed
Initial import of the project
0 parents  commit 3b288f6

File tree

134 files changed

+54132
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

134 files changed

+54132
-0
lines changed

README.md

+175
Large diffs are not rendered by default.

cs231n/assignment1/README.md

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<div>
2+
<h2 align="center"><a href="https://cs231n.github.io">CS231n: Convolutional Neural Networks for Visual Recognition</a></h2>
3+
<h2 align="center"><a href="https://cs231n.github.io/assignments2020/assignment1/">Assignment 1 (2020)</a></h3>
4+
</div>
5+
6+
# Goals
7+
8+
In this assignment you will practice putting together a simple image classification pipeline based on the k-Nearest Neighbor or the SVM/Softmax classifier. The goals of this assignment are as follows:
9+
10+
- Understand the basic **Image Classification pipeline** and the data-driven approach (train/predict stages).
11+
- Understand the train/val/test **splits** and the use of validation data for **hyperparameter tuning**.
12+
- Develop proficiency in writing efficient **vectorized** code with numpy.
13+
- Implement and apply a k-Nearest Neighbor (**kNN**) classifier.
14+
- Implement and apply a Multiclass Support Vector Machine (**SVM**) classifier.
15+
- Implement and apply a **Softmax** classifier.
16+
- Implement and apply a **Two layer neural network** classifier.
17+
- Understand the differences and tradeoffs between these classifiers.
18+
- Get a basic understanding of performance improvements from using **higher-level representations** as opposed to raw pixels, e.g. color histograms, Histogram of Gradient (HOG) features, etc.
19+
20+
# Questions
21+
22+
## Q1: k-Nearest Neighbor classifier
23+
24+
The notebook [``knn.ipynb``](https://github.com/seloufian/Deep-Learning-Computer-Vision/blob/master/cs231n/assignment1/knn.ipynb) will walk you through implementing the kNN classifier.
25+
26+
## Q2: Training a Support Vector Machine
27+
28+
The notebook [``svm.ipynb``](https://github.com/seloufian/Deep-Learning-Computer-Vision/blob/master/cs231n/assignment1/svm.ipynb) will walk you through implementing the SVM classifier.
29+
30+
## Q3: Implement a Softmax classifier
31+
32+
The notebook [``softmax.ipynb``](https://github.com/seloufian/Deep-Learning-Computer-Vision/blob/master/cs231n/assignment1/softmax.ipynb) will walk you through implementing the Softmax classifier.
33+
34+
## Q4: Two-Layer Neural Network
35+
36+
The notebook [``two_layer_net.ipynb``](https://github.com/seloufian/Deep-Learning-Computer-Vision/blob/master/cs231n/assignment1/two_layer_net.ipynb) will walk you through the implementation of a two-layer neural network classifier.
37+
38+
## Q5: Higher Level Representations: Image Features
39+
40+
The notebook [``features.ipynb``](https://github.com/seloufian/Deep-Learning-Computer-Vision/blob/master/cs231n/assignment1/features.ipynb) will examine the improvements gained by using higher-level representations as opposed to using raw pixel values.

cs231n/assignment1/cs231n/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from cs231n.classifiers.k_nearest_neighbor import *
2+
from cs231n.classifiers.linear_classifier import *
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
from builtins import range
2+
from builtins import object
3+
import numpy as np
4+
from past.builtins import xrange
5+
6+
7+
class KNearestNeighbor(object):
8+
""" a kNN classifier with L2 distance """
9+
10+
def __init__(self):
11+
pass
12+
13+
def train(self, X, y):
14+
"""
15+
Train the classifier. For k-nearest neighbors this is just
16+
memorizing the training data.
17+
18+
Inputs:
19+
- X: A numpy array of shape (num_train, D) containing the training data
20+
consisting of num_train samples each of dimension D.
21+
- y: A numpy array of shape (N,) containing the training labels, where
22+
y[i] is the label for X[i].
23+
"""
24+
self.X_train = X
25+
self.y_train = y
26+
27+
def predict(self, X, k=1, num_loops=0):
28+
"""
29+
Predict labels for test data using this classifier.
30+
31+
Inputs:
32+
- X: A numpy array of shape (num_test, D) containing test data consisting
33+
of num_test samples each of dimension D.
34+
- k: The number of nearest neighbors that vote for the predicted labels.
35+
- num_loops: Determines which implementation to use to compute distances
36+
between training points and testing points.
37+
38+
Returns:
39+
- y: A numpy array of shape (num_test,) containing predicted labels for the
40+
test data, where y[i] is the predicted label for the test point X[i].
41+
"""
42+
if num_loops == 0:
43+
dists = self.compute_distances_no_loops(X)
44+
elif num_loops == 1:
45+
dists = self.compute_distances_one_loop(X)
46+
elif num_loops == 2:
47+
dists = self.compute_distances_two_loops(X)
48+
else:
49+
raise ValueError('Invalid value %d for num_loops' % num_loops)
50+
51+
return self.predict_labels(dists, k=k)
52+
53+
def compute_distances_two_loops(self, X):
54+
"""
55+
Compute the distance between each test point in X and each training point
56+
in self.X_train using a nested loop over both the training data and the
57+
test data.
58+
59+
Inputs:
60+
- X: A numpy array of shape (num_test, D) containing test data.
61+
62+
Returns:
63+
- dists: A numpy array of shape (num_test, num_train) where dists[i, j]
64+
is the Euclidean distance between the ith test point and the jth training
65+
point.
66+
"""
67+
num_test = X.shape[0]
68+
num_train = self.X_train.shape[0]
69+
dists = np.zeros((num_test, num_train))
70+
for i in range(num_test):
71+
for j in range(num_train):
72+
#####################################################################
73+
# TODO: #
74+
# Compute the l2 distance between the ith test point and the jth #
75+
# training point, and store the result in dists[i, j]. You should #
76+
# not use a loop over dimension, nor use np.linalg.norm(). #
77+
#####################################################################
78+
# *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
79+
80+
distance_ij = np.square(X[i] - self.X_train[j])
81+
distance_ij = np.sqrt(np.sum(distance_ij))
82+
83+
dists[i, j] = distance_ij
84+
85+
# *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
86+
return dists
87+
88+
def compute_distances_one_loop(self, X):
89+
"""
90+
Compute the distance between each test point in X and each training point
91+
in self.X_train using a single loop over the test data.
92+
93+
Input / Output: Same as compute_distances_two_loops
94+
"""
95+
num_test = X.shape[0]
96+
num_train = self.X_train.shape[0]
97+
dists = np.zeros((num_test, num_train))
98+
for i in range(num_test):
99+
#######################################################################
100+
# TODO: #
101+
# Compute the l2 distance between the ith test point and all training #
102+
# points, and store the result in dists[i, :]. #
103+
# Do not use np.linalg.norm(). #
104+
#######################################################################
105+
# *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
106+
107+
dists[i, :] = np.sqrt(np.sum(np.square(X[i] - self.X_train), axis=1))
108+
109+
# *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
110+
return dists
111+
112+
def compute_distances_no_loops(self, X):
113+
"""
114+
Compute the distance between each test point in X and each training point
115+
in self.X_train using no explicit loops.
116+
117+
Input / Output: Same as compute_distances_two_loops
118+
"""
119+
num_test = X.shape[0]
120+
num_train = self.X_train.shape[0]
121+
dists = np.zeros((num_test, num_train))
122+
#########################################################################
123+
# TODO: #
124+
# Compute the l2 distance between all test points and all training #
125+
# points without using any explicit loops, and store the result in #
126+
# dists. #
127+
# #
128+
# You should implement this function using only basic array operations; #
129+
# in particular you should not use functions from scipy, #
130+
# nor use np.linalg.norm(). #
131+
# #
132+
# HINT: Try to formulate the l2 distance using matrix multiplication #
133+
# and two broadcast sums. #
134+
#########################################################################
135+
# *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
136+
137+
train_matrix_tr = self.X_train.T
138+
139+
sum_1 = np.sum(np.square(X), axis=1)
140+
sum_1 = sum_1.reshape((-1, sum_1.size)).T
141+
142+
sum_2 = np.sum(np.square(train_matrix_tr), axis=0)
143+
144+
dists = -2 * X.dot(train_matrix_tr) + sum_1 + sum_2
145+
dists = np.sqrt(dists)
146+
147+
# *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
148+
return dists
149+
150+
def predict_labels(self, dists, k=1):
151+
"""
152+
Given a matrix of distances between test points and training points,
153+
predict a label for each test point.
154+
155+
Inputs:
156+
- dists: A numpy array of shape (num_test, num_train) where dists[i, j]
157+
gives the distance betwen the ith test point and the jth training point.
158+
159+
Returns:
160+
- y: A numpy array of shape (num_test,) containing predicted labels for the
161+
test data, where y[i] is the predicted label for the test point X[i].
162+
"""
163+
num_test = dists.shape[0]
164+
y_pred = np.zeros(num_test)
165+
for i in range(num_test):
166+
# A list of length k storing the labels of the k nearest neighbors to
167+
# the ith test point.
168+
closest_y = []
169+
#########################################################################
170+
# TODO: #
171+
# Use the distance matrix to find the k nearest neighbors of the ith #
172+
# testing point, and use self.y_train to find the labels of these #
173+
# neighbors. Store these labels in closest_y. #
174+
# Hint: Look up the function numpy.argsort. #
175+
#########################################################################
176+
# *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
177+
178+
closet_indexes = np.argsort(dists[i])
179+
closet_indexes = closet_indexes[:k]
180+
181+
closest_y = self.y_train.take(closet_indexes)
182+
183+
# *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
184+
#########################################################################
185+
# TODO: #
186+
# Now that you have found the labels of the k nearest neighbors, you #
187+
# need to find the most common label in the list closest_y of labels. #
188+
# Store this label in y_pred[i]. Break ties by choosing the smaller #
189+
# label. #
190+
#########################################################################
191+
# *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
192+
193+
y_pred[i] = np.bincount(closest_y).argmax()
194+
195+
# *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
196+
197+
return y_pred
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
from __future__ import print_function
2+
3+
from builtins import range
4+
from builtins import object
5+
import numpy as np
6+
from cs231n.classifiers.linear_svm import *
7+
from cs231n.classifiers.softmax import *
8+
from past.builtins import xrange
9+
10+
11+
class LinearClassifier(object):
12+
13+
def __init__(self):
14+
self.W = None
15+
16+
def train(self, X, y, learning_rate=1e-3, reg=1e-5, num_iters=100,
17+
batch_size=200, verbose=False):
18+
"""
19+
Train this linear classifier using stochastic gradient descent.
20+
21+
Inputs:
22+
- X: A numpy array of shape (N, D) containing training data; there are N
23+
training samples each of dimension D.
24+
- y: A numpy array of shape (N,) containing training labels; y[i] = c
25+
means that X[i] has label 0 <= c < C for C classes.
26+
- learning_rate: (float) learning rate for optimization.
27+
- reg: (float) regularization strength.
28+
- num_iters: (integer) number of steps to take when optimizing
29+
- batch_size: (integer) number of training examples to use at each step.
30+
- verbose: (boolean) If true, print progress during optimization.
31+
32+
Outputs:
33+
A list containing the value of the loss function at each training iteration.
34+
"""
35+
num_train, dim = X.shape
36+
num_classes = np.max(y) + 1 # assume y takes values 0...K-1 where K is number of classes
37+
if self.W is None:
38+
# lazily initialize W
39+
self.W = 0.001 * np.random.randn(dim, num_classes)
40+
41+
# Run stochastic gradient descent to optimize W
42+
loss_history = []
43+
for it in range(num_iters):
44+
X_batch = None
45+
y_batch = None
46+
47+
#########################################################################
48+
# TODO: #
49+
# Sample batch_size elements from the training data and their #
50+
# corresponding labels to use in this round of gradient descent. #
51+
# Store the data in X_batch and their corresponding labels in #
52+
# y_batch; after sampling X_batch should have shape (batch_size, dim) #
53+
# and y_batch should have shape (batch_size,) #
54+
# #
55+
# Hint: Use np.random.choice to generate indices. Sampling with #
56+
# replacement is faster than sampling without replacement. #
57+
#########################################################################
58+
# *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
59+
60+
batch_indexes = np.random.choice(num_train, batch_size)
61+
X_batch = X[batch_indexes]
62+
y_batch = y[batch_indexes]
63+
64+
# *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
65+
66+
# evaluate loss and gradient
67+
loss, grad = self.loss(X_batch, y_batch, reg)
68+
loss_history.append(loss)
69+
70+
# perform parameter update
71+
#########################################################################
72+
# TODO: #
73+
# Update the weights using the gradient and the learning rate. #
74+
#########################################################################
75+
# *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
76+
77+
self.W += - learning_rate * grad
78+
79+
# *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
80+
81+
if verbose and it % 100 == 0:
82+
print('iteration %d / %d: loss %f' % (it, num_iters, loss))
83+
84+
return loss_history
85+
86+
def predict(self, X):
87+
"""
88+
Use the trained weights of this linear classifier to predict labels for
89+
data points.
90+
91+
Inputs:
92+
- X: A numpy array of shape (N, D) containing training data; there are N
93+
training samples each of dimension D.
94+
95+
Returns:
96+
- y_pred: Predicted labels for the data in X. y_pred is a 1-dimensional
97+
array of length N, and each element is an integer giving the predicted
98+
class.
99+
"""
100+
y_pred = np.zeros(X.shape[0])
101+
###########################################################################
102+
# TODO: #
103+
# Implement this method. Store the predicted labels in y_pred. #
104+
###########################################################################
105+
# *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
106+
107+
predict_matrix = X.dot(self.W)
108+
y_pred = predict_matrix.argmax(axis=1)
109+
110+
# *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
111+
return y_pred
112+
113+
def loss(self, X_batch, y_batch, reg):
114+
"""
115+
Compute the loss function and its derivative.
116+
Subclasses will override this.
117+
118+
Inputs:
119+
- X_batch: A numpy array of shape (N, D) containing a minibatch of N
120+
data points; each point has dimension D.
121+
- y_batch: A numpy array of shape (N,) containing labels for the minibatch.
122+
- reg: (float) regularization strength.
123+
124+
Returns: A tuple containing:
125+
- loss as a single float
126+
- gradient with respect to self.W; an array of the same shape as W
127+
"""
128+
pass
129+
130+
131+
class LinearSVM(LinearClassifier):
132+
""" A subclass that uses the Multiclass SVM loss function """
133+
134+
def loss(self, X_batch, y_batch, reg):
135+
return svm_loss_vectorized(self.W, X_batch, y_batch, reg)
136+
137+
138+
class Softmax(LinearClassifier):
139+
""" A subclass that uses the Softmax + Cross-entropy loss function """
140+
141+
def loss(self, X_batch, y_batch, reg):
142+
return softmax_loss_vectorized(self.W, X_batch, y_batch, reg)

0 commit comments

Comments
 (0)