大模型0基础开发入门与实践:第4章 “脑细胞”的模拟:神经网络与深度学习入门

第4章 “脑细胞”的模拟:神经网络与深度学习入门

1. 引言

在上一章,我们像一位侦探,学会了使用决策树这样的工具,从清晰的线索(花瓣、花萼的尺寸)中推理出确定的结论(鸢尾花的种类)。但如果案情变得扑朔迷离,线索不再是简单的数字,而是一幅模糊的监控录像截图(图像),或是一段充满暗示的匿名录音(语音),我们该如何应对?传统的机器学习模型,就像一位依赖明确证据的侦探,面对这种高度抽象、复杂的数据时,常常会束手无策。

这时,我们需要一位更“高级”的侦探——一位能够模仿人类大脑,从海量、杂乱的信息中,通过直觉和经验,自动发现深层模式的专家。这位“仿生侦探”,就是我们本章的主角:人工神经网络(Artificial Neural Network, ANN)

你是否曾好奇,我们的大脑是如何在毫秒之间认出一位多年未见的老友的?我们并非在脑中调用一个“if-else”规则库,而是通过亿万个神经元的协同工作,瞬间完成了模式匹配。深度学习的革命,正是源于对这种生物智能的深刻模仿。

本章学习目标:

  • 追本溯源:理解人工神经网络的设计灵感——生物神经元的工作原理。
  • 解构基本单元:掌握构成神经网络的最小单位——**感知器(Perceptron)神经元(Neuron)**的数学模型。
  • 搭建“迷你大脑”:学会如何将单个神经元组织成层次化的网络结构(输入层、隐藏层、输出层)。
  • 洞悉学习的奥秘:直观地理解神经网络是如何通过**前向传播(Forward Propagation)进行预测,并通过反向传播(Backpropagation)梯度下降(Gradient Descent)**来修正错误的。
  • 初探深度学习框架:使用当前最流行的深度学习框架之一PyTorchTensorFlow(Keras),亲手搭建并训练你的第一个神经网络。

本章核心问题:

  • 一个“人工神经元”是如何模拟生物神经元,对信息进行“处理”和“激活”的?
  • “神经网络”这个名字中的“网络”体现在哪里?信息是如何在其中流动的?
  • 如果神经网络做出了错误的预测,它是如何“聪明地”知道应该调整网络中哪个部分的哪个参数,以及应该调整多少的?这个过程(反向传播)可以如何通俗地理解?

在本章,我们将踏上一段激动人心的“仿生学”之旅。我们将从最基础的“脑细胞”开始,一步步搭建起一个能够学习和思考的“迷你大脑”。这将是理解所有现代大语言模型(如GPT)的基石,是整个课程中最具奠基意义的章节之一。系好安全带,我们将进入深度学习的核心腹地。


2. 正文

2.1 灵感之源:会“放电”的生物神经元

要构建人工神经网络,我们首先要看看它的“设计蓝本”——我们大脑中的生物神经元。

背景与动机
我们的大脑是一个由大约860亿个神经元组成的复杂网络。每个神经元本身是一个简单的处理单元,但它们以极其复杂的方式相互连接,形成了强大的计算能力。20世纪40年代,科学家沃伦·麦卡洛克和沃尔特·皮茨受到生物神经科学的启发,首次提出了一个极简的数学模型来描述神经元的工作方式,为人工神经网络奠定了思想基础。

直观比喻:生物神经元的工作流程

想象一个神经元就像一个社交达人

  1. 接收信息:他有许多“耳朵”(树突, Dendrites),用来接收来自成百上千个其他朋友(其他神经元)传来的“八卦消息”(化学信号)。
  2. 信息汇总:他把所有听到的消息汇总到自己的“大脑”(细胞体, Soma)里进行加工。请注意,并非所有朋友的话他都同样看重,来自“闺蜜”的消息权重可能就比来自“点头之交”的要高。
  3. 判断是否转发:当他脑中汇总的信息量(电信号)超过了一个阈值(Threshold),达到一个“不吐不快”的兴奋点时,他就会做出“转发”决策。
  4. 发布消息:他通过自己的“大喇叭”(轴突, Axon),将这个消息(动作电位)广播出去,传递给下游的其他朋友。如果没达到兴奋点,他就选择“保持沉默”。

这个“加权汇总 -> 判断是否激活 -> 传递信息”的过程,就是神经元工作的核心逻辑。

graph LRA[上游神经元A] -- 信号1 --> D{细胞体};B[上游神经元B] -- 信号2 --> D;C[上游神经元C] -- 信号3 --> D;subgraph 单个神经元direction LRD -- "汇总信号<br/>(w1*信号1 + w2*信号2 + ...)" --> E[激活判断<br/>(是否超过阈值?)];E -- "激活(放电)" --> F[轴突];endF -- 传递给下游 --> G[下游神经元];

2.2 从生物到数学:人工神经元(感知器)

现在,让我们用数学语言来翻译一下上面那个“社交达人”的工作流程,这就诞生了最早的人工神经元模型——感知器(Perceptron)

原理解析
一个感知器接收多个二进制输入((x_1, x_2, …, x_n)),并产生一个单独的二进制输出。

  • 加权汇总:每个输入 (x_i) 都被赋予了一个权重(weight) (w_i)。这个权重就代表了那位“社交达人”对不同朋友消息的重视程度。权重可以是正数(表示这个朋友的意见很重要,是促进因素),也可以是负数(表示这个朋友的意见需要反着听,是抑制因素)。我们将所有输入的加权和计算出来:
    [
    \text{Sum} = \sum_{i} w_i x_i + b
    ]
    这里的 (b) 是偏置(bias),你可以把它理解为这位“社交达人”自己内心的“固有偏见”或“兴奋的基础值”。即使没有任何朋友传来消息,如果他天生就很“嗨”(偏置值很高),也可能达到兴奋点。反之,如果他天生就很“丧”(偏置值很低),就需要特别多、特别强的正面消息才能被激活。

  • 激活判断:接下来,感知器使用一个简单的**阶跃函数(Step Function)作为激活函数(Activation Function)**来判断输出。
    [
    \text{Output} =
    \begin{cases}
    1 & \text{if } \text{Sum} \ge 0 \
    0 & \text{if } \text{Sum} < 0
    \end{cases}
    ]
    这完美地模拟了“超过阈值就激活(输出1),否则就抑制(输出0)”的过程。

下图展示了一个接收3个输入的感知器模型:

graph TDsubgraph 感知器x1[输入 x1] -- w1 --> Sum;x2[输入 x2] -- w2 --> Sum;x3[输入 x3] -- w3 --> Sum;bias[偏置 b] -- 1 --> Sum;Sum["Σ (加权和)"] --> Activation["激活函数<br/>(阶跃函数)"];Activation --> Output[输出 (0或1)];end

代码实战:用Python实现一个逻辑“与”门感知器
逻辑“与”(AND)门是一个简单的逻辑单元:只有当两个输入都为1时,输出才为1。我们可以用一个感知器来模拟它。

import numpy as npdef AND_gate(x1, x2):"""使用感知器模型实现一个'与'门:param x1: 输入1 (0或1):param x2: 输入2 (0或1):return: 感知器的输出 (0或1)"""# 输入向量x = np.array([x1, x2])# 权重向量。w1=0.5, w2=0.5。这两个权重意味着我们平等地看待两个输入。w = np.array([0.5, 0.5])# 偏置。b=-0.7。这个负偏置意味着,需要足够强的输入信号才能克服它,使总和大于0。b = -0.7# 计算加权和# np.sum(w*x)就是 w1*x1 + w2*x2weighted_sum = np.sum(w*x) + b# 通过阶跃函数激活if weighted_sum > 0:return 1else:return 0# --- 测试我们的'与'门 ---
print(f"AND(0, 0) = {AND_gate(0, 0)}") # 预期输出: 0
print(f"AND(1, 0) = {AND_gate(1, 0)}") # 预期输出: 0
print(f"AND(0, 1) = {AND_gate(0, 1)}") # 预期输出: 0
print(f"AND(1, 1) = {AND_gate(1, 1)}") # 预期输出: 1

预期输出:

AND(0, 0) = 0
AND(1, 0) = 0
AND(0, 1) = 0
AND(1, 1) = 1

Q&A: 你可能会问……

  • Q: 这里的权重w和偏置b是我手动设置的,这算是“学习”吗?
  • A: 问得好!这不算学习,这只是“实现”。我们是基于对“与”门逻辑的理解,手动设计了这组参数。真正的机器学习,是让机器从大量的(输入, 正确输出)数据对中,自动地、通过训练地找到这组合适的wb

2.3 从单个细胞到神经网络:层次化的力量

单个感知器能解决的问题非常有限(只能解决线性可分问题)。但是,当我们把成千上万个这样的“神经元”连接起来,形成一个层次化的“网络”时,奇迹就发生了。

一个典型的神经网络由以下几个部分组成:

  • 输入层 (Input Layer):网络的入口,负责接收最原始的数据。输入层有几个神经元,就代表我们的数据有几个特征。例如,在鸢尾花分类任务中,输入层就有4个神经元,分别对应花萼长、花萼宽、花瓣长、花瓣宽。
  • 隐藏层 (Hidden Layers):位于输入层和输出层之间,是神经网络进行“深度”思考的地方。这些层对外界是不可见的,它们负责从输入数据中提取越来越抽象、越来越复杂的特征。一个神经网络可以没有隐藏层(那就退化成了感知器),也可以有一个或多个隐藏层。
  • 输出层 (Output Layer):网络的出口,负责产生最终的预测结果。输出层神经元的数量和激活函数的形式,取决于我们的任务。
    • 二分类任务:通常用1个神经元,配合Sigmoid激活函数(输出一个0到1之间的概率)。
    • 多分类任务:通常用N个神经元(N为类别数),配合Softmax激活函数(输出N个类别各自的概率)。
    • 回归任务:通常用1个神经元,且不使用激活函数(或使用线性激活函数)。

直观比喻:图像识别的神经网络
想象一个识别“猫”的深度神经网络:

  • 输入层:接收一张图片的所有像素点。
  • 第一个隐藏层(浅层):这一层的神经元,可能会在训练后,各自学会识别一些基础的视觉元素,比如边缘、角点、颜色块。它们就像一群只负责画“横竖撇捺”的小学生。
  • 第二个隐藏层(中层):这一层的神经元接收来自第一层的信息。它会把那些“横竖撇捺”组合起来,学会识别更复杂的形状,比如眼睛、鼻子、耳朵、胡须。它们就像一群能把笔画组成“偏旁部首”的中学生。
  • 第三个隐藏层(深层):这一层的神经元,会把“眼睛”、“鼻子”、“耳朵”这些部件组合起来,最终学会识别出“猫脸”这个高度抽象的概念。它们就像一位能“组字成文”的大学生。
  • 输出层:接收到“猫脸”这个强烈的信号后,最终做出判断:“这是一只猫”。

这种层次化的特征提取,正是深度学习(“深度”就体现在隐藏层的数量多)之所以如此强大的核心原因。

神经网络
输入层
隐藏层1
隐藏层2
输出层
Setosa概率
Versicolour概率
Virginica概率
H2_1
H2_2
H2_3
H1_1
H1_2
H1_3
H1_4
H1_5
特征1: 花萼长
特征2: 花萼宽
特征3: 花瓣长
特征4: 花瓣宽

*注意:上图是一个**全连接(Fully Connected)*网络,意味着前一层中的每一个神经元都与后一层中的所有神经元相连。

2.4 学习的机制:前向传播与反向传播

我们已经搭建好了网络结构,但它的参数(权重w和偏置b)最初都是随机的,像一个什么都不懂的“新生大脑”。我们如何训练它呢?这个过程分为两步:前向传播反向传播

1. 前向传播 (Forward Propagation):进行一次“猜测”

这个过程很简单,就是让数据“从前到后”地流过整个网络,得出一个预测结果。

  1. 我们将一个样本数据(比如一张鸢尾花的数据)喂给输入层
  2. 输入层的输出,被传递给第一个隐藏层的每一个神经元。
  3. 第一个隐藏层的每个神经元,各自进行加权求和激活,然后将它们的输出传递给第二个隐藏层
  4. 这个过程层层递进,直到数据流过输出层,产生最终的预测值(比如[0.1, 0.8, 0.1],表示模型认为这朵花有80%的概率是Versicolour)。

2. 反向传播 (Backpropagation):一次“聪明的复盘”

现在,我们拿到了模型的“猜测”结果 y_pred,但我们还有“标准答案” y_true(比如,这朵花其实是Virginica,对应的标签是[0, 0, 1])。两者之间存在一个误差(Loss)。现在最关键的问题来了:我们该如何调整网络中成千上万个w和b,来让这个误差变小呢?

直观比喻:反向传播

想象一下,你是一个大型公司的CEO(输出层的误差),公司的年度利润目标没有达成(预测值与真实值有差距)。你非常生气,需要问责。

  1. 问责第一层(输出层 -> 隐藏层2):你首先找到你的直属下级——各位副总裁(隐藏层2的神经元)。你不会平均地批评他们,而是看谁负责的业务线(连接权重)对最终的利润亏损“贡献”最大,你就批评谁最狠。这个“贡献度”,在数学上就是偏导数(梯度)
  2. 问责第二层(隐藏层2 -> 隐藏层1):各位副总裁被批评后,他们会用同样的方式,去问责他们各自的直属下级——各位部门总监(隐藏层1的神经元)。一个总监会不会被批评,取决于他所支持的副总裁们被CEO批评的有多狠,以及他自己对这些副总裁的“贡献度”有多大。
  3. 层层传递:这个问责链会从后往前,一层一层地传递下去,直到最基层的员工(输入层的连接权重)。
  4. 集体调整:最终,公司里的每个人都根据自己对最终错误的“贡献度”,以及上级传达下来的“批评力度”,来微调自己的工作方式(更新参数w和b)。那些对错误“贡献”最大的连接,其权重会被做最大的调整。

这个“从后向前,层层追究责任,并按贡献度进行调整”的过程,就是反向传播的精髓。它是一种极其高效的算法,能够计算出损失函数对网络中每一个参数的梯度(偏导数),从而指导我们如何最有效率地去更新参数,以降低总损失。这个更新参数的具体方法,就是我们熟悉的梯度下降法

graph TDdirection LRA[输入] -- 前向传播 --> B(神经网络<br/>参数 w, b);B -- 预测值 y_pred --> C{计算损失<br/>Loss(y_pred, y_true)};C -- 误差信号 --> D(反向传播<br/>计算损失对每个参数的梯度 ∇w, ∇b);D -- 梯度信息 --> E(参数更新<br/>w = w - η*∇w<br/>b = b - η*∇b);E -- 更新后的参数 --> B;

注:这里的 (\eta) 是学习率(Learning Rate),它控制了我们每次参数更新的“步子”迈多大。

通过无数次的“前向传播 -> 计算损失 -> 反向传播 -> 更新参数”的循环,神经网络的参数就会被训练得越来越好,模型也就“学会”了。


2.5 神兵利器:初探深度学习框架PyTorch

理论我们已经了然于胸,但如果让我们用NumPy从零开始手写前向传播、反向传播、梯度下降……那将是一项极其繁琐且容易出错的工程。幸运的是,我们有专门为此设计的“神兵利器”——深度学习框架

背景与动机
PyTorchTensorFlow这样的框架,为我们处理好了所有底层的、复杂的数学运算和优化过程。它们的核心优势在于:

  1. 自动求导(Autograd):我们只需要搭建好神经网络的结构(前向传播),框架会自动帮我们计算所有参数的梯度。这极大地解放了我们,让我们不用手动去实现复杂的反向传播算法。
  2. GPU加速:神经网络的计算(主要是大规模的矩阵乘法)非常适合在GPU上并行处理。这些框架能让我们用极少的代码,就将计算任务无缝地迁移到GPU上,获得几十甚至上百倍的速度提升。
  3. 模块化组件:框架提供了大量预先封装好的“积木”,如网络层(nn.Linear)、激活函数(nn.ReLU)、损失函数(nn.CrossEntropyLoss)、优化器(optim.Adam)等,让我们可以像搭乐高一样,快速地构建和实验各种复杂的模型。

直观比喻:NumPy vs PyTorch

  • 用NumPy写神经网络,就像你从零开始,用砖块、水泥、钢筋来徒手盖一座房子。你需要精确地计算每一个力学结构,手动搬运每一块砖。这能让你深刻理解建筑的原理,但效率极低,且极易“塌房”。
  • 用PyTorch写神经网络,则像是你使用高度模块化的预制件来建造房子。墙体、窗户、屋顶都是在工厂里按标准生产好的(nn.Linear, nn.ReLU…)。你只需要像一个设计师一样,将这些模块按照你的蓝图(模型结构)组装起来即可。坚固、美观且效率极高。

我们将以PyTorch为例进行实战,它是目前学术界和工业界最受欢迎的框架之一,以其灵活性和简洁的“Pythonic”风格著称。

2.6 实战:用PyTorch搭建神经网络解决手写数字识别

我们将挑战一个比鸢尾花分类更复杂一点的任务:MNIST手写数字识别。这是一个“计算机视觉”领域的“Hello World”项目。

场景
MNIST数据集包含了大量28x28像素的手写数字灰度图片(从0到9),以及它们对应的真实标签。我们的任务是构建一个神经网络,输入一张这样的图片,让它能准确地识别出图片上写的是哪个数字。

代码实战

# --- 1. 导入必要的PyTorch库 ---
import torch
import torch.nn as nn # nn模块包含了构建神经网络所需的所有核心组件
import torch.optim as optim # optim模块包含了各种优化算法,如SGD, Adam
from torchvision import datasets, transforms # torchvision是PyTorch处理视觉问题的库
from torch.utils.data import DataLoader# --- 2. 准备数据 ---
# 定义一个转换流程:将图片转换成PyTorch的Tensor,并进行归一化
# 归一化:将像素值从[0, 255]的范围,转换到[-1, 1]的范围。这有助于模型更快更好地收敛。
transform = transforms.Compose([transforms.ToTensor(), # 将PIL图像或numpy.ndarray转换为tensor,并将像素值缩放到[0,1]transforms.Normalize((0.5,), (0.5,)) # 将[0,1]的数据归一化到[-1,1]
])# 下载并加载训练数据集
# root='./data'表示数据下载到当前目录下的data文件夹
# train=True表示加载训练集
# download=True表示如果本地没有,就自动下载
train_set = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
# DataLoader是一个重要工具,它帮助我们将数据集打包成一个个的批次(batch),并能自动打乱数据
train_loader = DataLoader(train_set, batch_size=64, shuffle=True)# 下载并加载测试数据集
test_set = datasets.MNIST(root='./data', train=False, download=True, transform=transform)
test_loader = DataLoader(test_set, batch_size=64, shuffle=False)# --- 3. 定义神经网络模型 ---
# 我们通过继承nn.Module的方式来定义自己的网络结构
class Net(nn.Module):def __init__(self):super(Net, self).__init__()# 定义网络层。我们这里构建一个简单的全连接网络# nn.Linear(in_features, out_features) 定义一个线性层(全连接层)# 28*28 = 784,这是我们输入图片被展平后的维度# 128是第一个隐藏层的神经元数量(这个数字是经验性的,可以调整)self.fc1 = nn.Linear(28 * 28, 128) # 第二个隐藏层self.fc2 = nn.Linear(128, 64)# 输出层。输出10个值,分别对应0-9这10个数字的概率self.fc3 = nn.Linear(64, 10)# 定义激活函数self.relu = nn.ReLU()# forward方法定义了数据在网络中的“前向传播”路径def forward(self, x):# x的初始形状是 [batch_size, 1, 28, 28]# x.view(-1, 28 * 28) 将其展平成 [batch_size, 784]x = x.view(-1, 28 * 28)# 数据依次流过每一层x = self.relu(self.fc1(x)) # 第一层:线性变换 -> ReLU激活x = self.relu(self.fc2(x)) # 第二层:线性变换 -> ReLU激活x = self.fc3(x)           # 输出层:只做线性变换,因为损失函数会自动处理return x# 创建模型实例
model = Net()
print("我们定义的神经网络结构:")
print(model)# --- 4. 定义损失函数和优化器 ---
# 交叉熵损失函数,非常适合用于多分类问题
criterion = nn.CrossEntropyLoss() 
# 优化器我们选择Adam,它是一种高效的梯度下降算法的变体
# lr=0.001是学习率
optimizer = optim.Adam(model.parameters(), lr=0.001)# --- 5. 训练模型 ---
epochs = 3 # 我们将整个数据集完整地训练3遍for epoch in range(epochs):running_loss = 0.0# 从train_loader中批量取出数据for images, labels in train_loader:# 1. 清零梯度:这是每次迭代前必须做的一步optimizer.zero_grad()# 2. 前向传播:将图片输入模型,得到预测输出outputs = model(images)# 3. 计算损失loss = criterion(outputs, labels)# 4. 反向传播:计算损失对所有参数的梯度loss.backward()# 5. 更新参数:优化器根据梯度来调整模型的权重optimizer.step()running_loss += loss.item()print(f"训练周期 {epoch+1}/{epochs} 完成, 平均损失: {running_loss/len(train_loader):.4f}")print("\n模型训练完成!")# --- 6. 评估模型 ---
correct = 0
total = 0
# 在测试时,我们不希望计算梯度,这样可以节省计算资源
with torch.no_grad():for images, labels in test_loader:outputs = model(images)# torch.max会返回最大值和对应的索引。我们只需要索引(即预测的类别)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print(f"\n模型在10000张测试图片上的准确率: {100 * correct / total:.2f} %")

预期输出:

我们定义的神经网络结构:
Net((fc1): Linear(in_features=784, out_features=128, bias=True)(fc2): Linear(in_features=128, out_features=64, bias=True)(fc3): Linear(in_features=64, out_features=10, bias=True)(relu): ReLU()
)
训练周期 1/3 完成, 平均损失: 0.3708
训练周期 2/3 完成, 平均损失: 0.1654
训练周期 3/3 完成, 平均损失: 0.1189模型训练完成!模型在10000张测试图片上的准确率: 96.55 %

Q&A: 你可能会问……

  • Q: 隐藏层的数量和神经元的个数(128, 64)是怎么决定的?
  • A: 这是一个非常核心的问题,被称为网络架构设计超参数调整。目前,这很大程度上仍然是一门“艺术”而非精确科学,依赖于经验、实验和一些设计原则。对于初学者,可以从一些经典的、被验证过的简单结构开始模仿。通常,更深(层数多)、更宽(神经元多)的网络有更强的学习能力,但也更容易过拟合(在训练集上表现好,但在测试集上表现差),并且需要更多的计算资源。
  • Q: nn.ReLU是什么?为什么不用之前感知器里的阶跃函数?
  • A: ReLU (Rectified Linear Unit)是目前最常用的激活函数之一,它的数学形式是f(x) = max(0, x)。相比于阶跃函数,它有一个非常重要的优点:在x>0的区域,它的导数恒为1。而阶跃函数几乎处处导数为0。在基于梯度的学习(反向传播)中,如果激活函数的导数总是0,梯度就无法有效地回传,网络就“学不动”了,这个问题被称为“梯度消失”。ReLU在很大程度上缓解了这个问题,使得训练更深的网络成为可能。

3. 总结与预告

在本章,我们完成了一次从生物学到计算机科学的跨越,深入探索了深度学习的基石——人工神经网络。

本章核心要点

  • 核心思想:神经网络通过模拟生物神经元的工作原理,将简单的处理单元(神经元)组织成层次化的网络,从而实现对复杂模式的层次化特征提取
  • 基本单元:人工神经元通过对输入进行加权求和,并通过一个激活函数(如ReLU)来决定其输出。
  • 学习机制:神经网络的学习是一个迭代的过程,通过前向传播做出预测,计算损失,然后通过反向传播高效地计算梯度,最后由优化器(如Adam)利用梯度来更新网络参数。
  • 深度学习框架:以PyTorch为代表的框架,通过自动求导模块化的设计,极大地简化了神经网络的搭建和训练过程,让我们能专注于模型架构的设计。
  • 实战成果:我们成功地使用PyTorch构建了一个简单的全连接神经网络,并在MNIST手写数字识别任务上取得了超过96%的准确率,亲身体验了深度学习的威力。

我们已经掌握了构建“大脑”的基本方法。但是,我们目前构建的“全连接神经网络”,在处理某些特定类型的数据时,还不够高效。例如,在处理图像时,它没有考虑到像素之间的空间关系;在处理语言时,它没有考虑到词语之间的顺序关系。

在下一章 《“听”和“看”的智慧:自然语言处理与计算机视觉基础》 中,我们将学习两种为特定任务“量身定做”的、更强大的神经网络结构:专门用于“看”的卷积神经网络(CNN)和早期用于“听”和“读”的循环神经网络(RNN)。这将使我们处理真实世界中非结构化数据的能力,再上一个台阶。


4. 课后练习

  1. 激活函数探索:查阅资料,了解除了ReLU之外,还有哪些常用的激活函数(例如:Sigmoid, Tanh, Leaky ReLU)。请简要描述它们各自的数学形式和优缺点。
  2. 代码调优:请尝试修改本章PyTorch实战代码中的超参数,看看能否获得更高的测试准确率。你可以尝试调整:
    • 学习率lr):试试把它调大(如0.01)或调小(如0.0001),观察训练过程的损失变化和最终准确率。
    • 网络宽度:改变隐藏层神经元的数量(如fc1改为256,fc2改为128)。
    • 训练周期数epochs):增加训练周期,看看准确率是否会继续提升。
  3. 思辨题:我们提到,更深、更宽的网络有更强的学习能力,但也更容易“过拟合”。请用你自己的话解释一下,什么是“过拟合”?并用一个生活中的例子来比喻它(例如:一个只会死记硬背、不会举一反三的学生)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/93940.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/93940.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微服务之间的调用关系如何处理,才能防止循环依赖

在微服务架构中&#xff0c;循环依赖是常见的设计问题&#xff0c;可能导致系统部署失败、启动顺序冲突、故障排查困难等问题。处理循环依赖的核心原则是通过架构设计打破依赖闭环&#xff0c;以下是具体的解决方案&#xff1a; 1. 重新划分服务边界&#xff08;根本解决&#…

粗粮厂的基于flink的汽车实时数仓解决方案

基于flink的实时数仓解决方案1 背景2 业务模型1 业务框架2 难点痛点3技术选型1 计算引擎2 中间存储3 查询引擎4 flink计算架构设计1 纯实时架构2 纯实时定期补充离线数据3 纯实时定期刷新过期binlog4 lamdba 分字段更新 历史过期数据刷新5 痛点解决delta joinmerge-enginehol…

Datawhale AI夏令营---coze空间共学

1.进入coze空间 2.点击免费使用 3.点击制作播客&#xff0c;微信上面选好链接 彻底搞懂深度学习-模型训练和推理&#xff08;动图讲解&#xff09; 4.运行过程 5.音频链接 https://lf-bot-studio-plugin-resource.coze.cn/obj/bot-studio-platform-plugin-tos/sami_podcast…

遥感机器学习入门实战教程|Sklearn案例⑥:网格搜索与超参数优化

在前几篇案例中&#xff0c;有同学在后台留言&#xff1a;“模型的参数到底怎么调&#xff1f;比如 SVM 的 C 和 γ&#xff0c;随机森林的树数和深度&#xff0c;要怎么选才能得到最优结果呢&#xff1f;”这是一个非常经典的问题&#xff1a;参数选不好&#xff0c;模型效果差…

论文精读(三)|智能合约漏洞检测技术综述

笔者链接&#xff1a;扑克中的黑桃A 专栏链接&#xff1a;论文精读 本文关键词&#xff1a;智能合约;合约安全;合约可靠性;合约质量保障;漏洞检测;合约程序分析 引 诸位技术同仁&#xff1a; 本系列将系统精读的方式&#xff0c;深入剖析计算机科学顶级期刊/会议论文&#…

YOLO --- YOLO11模型以及项目详解

YOLO — YOLO11模型以及项目详解 文章目录YOLO --- YOLO11模型以及项目详解一&#xff0c;开源地址二&#xff0c;重要模块2.1 C3K22.2 C2PSA2.3 检测头三&#xff0c;网络结构3.1 整体结构划分3.2 Backbone 结构分析&#xff08;从下往上看&#xff09;3.3 结构分析&#xff0…

Debezium监听MySQL binlog并实现有状态重启

Debezium实现MySQL数据监听了解Debezium​ 本期主要内容实现步骤1. 新建Maven工程2.导入依赖3.核心代码编写4.offset的存储5.OffsetBackingStore实现jdbc模式6.运行结果总结了解Debezium 官网&#xff1a;https://debezium.io/ Debezium是一组分布式服务&#xff0c;用于捕获数…

InfluxDB 存储优化:TSM 文件管理与空间回收(一)

一、InfluxDB 与 TSM 文件初相识**在数字化时代&#xff0c;数据量呈爆发式增长&#xff0c;尤其是时间序列数据&#xff0c;如服务器监控指标、传感器读数、金融交易记录等&#xff0c;它们都带有时间戳&#xff0c;记录着事物随时间的变化。InfluxDB 作为一款高性能的开源时序…

macos使用FFmpeg与SDL解码并播放H.265视频

效果: 安装依赖: brew install ffmpeg brew install sdl2 brew install x265 确认x265已启用 查看x265版本 工程CMakeLists.txt

C#开源库ACadSharp读取dwg图元的示例

文章目录介绍数据示例读取图元属性介绍 开源库ACadSharp的地址&#xff1a;https://github.com/DomCR/ACadSharp 可以在NuGet中搜索到该库并安装。 数据示例 数据是一个绘制了以下简单图元的dwg数据&#xff1a; 读取图元属性 创建了.net6控制台项目&#xff0c;通过NuG…

【UniApp打包鸿蒙APP全流程】如何配置并添加UniApp API所需的鸿蒙系统权限

一、前言&#xff1a;为什么选择 UniApp 打包鸿蒙应用&#xff1f; 随着鸿蒙生态的快速发展&#xff0c;越来越多开发者希望将现有跨平台项目快速接入鸿蒙系统。而 UniApp 作为国内领先的跨平台开发框架&#xff0c;凭借其“一次开发&#xff0c;多端发布”的特性&#xff0c;…

STM32-FreeRTOS快速入门指南(下)

第十一章 FreeRTOS事件标志组 1. 事件标志组简介 事件标志组与信号量一样属于任务间同步的机制&#xff0c;但是信号量一般用于任务间的单事件同步&#xff0c;对于任务间的多事件同步&#xff0c;仅使用信号量就显得力不从心了。 FreeRTOS 提供的事件标志组可以很好的处理多事…

KTH7812磁编码器芯片完全支持ABZ和UVW输出模式

KTH7812磁编码器芯片完全支持ABZ和UVW输出模式&#xff0c;具体功能细节如下&#xff1a;&#x1f527; 1. ABZ输出特性 分辨率可编程&#xff1a;支持 4~4096步/圈&#xff08;对应1~1024个脉冲周期/圈&#xff09;&#xff0c;用户可通过配置寄存器自定义分辨率。 输出频率…

Android为ijkplayer设置音频发音类型usage

官方文档 多区音频路由 | Android Open Source Projecthttps://source.android.google.cn/docs/automotive/audio/audio-multizone-routing?hlzh-cn 背景 车机系统开发多分区&#xff08;zone&#xff09;功能&#xff0c;可以实现同一个app通过设置&#xff0c;在不同分…

C++ 循环:从入门到精通的深度解析

《C++ 循环:从入门到精通的深度解析》 目录 循环的本质与编程价值 三大基础循环结构详解 循环控制语句:break与continue的魔法 嵌套循环:构建复杂逻辑的基石 现代C++循环特性(C++11+) 循环性能优化与常见陷阱 实战案例:算法与工程中的循环应用 面试题深度解析与编程技巧…

| `cat /etc/os-release` | 发行版详细信息(如 Ubuntu、CentOS) |

在 Linux 或类 Unix 系统中&#xff0c;最简洁的命令查看操作系统类型是&#xff1a; uname -s✅ 输出示例&#xff1a; LinuxDarwin&#xff08;macOS&#xff09;FreeBSD 等&#x1f50d; 说明&#xff1a; uname&#xff1a;显示系统信息-s&#xff1a;仅显示操作系统内核名…

Maya 3D建模:点、线、面、创建多边面

目录 一 点、线、面 二 创建多边面 一 点、线、面 鼠标放在模型上 按住鼠标右键&#xff1a;就可以选择点 线 面 shift 加选点线面 ctrl 减选点线面 顶点面&#xff1a;是一个检查模式&#xff0c;观察有无错误 选择面&#xff0c;单击一个面&#xff0c;按住shift键 同时…

CXR-LT 2024:一场关于基于胸部X线的长尾、多标签和零样本疾病分类的MICCAI挑战赛|文献速递-深度学习人工智能医疗图像

Title题目CXR-LT 2024: A MICCAI challenge on long-tailed, multi-label, and zero-shotdisease classification from chest X-rayCXR-LT 2024&#xff1a;一场关于基于胸部X线的长尾、多标签和零样本疾病分类的MICCAI挑战赛01文献速递介绍CXR-LT系列是一项由社区推动的计划&a…

拆解本地组策略编辑器 (gpedit.msc) 的界面和功能

我们来详细拆解本地组策略编辑器 (gpedit.msc) 的界面和功能。打开后,你会看到一个标准的微软管理控制台 (MMC) 窗口,主要分为三个部分。 这是一个典型的本地组策略编辑器界面,我们将其分为三个主要部分进行讲解: +-----------------------------------------------+----…

[NCTF2019]True XML cookbook

TRY 尝试XML外部实体注入 <?xml version"1.0" encoding"utf-8" ?> <!DOCTYPE user[<!ENTITY flag SYSTEM "file://./doLogin.php"> ]> <user><username> &flag; </username><password>1</pa…