当前位置: 首页 > news >正文

深度学习:从零开始手搓一个深层神经网络

本文将带你不依赖任何深度学习框架(如 TensorFlow 或 PyTorch),仅用 NumPy 从头实现一个完整的深层神经网络(Deep Neural Network, DNN)。我们将一步步构建前向传播、反向传播、参数更新等核心模块,并在真实的猫图识别数据集上训练模型——真正“手搓”AI!


🧱 第一步:初始化网络参数

神经网络的“大脑”就是它的参数:权重矩阵 W 和偏置向量 b。我们需要为每一层随机初始化这些参数。

def initialize_parameters_deep(layer_dims):np.random.seed(1)parameters = {}L = len(layer_dims)for l in range(1, L):# 使用 Xavier 初始化(除以 sqrt(前一层神经元数))parameters['W' + str(l)] = np.random.randn(layer_dims[l], layer_dims[l-1]) / np.sqrt(layer_dims[l-1])parameters['b' + str(l)] = np.zeros((layer_dims[l], 1))return parameters
  • 为什么除以 sqrt(layer_dims[l-1])
    这是为了防止梯度爆炸或消失,让激活值的方差保持稳定(Xavier 初始化)。
  • 示例:layer_dims = [12288, 20, 7, 5, 1] 表示输入是 64×64×3=12288 维的图像,网络有 4 层隐藏/输出层。

🔁 第二步:前向传播(Forward Propagation)

前向传播分为两部分:线性变换 + 非线性激活

2.1 线性部分:Z = W·A + b

def linear_forward(A, W, b):Z = np.dot(W, A) + bcache = (A, W, b)  # 缓存用于反向传播return Z, cache

2.2 激活函数:ReLU 或 Sigmoid

def linear_activation_forward(A_prev, W, b, activation):Z, linear_cache = linear_forward(A_prev, W, b)if activation == "sigmoid":A = sigmoid(Z)elif activation == "relu":A = relu(Z)cache = (linear_cache, Z)return A, cache
  • 隐藏层用 ReLU:加速训练,缓解梯度消失。
  • 输出层用 Sigmoid:将结果压缩到 (0,1),适合二分类。

2.3 整个网络的前向传播

def L_model_forward(X, parameters):caches = []A = XL = len(parameters) // 2  # 总层数# 前 L-1 层:ReLUfor l in range(1, L):A, cache = linear_activation_forward(A, parameters['W'+str(l)], parameters['b'+str(l)], 'relu')caches.append(cache)# 最后一层:SigmoidAL, cache = linear_activation_forward(A, parameters['W'+str(L)], parameters['b'+str(L)], 'sigmoid')caches.append(cache)return AL, caches

💰 第三步:计算损失(Cost Function)

我们使用二分类交叉熵损失

def compute_cost(AL, Y):m = Y.shape[1]cost = (-1/m) * np.sum(Y * np.log(AL) + (1 - Y) * np.log(1 - AL))return np.squeeze(cost)

⚠️ 实际应用中建议加上 np.clip(AL, 1e-8, 1-1e-8) 防止 log(0)。


🔙 第四步:反向传播(Backpropagation)

反向传播的核心思想:链式法则 + 缓存复用

4.1 线性部分的梯度

def linear_backward(dZ, cache):A_prev, W, b = cachem = A_prev.shape[1]dW = np.dot(dZ, A_prev.T) / mdb = np.sum(dZ, axis=1, keepdims=True) / mdA_prev = np.dot(W.T, dZ)return dA_prev, dW, db

4.2 激活函数的梯度

def linear_activation_backward(dA, cache, activation):linear_cache, Z = cacheif activation == "relu":dZ = relu_backward(dA, Z)elif activation == "sigmoid":dZ = sigmoid_backward(dA, Z)return linear_backward(dZ, linear_cache)

4.3 全网络反向传播

def L_model_backward(AL, Y, caches):grads = {}L = len(caches)Y = Y.reshape(AL.shape)# 最后一层(Sigmoid)dAL = -(np.divide(Y, AL) - np.divide(1 - Y, 1 - AL))current_cache = caches[-1]grads["dA"+str(L-1)], grads["dW"+str(L)], grads["db"+str(L)] = \linear_activation_backward(dAL, current_cache, "sigmoid")# 前面各层(ReLU)for l in reversed(range(1, L)):current_cache = caches[l-1]dA_prev, dW, db = linear_activation_backward(grads["dA"+str(l)], current_cache, "relu")grads["dA"+str(l-1)] = dA_prevgrads["dW"+str(l)] = dWgrads["db"+str(l)] = dbreturn grads

🔄 第五步:参数更新(Gradient Descent)

有了梯度,就可以用梯度下降法更新参数:

def update_parameters(parameters, grads, learning_rate):L = len(parameters) // 2for l in range(1, L + 1):parameters["W" + str(l)] -= learning_rate * grads["dW" + str(l)]parameters["b" + str(l)] -= learning_rate * grads["db" + str(l)]return parameters

🏗️ 第六步:整合训练流程

把所有模块组装成一个完整的训练函数:

def dnn_model(X, Y, layers_dims, learning_rate=0.0075, num_iterations=2000, print_cost=True):parameters = initialize_parameters_deep(layers_dims)costs = []for i in range(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"训练 {i} 次后成本是: {cost:.6f}")costs.append(cost)plt.plot(costs)plt.title(f"Learning rate = {learning_rate}")plt.xlabel("Iterations (per hundreds)")plt.ylabel("Cost")plt.show()return parameters

🐱 第七步:在真实数据上训练

我们使用经典的 猫图识别数据集(来自 Coursera Deep Learning 课程):

# 加载并预处理数据
train_x_orig, train_y, test_x_orig, test_y, classes = load_data()
train_x = train_x_orig.reshape(train_x_orig.shape[0], -1).T / 255.
test_x = test_x_orig.reshape(test_x_orig.shape[0], -1).T / 255.# 构建 4 层网络:12288 → 20 → 7 → 5 → 1
layers_dims = [12288, 20, 7, 5, 1]
parameters = dnn_model(train_x, train_y, layers_dims, num_iterations=2000, print_cost=True)

🎯 总结

通过这篇文章,我们亲手实现了:

  • 参数初始化
  • 前向传播(含 ReLU/Sigmoid)
  • 成本计算
  • 反向传播(链式求导 + 缓存机制)
  • 梯度下降更新
  • 完整训练循环

没有调用任何高级 API,一切尽在掌握之中!

这不仅加深了对神经网络内部机制的理解,也为后续学习更复杂的模型(如 CNN、RNN)打下坚实基础。

💡 真正的深度学习,始于手搓一行代码。

http://www.dtcms.com/a/601114.html

相关文章:

  • Docker 多服务镜像构建完整教程
  • Docker 启动 EMQX 5.x 并配置自签名证书
  • 网站招工费怎么做会计分录小小视频免费观看高清
  • C++重点知识梳理(上)
  • 长沙市建设局官方网站wordpress 显示文章标签
  • 基于用户评论分析挖掘的旅游景点推荐系统
  • 宣传旅游网站建设的重点是什么装修公司哪家好排名
  • 【C语言学习笔记】动态内存分配:malloc/free的正确打开方式
  • HOVER:用于人形机器人的多功能全身神经控制器
  • 学会给网页穿衣服——学习 CSS 语言
  • Android11-Launcher3 定制-去除副屏幕-可以滑动效果 - 篇二
  • 在 ubuntu怎么创建一个新用户,并且设置为默认自动登录用户,最简单
  • 字符串的陷阱与艺术——std::string全解析
  • 深信服云桌面有什么替代方案?
  • 网页制作与网站建设试卷及答案wordpress 默认文章形式
  • 企业为什么要建立自己的网站云南工程建设信息网站
  • Dubbo如何使用Nacos做注册中心的
  • 决策树悲观错误剪枝(PEP)详解:原理、实现与应用
  • 外卖项目 day01
  • 前端vue3 window.open 项目部署后页面404解决办法
  • pc网站 手机网站 微信网站 上海跨境电商官方网站建设
  • Windows 10 C语言编译器安装与配置
  • 网站后台进不去的原因挂机宝做php网站吗
  • Java I/O模型演进 — BIO、NIO与AIO的原理与实战
  • Flutter---泛型
  • 小米Java开发200道面试题及参考答案(上)
  • 【实战】如何优雅的在Win11/10系统下运行Rust编写的binwalk v3.1.1
  • 网站建设费可以计入管理费用吗手机网站开发利用流程
  • MySQL进阶学习笔记:从单表查询到多表关联的深度解析(万字详解)
  • docker一键部署PDF免费工具箱stirling-PDF