Я кодировал многослойный персептрон с 2 скрытыми слоями.
У меня есть версия с одним слоем, которая, кажется, работает должным образом, но когда я добавляю дополнительный слой, потеря, кажется, не падает ниже 1.
То, чего я пытаюсь добиться, - это метод двоичной классификации для набора данных MNIST. Точнее, я пытаюсь использовать этот MLP, чтобы различать 3 и 7. Я использую функцию активации сигмовидной кишки и обратное распространение для регулировки весов.
Я подозреваю, что может быть что-то не так с тем, как я закодировал обратное распространение.
num_examples = len(X) # training set size
nn_input_dim = 784 # input layer dimensionality
nn_output_dim = 2 # output layer dimensionality
# Gradient descent parameters
epsilon = 0.005 # learning rate for gradient descent
def calculate_loss(model):
W1, b1, W2, b2, W3, b3 = model['W1'], model['b1'], model['W2'], model['b2'], model['W3'], model['b3']
# Forward propagation to calculate predictions
z1 = X.dot(W1) + b1
a1 = sigmoid(z1)
z2 = a1.dot(W2) + b2
a2 = sigmoid(z2)
z3 = a2.dot(W3) + b3
exp_scores = np.exp(z3)
probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
# Calculate the loss
corect_logprobs = -np.log(probs[range(num_examples), y])
data_loss = np.sum(corect_logprobs)
return 1./num_examples * data_loss
def predict(model, X):
W1, b1, W2, b2, W3, b3 = model['W1'], model['b1'], model['W2'], model['b2'], model['W3'], model['b3']
#Forward propagation
z1 = X.dot(W1) + b1
a1 = sigmoid(z1)
z2 = a1.dot(W2) + b2
a2 = sigmoid(z2)
z3 = a2.dot(W3) + b3
exp_scores = np.exp(z3)
probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
return np.argmax(probs, axis=1)
def build_model(nn_hdim1, nn_hdim2, num_passes=20000, print_loss=False):
# Initialize the params that need to be learned to random values
np.random.seed(0)
W1 = np.random.randn(nn_input_dim, nn_hdim1) / np.sqrt(nn_input_dim)
b1 = np.zeros((1, nn_hdim1))
W2 = np.random.randn(nn_hdim1, nn_hdim2) / np.sqrt(nn_hdim1)
b2 = np.zeros((1, nn_hdim2))
W3 = np.random.randn(nn_hdim2, nn_output_dim) / np.sqrt(nn_hdim2)
b3 = np.zeros((1, nn_output_dim))
# This is what we return at the end
model = {}
loss = []
for i in range(0, num_passes):
# Forward propagation
z1 = X.dot(W1) + b1
a1 = sigmoid(z1)
z2 = a1.dot(W2) + b2
a2 = sigmoid(z2)
z3 = a2.dot(W3) + b3
exp_scores = np.exp(z3)
probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
# Back propagation
delta4 = probs
delta4[range(num_examples), y] -= 1
dW3 = (a2.T).dot(delta4)
db3 = np.sum(delta4, axis=0, keepdims=True)
delta3 = delta4.dot(W3.T) * (1 - sigmoid(a2))
dW2 = (a1.T).dot(delta3)
db2 = np.sum(delta3, axis=0, keepdims=True)
delta2 = delta3.dot(W2.T) * (1 - sigmoid(a1))
dW1 = np.dot(X.T, delta2)
db1 = np.sum(delta2, axis=0)
# Gradient descent parameter update
W1 += -epsilon * dW1
b1 += -epsilon * db1
W2 += -epsilon * dW2
b2 += -epsilon * db2
W3 += -epsilon * dW3
b3 += -epsilon * db3
# Assign new parameters to the model
model = { 'W1': W1, 'b1': b1,
'W2': W2, 'b2': b2,
'W3': W3, 'b3': b3}
if print_loss and i % 500 == 0:
loss.append(calculate_loss(model))
print("Loss after iter. %i: %f" %(i, calculate_loss(model)))
return model, loss
model, loss = build_model(3, 3, num_passes=10000, print_loss=True)
Это вывод, который я получаю:
Loss after iter. 500: 2.115385
Loss after iter. 1000: 3.981505
Loss after iter. 1500: 4.851937
Loss after iter. 2000: 2.286764
Loss after iter. 2500: 0.650758
Loss after iter. 3000: 0.454743
Loss after iter. 3500: 2.034308
Loss after iter. 4000: 2.221124
Loss after iter. 4500: 0.486550
Loss after iter. 5000: 1.803266
Loss after iter. 5500: 2.318486
Loss after iter. 6000: 1.594879
Loss after iter. 6500: 3.081962
Loss after iter. 7000: 2.340241
Loss after iter. 7500: 3.693953
Loss after iter. 8000: 1.618758
Loss after iter. 8500: 2.328891
Loss after iter. 9000: 2.265693
Loss after iter. 9500: 3.503290
Я ожидаю, что после итерации 4500, когда потеря равна .4, модель продолжит улучшаться, но этого не произойдет.
Сначала кажется, что шаг слишком велик, и регрессия выходит за пределы "долины" конвергенции, но я думаю, что 0,005 довольно мало по сравнению с тем, что обычно используется для этого.