本项目为神经网络课程的课设,做总结加深印象之用,欢迎大家指出不足之处
正文:
导入numpy库(简言之,numpy就是把各种用python写的(核心运算用其他语言写以优化性能,因为python较慢)可以处理不同数组运算的函数打包为一个库,如各种n维数组的创建,转置,乘积等线性代数中 学习的知识,使用者如需要使用相关函数可以下载该库并导入到相应文件中,方便处理相关数据和运算)
import numpy as np
定义两种常见的激活函数(简言之,激活函数就是使上层节点的输出和下层节点的输入之间具有一个函数关系,如果没有激活函数,只有简单的加权求和那么无论有多少层的神经网络,输入和输出都是可知的线性关系 ,那么该网络的能力就十分有限难以逼近复杂的非线性关系,使用激活函数就可以使该网络能力更加强大,更能逼近输入与输出之间的关系)
def sigmoid(Z):
A = 1 / (1 + np.exp(-Z))
cache = Z
return A, cache
def relu(Z):
A = np.maximum(0, Z)
cache = Z
return A, cache
定义激活函数的反向传播算法,反向传播算法用于计算损失函数关于网络参数的梯度,以便通过梯度下降等方法更新这些参数,接受激活函数关于激活值A的梯度dA以及激活函数中用于存储相应数据的cache,返回损失函数关于激活函数输入Z 的梯度用于计算网络中前一层参数的梯度。
def sigmoid_backward(dA, cache):
Z = cache
s = 1 / (1 + np.exp(-Z))
dZ = dA * s * (1 - s)
return dZ
def relu_backward(dA, cache):
Z = cache
dZ = np.array(dA, copy=True)
dZ[Z <= 0] = 0
return dZ
初始化一个两层的神经网络,神经网络通常包含权重(W)和偏置(b)作为可学习的参数。这些参数在训练开始前被随机初始化,以便在训练过程中通过反向传播算法进行更新。
def initialize_parameters(n_x, n_h, n_y):
np.random.seed(1)
W1 = np.random.randn(n_h, n_x) * 0.01
b1 = np.zeros((n_h, 1))
W2 = np.random.randn(n_y, n_h) * 0.01
b2 = np.zeros((n_y, 1))
parameters = {"W1": W1,
"b1": b1,
"W2": W2,
"b2": b2}
return parameters
初始化 L 层神经网络参数
def initialize_parameters_deep(layers_dims):#layers_dims是个列表,包含每一层神经元的数量
#确保每次调用该函数时都能生成相同的随机数,这有助于调试和复现结果。
np.random.seed(3)
parameters = {}
L = len(layers_dims)
for l in range(1, L):
parameters['W' + str(l)] = np.random.randn(layers_dims[l], layers_dims[l - 1]) * 0.01
parameters['b' + str(l)] = np.zeros((layers_dims[l], 1))
return parameters
前向传播(加权求和以及激活)
# 前向传播线性部分
def linear_forward(A, W, b):
Z = np.dot(W, A) + b
cache = (A, W, b)
return Z, cache
# 前向传播线性->激活
def linear_activation_forward(A_prev, W, b, activation):
if activation == "sigmoid":
Z, linear_cache = linear_forward(A_prev, W, b)
A, activation_cache = sigmoid(Z)
elif activation == "relu":
Z, linear_cache = linear_forward(A_prev, W, b)
A, activation_cache = relu(Z)
cache = (linear_cache, activation_cache)
return A, cache
# 前向传播 L 层模型
def L_model_forward(X, parameters):
caches = []
A = X
L = len(parameters) // 2
for l in range(1, L):
A_prev = A
A, cache = linear_activation_forward(A_prev, parameters['W' + str(l)], parameters['b' + str(l)],
activation="relu")
caches.append(cache)
AL, cache = linear_activation_forward(A, parameters['W' + str(L)], parameters['b' + str(L)], activation="sigmoid")
caches.append(cache)
return AL, caches
用交叉熵损失函数计算损失值
def compute_cost(AL, Y):
m = Y.shape[1]
cost = -(1 / m) * np.sum(Y * np.log(AL) + (1 - Y) * np.log(1 - AL))
cost = np.squeeze(cost)
return cost
反向传播(在神经网络中,通过计算损失函数关于各层参数的梯度,逐层更新参数以最小化损失函数。)
dA_prev
:前一层的激活值的梯度,将用于前一层的反向传播。dW
:当前层权重的梯度,将用于更新当前层的权重。db
:当前层偏置的梯度,将用于更新当前层的偏置。
def linear_backward(dZ, cache):
A_prev, W, b = cache
m = A_prev.shape[1]
dW = (1 / m) * np.dot(dZ, A_prev.T)
db = (1 / m) * np.sum(dZ, axis=1, keepdims=True)
dA_prev = np.dot(W.T, dZ)
return dA_prev, dW, db
# 反向传播 L 层模型
def L_model_backward(AL, Y, caches):
grads = {}
L = len(caches)
m = AL.shape[1]
Y = Y.reshape(AL.shape)
dAL = - (np.divide(Y, AL) - np.divide(1 - Y, 1 - AL))
current_cache = caches[L - 1]
grads["dA" + str(L - 1)], grads["dW" + str(L)], grads["db" + str(L)] = linear_activation_backward(dAL,current_cache,activation="sigmoid")
for l in reversed(range(L - 1)):
current_cache = caches[l]
dA_prev_temp, dW_temp, db_temp = linear_activation_backward(grads["dA" + str(l + 1)], current_cache,
activation="relu")
grads["dA" + str(l)] = dA_prev_temp
grads["dW" + str(l + 1)] = dW_temp
grads["db" + str(l + 1)] = db_temp
return grads
更新参数
接受的参数有所有层的w和b,所有层w和b的梯度,学习率(控制更新步长)。返回所有层更新后的权重和偏置
def update_parameters(parameters, grads, learning_rate):
L = len(parameters) // 2
for l in range(L):
parameters["W" + str(l + 1)] -= learning_rate * grads["dW" + str(l + 1)]
parameters["b" + str(l + 1)] -= learning_rate * grads["db" + str(l + 1)]
return parameters
整合所有模块
def L_layer_model(X, Y, layers_dims, learning_rate=0.0075, num_iterations=3000, print_cost=False):
np.random.seed(1)
costs = []
parameters = initialize_parameters_deep(layers_dims)
for i in range(0, num_iterations):
AL, caches = L_model_forward(X, parameters)
cost = compute_cost(AL, Y)
grads = L_model_backward(AL, Y, caches)
parameters = update_parameters(parameters, grads, learning_rate)
if print_cost and i % 100 == 0:
print(f"Cost after iteration {i}: {cost}")
costs.append(cost)
return parameters
模拟训练
if __name__ == "__main__":
# 假设 X 是输入数据,Y 是标签,生成标准正太分布的随机数
X = np.random.randn(12288, 209)
Y = (np.random.randn(1, 209) > 0).astype(int)#0或1
layers_dims = [12288, 20, 7, 5, 1]
parameters = L_layer_model(X, Y, layers_dims, num_iterations=2000, print_cost=True)
得到结果