66、神经网络的定义网络结构【用Python进行AI数据分析进阶教程】

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

用Python进行AI数据分析进阶教程66:

神经网络的定义网络结构


关键词:输入层、隐藏层、输出层、PyTorch、全连接层

摘要:本文主要介绍了如何使用 PyTorch 定义神经网络的结构,包括输入层、隐藏层和输出层的功能与实现方法。输入层的神经元数量需与数据特征匹配,隐藏层通过激活函数进行非线性变换以提升模型表达能力,输出层则根据任务类型(如分类或回归)选择合适的激活函数,例如 Softmax 用于多分类问题。文章还展示了如何构建一个完整的神经网络类,封装各层及前向传播逻辑,并对关键代码语句进行了详细解读,帮助读者理解神经网络的基本构成和工作流程。

👉 欢迎订阅🔗
《用Python进行AI数据分析进阶教程》专栏
《AI大模型应用实践进阶教程》专栏
《Python编程知识集锦》专栏
《字节跳动旗下AI制作抖音视频》专栏
《智能辅助驾驶》专栏
《工具软件及IT技术集锦》专栏


一、整体概述

在 Python 中,通常使用深度学习框架(如PyTorchTensorFlow)来定义和训练神经网络。下面会以PyTorch为例,详细讲解神经网络各层结构的定义、关键点、注意点,给出示例代码并解读重点语句。

二、输入层

1、关键点

输入层是神经网络接收原始数据的地方,其神经元数量应与输入数据的特征数量一致。比如,处理手写数字识别问题,每个图像是 28x28 像素,将其展平为一维向量后,输入层就需要有 28 * 28 = 784 个神经元。

2、注意点

  • 要保证输入数据的维度和输入层神经元数量匹配,否则会引发维度不匹配的错误。
  • 对于不同类型的数据(如文本、图像、音频),需要进行合适的预处理,以使其能作为输入层的有效输入。

3、示例代码

Python脚本

# 导入必要的库
import torch
import torch.nn as nn

def create_sample_data(batch_size=1, height=28, width=28):
    """
    创建示例输入数据
    
    Args:
        batch_size (int): 批次大小
        height (int): 图像高度
        width (int): 图像宽度
    
    Returns:
        torch.Tensor: 展平后的输入数据张量,形状为(batch_size, height*width)
    """
    input_size = height * width
    # 生成随机输入数据,模拟展平后的图像数据
    input_data = torch.randn(batch_size, input_size)
    return input_data, input_size

def main():
    """主函数"""
    try:
        # 设置随机种子以确保结果可重现(可选)
        torch.manual_seed(42)
        
        # 定义输入数据的维度
        BATCH_SIZE = 1
        IMAGE_HEIGHT = 28
        IMAGE_WIDTH = 28
        
        # 创建输入数据
        input_data, input_size = create_sample_data(BATCH_SIZE, 
                                          IMAGE_HEIGHT, 
                                          IMAGE_WIDTH)
        
        # 打印相关信息
        print(f"输入数据形状: {input_data.shape}")
        print(f"输入数据特征数量: {input_size}")
        print("输入数据样本:")
        print(input_data)
        
        # 可选:打印一些统计信息
        print(f"\n数据统计信息:")
        print(f"均值: {input_data.mean().item():.4f}")
        print(f"标准差: {input_data.std().item():.4f}")
        print(f"最小值: {input_data.min().item():.4f}")
        print(f"最大值: {input_data.max().item():.4f}")
        
    except Exception as e:
        print(f"发生错误: {e}")
        return None
    
    return input_data

# 如果直接运行此脚本,则执行main函数
if __name__ == "__main__":
    data = main()

三、隐藏层

1、关键点

  • 隐藏层位于输入层和输出层之间,可以有一层或多层。每一层隐藏层通过对输入数据进行非线性变换,学习数据中的复杂模式。
  • 隐藏层的层数和每层的神经元数量是超参数,需要根据具体问题进行调整。增加隐藏层数量和神经元数量可以提高模型的表达能力,但也可能导致过拟合。

2、注意点

  • 激活函数的选择很重要,它能为网络引入非线性,常用的激活函数有 ReLU、Sigmoid、Tanh 等。
  • 每层隐藏层的输入和输出维度要匹配,确保数据能在网络中顺利流动。

3、示例代码

Python脚本

import torch
import torch.nn as nn

# 定义输入层和隐藏层的神经元数量
# 这些值都是超参数,需要根据具体问题进行调整
input_size = 784  # 例如:MNIST图像的像素数 (28*28)
hidden_size = 128  # 隐藏层神经元数量

# 创建一个全连接层作为隐藏层
# nn.Linear是PyTorch中用于创建全连接层的类
# input_size是输入层的神经元数量,也就是输入数据的特征数量
# hidden_size是隐藏层的神经元数量
# 该层会对输入数据进行线性变换,将输入数据从input_size维映射到hidden_size维
hidden_layer = nn.Linear(input_size, hidden_size)

# 应用激活函数,这里使用ReLU
# ReLU(Rectified Linear Unit)是一种常用的激活函数,其公式为 f(x) = max(0, x)
# 它可以为神经网络引入非线性,增强模型的表达能力
activation = nn.ReLU()

# 创建示例输入数据
# 假设我们有一个批次大小为1的样本,每个样本有input_size个特征
input_data = torch.randn(1, input_size)  # 生成随机输入数据用于演示

# 前向传播
# 首先将输入数据input_data传入隐藏层hidden_layer进行线性变换
# 然后将线性变换的结果传入激活函数activation进行非线性变换
# 最终得到隐藏层的输出hidden_output
hidden_output = activation(hidden_layer(input_data))

# 打印隐藏层的输出
print("隐藏层输出形状:", hidden_output.shape)
print("隐藏层输出:", hidden_output)

# 输出结果说明:
# 输出一个形状为(1, hidden_size)的张量,
# 其中每个元素都是经过ReLU激活函数处理后的值
# 由于ReLU的特性,输出值要么是0,要么是正数
# 示例输出(实际值会因随机性而不同):
# 隐藏层输出形状: torch.Size([1, 128])
# 隐藏层输出: 
# tensor([[0.0000, 0.0000, 0.1234, ..., 0.5678, 0.0000, 0.0000]], 
#       grad_fn=<ReluBackward0>)

四、输出层

1、关键点

  • 输出层的神经元数量取决于具体的任务。例如,在二分类问题中,输出层通常有 1 个神经元;在多分类问题中,输出层的神经元数量等于类别数。

2、注意点

  • 对于分类问题,输出层通常需要搭配合适的激活函数,如 Sigmoid 用于二分类,Softmax 用于多分类。
  • 对于回归问题,输出层一般不需要激活函数,直接输出连续值。

3、示例代码(多分类问题)

Python脚本

import torch
import torch.nn as nn

# 假设是10分类问题
# 定义输出层的神经元数量,由于是10分类问题,所以输出层要有10个神经元对应10个类别
output_size = 10

# 创建输出层
# 使用nn.Linear类创建一个全连接层作为输出层
# 该层接收隐藏层的输出,将隐藏层的hidden_size个神经元连接到输出层的output_size个神经元
# 会对隐藏层的输出进行线性变换,得到每个类别的得分
output_layer = nn.Linear(hidden_size, output_size)

# 方法1:显式使用Softmax(适用于需要概率输出的场景)
# Softmax函数用于将线性输出转换为概率分布,使得所有输出值之和为1
# dim=1表示在第1维(即类别维度)上进行Softmax操作,确保每行的元素之和为1
softmax = nn.Softmax(dim=1)

# 前向传播得到最终输出
# 先将隐藏层的输出hidden_output传入输出层output_layer进行线性变换
# 然后将线性变换的结果传入Softmax激活函数,得到每个类别的概率值
output_prob = softmax(output_layer(hidden_output))
print("概率输出:", output_prob)

# 方法2:推荐的优化方式 - 直接返回线性输出(训练时)或使用LogSoftmax(数值稳定性更好)
# 在实际训练中,通常直接返回线性输出给损失函数(如CrossEntropyLoss)
# 因为CrossEntropyLoss内部已经包含了LogSoftmax操作
raw_output = output_layer(hidden_output)
print("原始线性输出:", raw_output)

# 如果需要概率输出,也可以这样写(更简洁)
output_prob_direct = torch.softmax(raw_output, dim=1)
print("直接使用torch.softmax:", output_prob_direct)

# 验证概率和为1
print("概率之和:", torch.sum(output_prob_direct, dim=1))

# 如果用于训练,推荐使用LogSoftmax + NLLLoss 或直接使用CrossEntropyLoss
log_softmax = nn.LogSoftmax(dim=1)
log_probs = log_softmax(output_layer(hidden_output))
print("对数概率输出:", log_probs)

五、完整的神经网络类定义

将上述各层组合起来,定义一个完整的神经网络类。

Python脚本

# 导入PyTorch核心库
import torch
import torch.nn as nn

# 定义一个简单的神经网络类
class SimpleNeuralNetwork(nn.Module):
    def __init__(self, input_size: int, hidden_size: int, output_size: int):
        """
        初始化神经网络结构。
        
        参数:
            input_size (int): 输入特征维度(如28*28=784)
            hidden_size (int): 隐藏层神经元数量
            output_size (int): 输出类别数(如10类)
        """
        super().__init__()  # 简化写法,适用于Python 3+

        # 全连接层 + 激活函数
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(hidden_size, output_size)
        # 注意:Softmax通常不在模型中显式使用,尤其当使用CrossEntropyLoss时

    def forward(self, x):
        """
        前向传播过程。
        
        参数:
            x (Tensor): 输入张量,形状为 (batch_size, input_size)
            
        返回:
            Tensor: 输出张量,形状为 (batch_size, output_size)
        """
        out = self.fc1(x)
        out = self.relu(out)
        out = self.fc2(out)
        # 不加 softmax,交由损失函数处理(如 CrossEntropyLoss)
        return out

# 设置参数
input_size = 28 * 28  # MNIST 图像大小
hidden_size = 128     # 隐藏层大小
output_size = 10      # 分类数(0~9)

# 创建网络实例
net = SimpleNeuralNetwork(input_size, hidden_size, output_size)

# 创建一个模拟输入(batch_size=1)
input_data = torch.randn(1, input_size)

# 前向传播
output = net(input_data)

# 打印输出结果(logits)
print("模型输出(logits):", output)

# 如果你想查看概率分布(仅用于推理/可视化),可以手动加 softmax:
probabilities = torch.softmax(output, dim=1)
print("Softmax 概率分布:", probabilities)
 

 说明与建议:

  • 如果你后续使用 nn.CrossEntropyLoss(),那么模型输出不应该包含 Softmax。
  • 如果你只是做推理或者可视化,可以手动调用 torch.softmax()。
  • 这样做的好处是避免数值不稳定(比如 log(0)),因为 CrossEntropyLoss 内部已经高效地处理了这些。 

重点语句解读

  • class SimpleNeuralNetwork(nn.Module)定义了一个名为SimpleNeuralNetwork的神经网络类,继承自nn.Module,这是PyTorch中所有神经网络模块的基类。
  • super(SimpleNeuralNetwork, self).__init__()调用父类nn.Module的构造函数,确保正确初始化。
  • self.fc1 = nn.Linear(input_size, hidden_size)创建一个全连接层,将输入层的input_size个神经元连接到隐藏层的hidden_size个神经元。
  • self.relu = nn.ReLU()定义 ReLU 激活函数,为网络引入非线性。
  • self.fc2 = nn.Linear(hidden_size, output_size)创建另一个全连接层,将隐藏层的hidden_size个神经元连接到输出层的output_size个神经元。
  • self.softmax = nn.Softmax(dim=1)定义 Softmax 激活函数,用于多分类问题,dim=1表示在第 1 维(通常是类别维度)上进行 Softmax 操作。
  • def forward(self, x)定义前向传播函数,描述数据在网络中的流动过程。
  • out = self.fc1(x)将输入数据x通过第一个全连接层。
  • out = self.relu(out)对第一个全连接层的输出应用 ReLU 激活函数。
  • out = self.fc2(out)将经过激活函数处理后的数据通过第二个全连接层。
  • out = self.softmax(out)对第二个全连接层的输出应用 Softmax 激活函数,得到最终的概率分布。

——The END——


🔗 欢迎订阅专栏

序号专栏名称说明
1用Python进行AI数据分析进阶教程《用Python进行AI数据分析进阶教程》专栏
2AI大模型应用实践进阶教程《AI大模型应用实践进阶教程》专栏
3Python编程知识集锦《Python编程知识集锦》专栏
4字节跳动旗下AI制作抖音视频《字节跳动旗下AI制作抖音视频》专栏
5智能辅助驾驶《智能辅助驾驶》专栏
6工具软件及IT技术集锦《工具软件及IT技术集锦》专栏

👉 关注我 @理工男大辉郎 获取实时更新

欢迎关注、收藏或转发。
敬请关注 我的
微信搜索公众号:cnFuJH
优快云博客:理工男大辉郎
抖音号:31580422589

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

理工男大辉郎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值