In [ ]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = (10.0, 8.0) # set default size of plots
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'
def rel_error(x, y):
""" returns relative error """
return np.max(np.abs(x - y) / (np.maximum(1e-8, np.abs(x) + np.abs(y))))
In [ ]:
class TwoLayerNet(object):
def __init__(self, input_size, hidden_size, output_size, std=1e-4):
"""
W1: Первый слой с размерами (D, H)
b1: Вектор байесов, размер (H,)
W2: Второй слой с размерами (H, C)
b2: Вектор байесов, размер (C,)
Входные парамерты:
- input_size: Размерность входных данных
- hidden_size: Размер скрытого слоя
- output_size: Количество классов
"""
self.params = {}
self.params['W1'] = std * np.random.randn(input_size, hidden_size)
self.params['b1'] = np.zeros(hidden_size)
self.params['W2'] = std * np.random.randn(hidden_size, output_size)
self.params['b2'] = np.zeros(output_size)
def loss(self, X, y=None, reg=0.0):
"""
Вычисление функции потерь
Входные парамерты:
- X: Таблица данных (N, D). X[i] - один пример
- y: Вектор лейблов. Если отсутсвует, то возвращается предсказание лейблов
- reg: Коэффициент регуляризации
Возвращает:
Если y == None, то возвращаются скор для классов
Если y != None, то возвращаются:
- Лосс для данного семпла данных
- grads: Словарь градиентов, ключи соответствуют ключам словаря self.params.
"""
W1, b1 = self.params['W1'], self.params['b1']
W2, b2 = self.params['W2'], self.params['b2']
N, D = X.shape
scores = None
#############################################################################
# TODO: Расчет forward pass или прямой проход, для данных находятся скоры, #
# на выходе размер (N, C) #
#############################################################################
pass
#############################################################################
# END OF YOUR CODE #
#############################################################################
# Если y == None, то завершаем вызов
if y is None:
return scores
loss = None
#############################################################################
# TODO: Расчет Softmax loss для полученных скоров обьектов, на выходе скаляр #
#############################################################################
pass
#############################################################################
# END OF YOUR CODE #
#############################################################################
grads = {}
#############################################################################
# TODO: Расчет обратнохо прохода или backward pass, находятся градиенты для всех #
# параметров, результаты сохраняются в grads, например grads['W1'] #
#############################################################################
pass
#############################################################################
# END OF YOUR CODE #
#############################################################################
return loss, grads
def train(self, X, y, X_val, y_val,
learning_rate=1e-3, learning_rate_decay=0.95,
reg=5e-6, num_iters=100,
batch_size=200, verbose=False):
"""
Обучение нейронной сети с помощью SGD
Входные парамерты:
- X: Матрица данных (N, D)
- y: Вектор лейблов (N, )
- X_val: Данные для валидации (N_val, D)
- y_val: Вектор лейблов валидации (N_val, )
- reg: Коэффициент регуляризации
- num_iters: Количнство итераций
- batch_size: Размер семпла данных, на 1 шаг алгоритма
- verbose: Вывод прогресса
"""
num_train = X.shape[0]
iterations_per_epoch = max(num_train / batch_size, 1)
loss_history = []
train_acc_history = []
val_acc_history = []
for it in range(num_iters):
X_batch = None
y_batch = None
#########################################################################
# TODO: Семпл данных их X-> X_batch, y_batch #
#########################################################################
pass
#########################################################################
# END OF YOUR CODE #
#########################################################################
loss, grads = self.loss(X_batch, y=y_batch, reg=reg)
loss_history.append(loss)
#########################################################################
# TODO: Используя градиенты из grads обновите параметры сети #
#########################################################################
pass
#########################################################################
# END OF YOUR CODE #
#########################################################################
if verbose and it % 100 == 0:
print('iteration %d / %d: loss %f' % (it, num_iters, loss))
if it % iterations_per_epoch == 0:
train_acc = (self.predict(X_batch) == y_batch).mean()
val_acc = (self.predict(X_val) == y_val).mean()
train_acc_history.append(train_acc)
val_acc_history.append(val_acc)
# Decay learning rate
learning_rate *= learning_rate_decay
return {
'loss_history': loss_history,
'train_acc_history': train_acc_history,
'val_acc_history': val_acc_history,
}
def predict(self, X):
"""
Входные параметры:
- X: Матрица данных (N, D)
Возвращает:
- y_pred: Вектор предсказаний классов для обьектов (N,)
"""
y_pred = None
###########################################################################
# TODO: Предсказание классов для обьектов из X #
###########################################################################
pass
###########################################################################
# END OF YOUR CODE #
###########################################################################
return y_pred
In [ ]:
# Инициализация простого примера. Данные и обьект модели
input_size = 4
hidden_size = 10
num_classes = 3
num_inputs = 5
def init_toy_model():
np.random.seed(0)
return TwoLayerNet(input_size, hidden_size, num_classes, std=1e-1)
def init_toy_data():
np.random.seed(1)
X = 10 * np.random.randn(num_inputs, input_size)
y = np.array([0, 1, 2, 2, 1])
return X, y
net = init_toy_model()
X, y = init_toy_data()
In [ ]:
scores = net.loss(X)
print('Your scores:')
print(scores)
print()
print('correct scores:')
correct_scores = np.asarray([
[-0.81233741, -1.27654624, -0.70335995],
[-0.17129677, -1.18803311, -0.47310444],
[-0.51590475, -1.01354314, -0.8504215 ],
[-0.15419291, -0.48629638, -0.52901952],
[-0.00618733, -0.12435261, -0.15226949]])
print(correct_scores)
print()
# The difference should be very small. We get < 1e-7
print('Difference between your scores and correct scores:')
print(np.sum(np.abs(scores - correct_scores)))
In [ ]:
loss, _ = net.loss(X, y, reg=0.05)
correct_loss = 1.30378789133
# Ошибка должна быть < 1e-12
print('Difference between your loss and correct loss:')
print(np.sum(np.abs(loss - correct_loss)))
In [ ]:
def eval_numerical_gradient(f, x, verbose=True, h=0.00001):
fx = f(x) # evaluate function value at original point
grad = np.zeros_like(x)
# iterate over all indexes in x
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
# evaluate function at x+h
ix = it.multi_index
oldval = x[ix]
x[ix] = oldval + h # increment by h
fxph = f(x) # evalute f(x + h)
x[ix] = oldval - h
fxmh = f(x) # evaluate f(x - h)
x[ix] = oldval # restore
# compute the partial derivative with centered formula
grad[ix] = (fxph - fxmh) / (2 * h) # the slope
if verbose:
print(ix, grad[ix])
it.iternext() # step to next dimension
return grad
In [ ]:
loss, grads = net.loss(X, y, reg=0.05)
# Ошибка должна быть меньше или около 1e-8
for param_name in grads:
f = lambda W: net.loss(X, y, reg=0.05)[0]
param_grad_num = eval_numerical_gradient(f, net.params[param_name], verbose=False)
print('%s max relative error: %e' % (param_name, rel_error(param_grad_num, grads[param_name])))
In [ ]:
net = init_toy_model()
stats = net.train(X, y, X, y,
learning_rate=1e-1, reg=5e-6,
num_iters=100, verbose=False)
print('Final training loss: ', stats['loss_history'][-1])
plt.plot(stats['loss_history'])
plt.xlabel('iteration')
plt.ylabel('training loss')
plt.title('Training Loss history')
plt.show()
In [ ]:
from keras.datasets import cifar10
In [ ]:
(X_train, y_train), (X_val, y_val) = cifar10.load_data()
X_test, y_test = X_val[:int(X_val.shape[0]*0.5)], y_val[:int(X_val.shape[0]*0.5)]
X_val, y_val = X_val[int(X_val.shape[0]*0.5):], y_val[int(X_val.shape[0]*0.5):]
print('Train data shape: ', X_train.shape)
print('Train labels shape: ', y_train.shape)
print('Validation data shape: ', X_val.shape)
print('Validation labels shape: ', y_val.shape)
print('Test data shape: ', X_test.shape)
print('Test labels shape: ', y_test.shape)
In [ ]:
input_size = 32 * 32 * 3
hidden_size = 50
num_classes = 10
net = TwoLayerNet(input_size, hidden_size, num_classes)
stats = net.train(X_train, y_train, X_val, y_val,
num_iters=1000, batch_size=200,
learning_rate=1e-4, learning_rate_decay=0.95,
reg=0.25, verbose=True)
val_acc = (net.predict(X_val) == y_val).mean()
print('Validation accuracy: ', val_acc)
In [ ]:
plt.subplot(2, 1, 1)
plt.plot(stats['loss_history'])
plt.title('Loss history')
plt.xlabel('Iteration')
plt.ylabel('Loss')
plt.subplot(2, 1, 2)
plt.plot(stats['train_acc_history'], label='train')
plt.plot(stats['val_acc_history'], label='val')
plt.title('Classification accuracy history')
plt.xlabel('Epoch')
plt.ylabel('Clasification accuracy')
plt.show()
In [ ]:
best_net = None
#################################################################################
# TODO: Напишите свою реализцию кросс валидации для настройки гиперпараметров сети #
#################################################################################
pass
#################################################################################
# END OF YOUR CODE #
#################################################################################
In [ ]:
test_acc = (best_net.predict(X_test) == y_test).mean()
print('Test accuracy: ', test_acc)