#python-3.x #neural-network
#python-3.x #нейронная сеть
Вопрос:
Я пытался создать базовую нейронную сеть с нуля на Python. Это то, что я придумал.
Функции активации и производные
def sigmoid(Z):
return 1 / (1 np.exp(-Z))
def relu(Z):
return np.maximum(0, Z)
# derivatives
def d_relu(Z):
return (Z > 0) * 1
def d_sigmoid(Z):
return sigmoid(Z) * (1 - sigmoid(Z))
Инициализация параметров
def initialize_params(layer_dims):
W, b = {}, {}
L = len(layer_dims)
for l in range(1, L):
W[l] = np.random.randn(layer_dims[l], layer_dims[l - 1]) * 0.01
b[l] = np.zeros((layer_dims[l], 1))
return W, b
Прямое распространение
def forward_prop(X, W, b, activation_func='relu'):
Z = np.dot(W, X) b
if activation_func == 'relu':
A = relu(Z)
elif activation_func == 'sigmoid':
A = sigmoid(Z)
elif activation_func == 'tanh':
A = tanh(Z)
return Z, A
Стоимость
def compute_cost(A_L, Y):
m = Y.shape[1]
cost = -np.sum(Y * np.log(A_L) (1 - Y) * np.log(1 - A_L), axis=1, keepdims=True) / m
return np.squeeze(cost)
Обратное распространение
def backward_prop(dA, A_prev, Z, W, activation_func):
if activation_func == 'relu':
dZ = dA * d_relu(Z)
elif activation_func == 'sigmoid':
dZ = dA * d_sigmoid(Z)
elif activation_func == 'tanh':
dZ = dA * d_tanh(Z)
m = A_prev.shape[1]
dW = np.dot(dZ, A_prev.T) / m
db = np.sum(dZ, axis=1, keepdims=True) / m
dA_prev = np.dot(W.T, dZ)
return dA_prev, dW, db
Обновить параметры
def update_params(W, b, dW, db, learning_rate):
L = len(W)
for l in range(1, L):
W[l] -= learning_rate * dW[l]
b[l] -= learning_rate * db[l]
return W, b
Neural Network Class
class LLayerNeuralNet:
def __init__(self, layer_dims, activation_funcs):
self.layer_dims = layer_dims
self.activation_funcs = activation_funcs
self.L = len(layer_dims)
# initalize W and b
self.W, self.b = initialize_params(layer_dims)
def train(self, X, Y, num_iter=1000, learning_rate=0.01, print_costs=True):
self.Z, self.A = {}, {}
self.dZ, self.dA, self.dW, self.db = {}, {}, {}, {}
self.costs = []
self.learning_rate = learning_rate
self.A[0] = X
for i in range(1, num_iter 1):
# forward propagation
for l in range(1, self.L):
self.Z[l], self.A[l] = forward_prop(self.A[l-1], self.W[l], self.b[l], self.activation_funcs[l])
# compute cost
if i % 100 == 0:
cost = compute_cost(self.A[self.L-1], Y)
self.costs.append(cost)
if print_costs:
print('Cost after %d: %f' %(i, cost))
# backward propagation
self.dA[self.L-1] = - np.divide(Y, self.A[self.L-1]) np.divide(1 - Y, 1 - self.A[self.L-1])
for l in reversed(range(1, self.L)):
self.dA[l-1], self.dW[l], self.db[l] = backward_prop(self.dA[l], self.A[l-1], self.Z[l], self.W[l], self.activation_funcs[l])
# update parameters
for l in range(1, self.L):
self.W[l] -= learning_rate * self.dW[l]
self.b[l] -= learning_rate * self.db[l]
def predict(X_pred):
A_pred = {}
A_pred[0] = X_pred
for i in range(num_iter):
for l in range(1, self.L 1):
_, A_pred[l] = forward_prop(A_pred[l-1], self.W[l], self.b[l], self.activation_funcs[l])
return (A_pred[self.L] > 0.5) * 1.0
Создание модели и ее обучение
layer_dims = [12288, 20, 7, 5, 1]
funcs = {1:'relu', 2:'relu', 3:'relu', 4:'sigmoid'}
model = LLayerNeuralNet(layer_dims, funcs)
model.train(train_x, train_y, learning_rate=0.0075)
После запуска в течение 1000 эпох затраты составляют:
Стоимость после 100: 0.678129
Стоимость после 200: 0,667676
Стоимость после 300: 0.660471
Стоимость после 400: 0.655489
Стоимость после 500: 0,652033
Стоимость после 600: 0.649628
Стоимость после 700: 0.647949
Стоимость после 800: 0.646774
Стоимость после 900: 0.645949
Стоимость после 1000: 0.645369
Я думаю, что это неверно, потому что стоимость не сильно снижается. Есть ли способ проверить правильность моей реализации?
Комментарии:
1. Кроме того, как следует отлаживать что-то подобное?
2. Какую проблему использования вы пытались решить в первую очередь? Можете ли вы подробнее рассказать об этом? Может быть, вы можете попробовать это в этом случае использования.
3. Я не пытался решить какую-либо конкретную проблему. Я узнал о нейронных сетях из deeplearning.ai курс coursera. Я просто пытался создать свою собственную нейронную сеть, просто чтобы убедиться, что я понял теорию (задания по программированию были не такими уж хорошими). Я взял набор данных из последнего задания (классификатор cat против не-cat)
Ответ №1:
Хороший способ убедиться, что ваша реализация функциональна, — начать с более простой задачи, такой как тестирование вашей реализации с помощью XOR. Судя по всему, проблема может быть такой же простой, как увеличение количества параметров в сети. Передача значений из 12288 входных узлов в 20 скрытых узлов является значительным сокращением и может привести к потере информации, необходимой вашей модели для дальнейшего снижения стоимости.