機械学習学習に数学力は必須というのが、機械学習学習の最大のネックだろう。プログラミングにもある程度の数学力(高校レベル)は必須だが、機械学習学習の数学力は大学・大学院レベルのかなり高度なものが要求される。コードをコピペして遊ぶ程度なら数学力もプログラミング能力も必要ないが、真剣に学習しようと思うとかなり敷居が高い。
スタンフォード大学のCS231n: Convolutional Neural Networks for Visual Recognitionを使い学習しようと思うと、assignment 1でいきなり躓く。CS229:Machine Learningもいい教材ではあるとは思うが、宿題に使われる言語がPythonではなくMatlab(Octave)なので、パイソンプログラミングの学習ならCS231nということになる。
問題の宿題1は、自力で解くのは数学力がないと困難というか無理で、結局は、ネットで模範解答を検索するしかなかった。解答を見ても何でそうなるのかすら分からない。
コード:huyouare/CS231n
import numpy as np
class KNearestNeighbor:
""" a kNN classifier with L2 distance """
def __init__(self):
pass
def train(self, X, y):
"""
Train the classifier. For k-nearest neighbors this is just
memorizing the training data.
Input:
X - A num_train x dimension array where each row is a training point.
y - A vector of length num_train, where y[i] is the label for X[i, :]
"""
self.X_train = X
self.y_train = y
def predict(self, X, k=1, num_loops=0):
"""
Predict labels for test data using this classifier.
Input:
X - A num_test x dimension array where each row is a test point.
k - The number of nearest neighbors that vote for predicted label
num_loops - Determines which method to use to compute distances
between training points and test points.
Output:
y - A vector of length num_test, where y[i] is the predicted label for the
test point X[i, :].
"""
if num_loops == 0:
dists = self.compute_distances_no_loops(X)
elif num_loops == 1:
dists = self.compute_distances_one_loop(X)
elif num_loops == 2:
dists = self.compute_distances_two_loops(X)
else:
raise ValueError('Invalid value %d for num_loops' % num_loops)
return self.predict_labels(dists, k=k)
def compute_distances_two_loops(self, X):
"""
Compute the distance between each test point in X and each training point
in self.X_train using a nested loop over both the training data and the
test data.
Input:
X - An num_test x dimension array where each row is a test point.
Output:
dists - A num_test x num_train array where dists[i, j] is the distance
between the ith test point and the jth training point.
"""
num_test = X.shape[0]
num_train = self.X_train.shape[0]
dists = np.zeros((num_test, num_train))
print X.shape, self.X_train.shape
for i in xrange(num_test):
for j in xrange(num_train):
#####################################################################
# TODO: #
# Compute the l2 distance between the ith test point and the jth #
# training point, and store the result in dists[i, j] #
#####################################################################
dists[i, j] = np.sqrt(np.sum((X[i, :] - self.X_train[j, :]) ** 2))
#####################################################################
# END OF YOUR CODE #
#####################################################################
return dists
def compute_distances_one_loop(self, X):
"""
Compute the distance between each test point in X and each training point
in self.X_train using a single loop over the test data.
Input / Output: Same as compute_distances_two_loops
"""
num_test = X.shape[0]
num_train = self.X_train.shape[0]
dists = np.zeros((num_test, num_train))
for i in xrange(num_test):
#######################################################################
# TODO: #
# Compute the l2 distance between the ith test point and all training #
# points, and store the result in dists[i, :]. #
#######################################################################
dists[i, :] = np.sqrt(np.sum(np.square(self.X_train - X[i, :]), axis=1)) # broadcasting
#####################################################################
# END OF YOUR CODE #
#####################################################################
return dists
def compute_distances_no_loops(self, X):
"""
Compute the distance between each test point in X and each training point
in self.X_train using no explicit loops.
Input / Output: Same as compute_distances_two_loops
"""
num_test = X.shape[0]
num_train = self.X_train.shape[0]
dists = np.zeros((num_test, num_train))
#########################################################################
# TODO: #
# Compute the l2 distance between all test points and all training #
# points without using any explicit loops, and store the result in #
# dists. #
# HINT: Try to formulate the l2 distance using matrix multiplication #
# and two broadcast sums. #
#########################################################################
# Output: sqrt((x-y)^2)
# (x-y)^2 = x^2 + y^2 - 2xy
test_sum = np.sum(np.square(X), axis=1) # num_test x 1
train_sum = np.sum(np.square(self.X_train), axis=1) # num_train x 1
inner_product = np.dot(X, self.X_train.T) # num_test x num_train
dists = np.sqrt(-2 * inner_product + test_sum.reshape(-1, 1) + train_sum) # broadcast
#####################################################################
# END OF YOUR CODE #
#####################################################################
return dists
def predict_labels(self, dists, k=1):
"""
Given a matrix of distances between test points and training points,
predict a label for each test point.
Input:
dists - A num_test x num_train array where dists[i, j] gives the distance
between the ith test point and the jth training point.
Output:
y - A vector of length num_test where y[i] is the predicted label for the
ith test point.
"""
num_test = dists.shape[0]
y_pred = np.zeros(num_test)
for i in xrange(num_test):
# A list of length k storing the labels of the k nearest neighbors to
# the ith test point.
closest_y = []
#########################################################################
# TODO: #
# Use the distance matrix to find the k nearest neighbors of the ith #
# training point, and use self.y_train to find the labels of these #
# neighbors. Store these labels in closest_y. #
# Hint: Look up the function numpy.argsort. #
#########################################################################
y_indicies = np.argsort(dists[i, :], axis = 0)
closest_y = self.y_train[y_indicies[:k]]
#########################################################################
# TODO: #
# Now that you have found the labels of the k nearest neighbors, you #
# need to find the most common label in the list closest_y of labels. #
# Store this label in y_pred[i]. Break ties by choosing the smaller #
# label. #
#########################################################################
y_pred[i] = np.argmax(np.bincount(closest_y))
#########################################################################
# END OF YOUR CODE #
#########################################################################
return y_pred
class KNearestNeighbor:
""" a kNN classifier with L2 distance """
def __init__(self):
pass
def train(self, X, y):
"""
Train the classifier. For k-nearest neighbors this is just
memorizing the training data.
Input:
X - A num_train x dimension array where each row is a training point.
y - A vector of length num_train, where y[i] is the label for X[i, :]
"""
self.X_train = X
self.y_train = y
def predict(self, X, k=1, num_loops=0):
"""
Predict labels for test data using this classifier.
Input:
X - A num_test x dimension array where each row is a test point.
k - The number of nearest neighbors that vote for predicted label
num_loops - Determines which method to use to compute distances
between training points and test points.
Output:
y - A vector of length num_test, where y[i] is the predicted label for the
test point X[i, :].
"""
if num_loops == 0:
dists = self.compute_distances_no_loops(X)
elif num_loops == 1:
dists = self.compute_distances_one_loop(X)
elif num_loops == 2:
dists = self.compute_distances_two_loops(X)
else:
raise ValueError('Invalid value %d for num_loops' % num_loops)
return self.predict_labels(dists, k=k)
def compute_distances_two_loops(self, X):
"""
Compute the distance between each test point in X and each training point
in self.X_train using a nested loop over both the training data and the
test data.
Input:
X - An num_test x dimension array where each row is a test point.
Output:
dists - A num_test x num_train array where dists[i, j] is the distance
between the ith test point and the jth training point.
"""
num_test = X.shape[0]
num_train = self.X_train.shape[0]
dists = np.zeros((num_test, num_train))
print X.shape, self.X_train.shape
for i in xrange(num_test):
for j in xrange(num_train):
#####################################################################
# TODO: #
# Compute the l2 distance between the ith test point and the jth #
# training point, and store the result in dists[i, j] #
#####################################################################
dists[i, j] = np.sqrt(np.sum((X[i, :] - self.X_train[j, :]) ** 2))
#####################################################################
# END OF YOUR CODE #
#####################################################################
return dists
def compute_distances_one_loop(self, X):
"""
Compute the distance between each test point in X and each training point
in self.X_train using a single loop over the test data.
Input / Output: Same as compute_distances_two_loops
"""
num_test = X.shape[0]
num_train = self.X_train.shape[0]
dists = np.zeros((num_test, num_train))
for i in xrange(num_test):
#######################################################################
# TODO: #
# Compute the l2 distance between the ith test point and all training #
# points, and store the result in dists[i, :]. #
#######################################################################
dists[i, :] = np.sqrt(np.sum(np.square(self.X_train - X[i, :]), axis=1)) # broadcasting
#####################################################################
# END OF YOUR CODE #
#####################################################################
return dists
def compute_distances_no_loops(self, X):
"""
Compute the distance between each test point in X and each training point
in self.X_train using no explicit loops.
Input / Output: Same as compute_distances_two_loops
"""
num_test = X.shape[0]
num_train = self.X_train.shape[0]
dists = np.zeros((num_test, num_train))
#########################################################################
# TODO: #
# Compute the l2 distance between all test points and all training #
# points without using any explicit loops, and store the result in #
# dists. #
# HINT: Try to formulate the l2 distance using matrix multiplication #
# and two broadcast sums. #
#########################################################################
# Output: sqrt((x-y)^2)
# (x-y)^2 = x^2 + y^2 - 2xy
test_sum = np.sum(np.square(X), axis=1) # num_test x 1
train_sum = np.sum(np.square(self.X_train), axis=1) # num_train x 1
inner_product = np.dot(X, self.X_train.T) # num_test x num_train
dists = np.sqrt(-2 * inner_product + test_sum.reshape(-1, 1) + train_sum) # broadcast
#####################################################################
# END OF YOUR CODE #
#####################################################################
return dists
def predict_labels(self, dists, k=1):
"""
Given a matrix of distances between test points and training points,
predict a label for each test point.
Input:
dists - A num_test x num_train array where dists[i, j] gives the distance
between the ith test point and the jth training point.
Output:
y - A vector of length num_test where y[i] is the predicted label for the
ith test point.
"""
num_test = dists.shape[0]
y_pred = np.zeros(num_test)
for i in xrange(num_test):
# A list of length k storing the labels of the k nearest neighbors to
# the ith test point.
closest_y = []
#########################################################################
# TODO: #
# Use the distance matrix to find the k nearest neighbors of the ith #
# training point, and use self.y_train to find the labels of these #
# neighbors. Store these labels in closest_y. #
# Hint: Look up the function numpy.argsort. #
#########################################################################
y_indicies = np.argsort(dists[i, :], axis = 0)
closest_y = self.y_train[y_indicies[:k]]
#########################################################################
# TODO: #
# Now that you have found the labels of the k nearest neighbors, you #
# need to find the most common label in the list closest_y of labels. #
# Store this label in y_pred[i]. Break ties by choosing the smaller #
# label. #
#########################################################################
y_pred[i] = np.argmax(np.bincount(closest_y))
#########################################################################
# END OF YOUR CODE #
#########################################################################
return y_pred
linear algebraの良質なオープンコースもMITが提供してくれているので、並行して学習すればかなりの学習効果が得られそうである。同時に、英語のリスニング力と読解力も高められるので一石二鳥と言えよう。いや、英語、Python、機械学習、数学の一石四鳥と言える。
参考サイトhttps://github.com/スポンサーリンク
スポンサーリンク