【AI】一文带你掌握人工智能&深度学习&Pytorch

目录

人工智能应用分支

1. 计算机视觉(Computer Vision)

2. 自然语言处理(Natural Language Processing, NLP)

3. 语音识别与合成(Speech Recognition and Synthesis)

4. 推荐系统(Recommendation Systems)

5. 机器人与自动化(Robotics and Automation)

6. 专家系统与决策支持(Expert Systems and Decision Support)

7. 智能控制与自动化系统(Intelligent Control and Automation Systems)

人工智能学习方式

1. 深度学习(Deep Learning)

2. 机器学习(Machine Learning)

深度学习与机器学习的关系

深度学习和机器学习与其他学习方式的关系

Pytorch相关

Dataset&DataLoader

1. Dataset

1.1 Dataset 的基本用法

1.2 示例:创建一个简单的自定义数据集

2. DataLoader

2.1 DataLoader 的基本用法

2.2 示例:使用 DataLoader 加载自定义数据集

3. Dataset 和 DataLoader 的关系

4. 实际应用中的使用场景

Transforms

1. 使用 Transforms

1.1 基本用法

2. 常用的 Transforms

2.1 尺寸调整与裁剪

2.2 旋转与翻转

2.3 颜色调整

2.4 数据格式转换

2.5 合成与增强

3. 自定义 Transform

3.1 创建自定义 Transform

torchvision中数据集使用

1. 加载数据集

1.1 示例:加载 CIFAR-10 数据集

神经网络

1. nn.Module 的基本使用

1.1 创建自定义神经网络

2. 卷积层 (nn.Conv2d)

2.1 卷积层的定义

2.2 卷积层的使用示例

3. 池化层 (nn.MaxPool2d 和 nn.AvgPool2d)

3.1 最大池化层 (nn.MaxPool2d)

3.2 平均池化层 (nn.AvgPool2d)

4. 非线性激活层

4.1 ReLU 激活 (nn.ReLU)

4.2 Sigmoid 激活 (nn.Sigmoid)

4.3 Tanh 激活 (nn.Tanh)

5. 线性层 (nn.Linear)

5.1 线性层的定义

6. Sequential 容器

6.1 使用 Sequential 构建简单模型

损失函数&反向传播

1. 损失函数(Loss Function)

1.1 概述

1.2 常用的损失函数

2. 反向传播(Backpropagation)

2.1 概述

2.2 反向传播的过程

2.3 反向传播的使用示例

3.损失函数和反向传播的联系

优化器

1. 什么是优化器?

2. 常见的优化器

2.1 随机梯度下降(SGD)

2.2 动量优化(Momentum)

2.3 自适应学习率优化(AdaGrad)

2.4 RMSProp

2.5 Adam(Adaptive Moment Estimation)

2.6 AdamW

3. 优化器的使用方法

4. 如何选择合适的优化器

现有网络模型的使用&修改&保存

1. 使用预训练模型

1.1 加载预训练模型

1.2 模型推理

2. 微调预训练模型

2.1 修改模型的全连接层

2.2 只训练部分层

2.3 微调模型

3. 修改网络结构

3.1 替换网络的部分层

3.2 添加新的层

4. 模型保存与加载

4.1 保存模型

4.2 加载模型

用GPU训练

1. 检查 GPU 是否可用

2. 将模型和数据移到 GPU

2.1 将模型移动到 GPU

2.2 将数据移动到 GPU

完整的模型训练&模型验证套路

1. 完整的模型训练套路

2. 完整的模型验证套路

3. 总结与注意事项


人工智能应用分支

1. 计算机视觉(Computer Vision)

  • 应用领域
    • 人脸识别:广泛应用于安防系统、社交媒体自动标记、手机解锁等。
    • 自动驾驶:计算机视觉用于识别道路标志、行人、车辆等,实现车辆的自动驾驶和导航。
    • 医疗影像分析:帮助医生分析X光片、MRI和CT扫描,辅助诊断疾病。
    • 工业自动化:在制造业中用于产品质量检测、缺陷识别等。

2. 自然语言处理(Natural Language Processing, NLP)

  • 应用领域
    • 智能助手和聊天机器人:如Siri、Alexa、Google Assistant,帮助用户完成任务、提供信息。
    • 机器翻译:如Google Translate,用于将文本从一种语言翻译到另一种语言。
    • 情感分析:分析社交媒体、客户评论等文本,帮助企业了解客户的情感倾向。
    • 文本摘要:自动生成文档、文章的简要摘要,应用于新闻报道、文档管理等。

3. 语音识别与合成(Speech Recognition and Synthesis)

  • 应用领域
    • 语音助手:如Google Assistant、Amazon Alexa,用于语音命令识别和执行。
    • 语音到文本:在打字困难或不便时将语音转换为文本,应用于笔记记录、语音输入法等。
    • 语音合成:生成自然的语音,如为盲人提供语音提示、自动生成客服系统的语音应答。

4. 推荐系统(Recommendation Systems)

  • 应用领域
    • 电子商务:如Amazon、淘宝等,根据用户的浏览和购买历史,推荐相关产品。
    • 流媒体平台:如Netflix、Spotify,根据用户的观看或收听记录,推荐电影、音乐等内容。
    • 社交媒体:如Facebook、Instagram,推荐朋友、内容或广告。

5. 机器人与自动化(Robotics and Automation)

  • 应用领域
    • 工业机器人:用于制造业的自动化生产,如装配、焊接、搬运等。
    • 服务机器人:如送餐机器人、清扫机器人,在酒店、餐馆、家居中应用。
    • 医用机器人:如达芬奇手术机器人,辅助医生进行精细的外科手术。
    • 无人驾驶技术:如无人驾驶汽车、无人机,用于运输、物流、测绘等领域。

6. 专家系统与决策支持(Expert Systems and Decision Support)

  • 应用领域
    • 医疗诊断:如IBM Watson,帮助医生诊断疾病、推荐治疗方案。
    • 金融分析:用于投资决策、风险评估、欺诈检测等。
    • 法律分析:帮助律师分析案件、进行法律推理和文档生成。

7. 智能控制与自动化系统(Intelligent Control and Automation Systems)

  • 应用领域
    • 智能家居:如智能恒温器、智能灯光控制系统,提升家居生活的便利性和节能性。
    • 能源管理系统:优化能源使用,提高能源效率,应用于智能电网、工厂自动化等。
    • 自动化物流:如自动化仓库、配送机器人,提升物流效率和准确性。

人工智能学习方式

1. 深度学习(Deep Learning)

概述

  • 深度学习是机器学习的一个子领域,使用多层神经网络来自动学习数据的特征和模式。它特别擅长处理复杂和高维度的数据,如图像、语音、文本等。
  • 深度神经网络(DNN):深度学习的核心是由多个隐藏层组成的深度神经网络,这些网络能够通过层层抽象,提取数据中的高层次特征。
  • 关键技术
    • 卷积神经网络(CNN):主要用于图像处理任务,如图像分类、目标检测、图像分割。
    • 递归神经网络(RNN):用于处理序列数据,如自然语言处理、时间序列预测。
    • 生成对抗网络(GAN):用于生成数据,如图像生成、风格转换。
    • 自编码器(Autoencoder):用于数据降维、特征提取和生成任务。

应用场景

  • 图像识别:人脸识别、自动驾驶中的物体识别。
  • 自然语言处理:机器翻译、文本生成、情感分析。
  • 语音识别:语音转文本、语音合成。

2. 机器学习(Machine Learning)

概述

  • 机器学习是人工智能的一个广泛领域,涵盖了从数据中自动学习和预测的算法和模型。它包括传统的统计学习方法以及更复杂的算法。
  • 核心思想:机器学习通过数据训练模型,使模型能够在没有显式编程的情况下,进行预测或决策。
  • 关键技术
    • 线性回归和逻辑回归:用于回归和二分类问题。
    • 决策树和随机森林:用于分类和回归任务。
    • 支持向量机(SVM):用于分类、回归和异常检测。
    • 聚类算法(如K-means):用于无监督学习中的数据聚类。

应用场景

  • 金融预测:股票价格预测、信用评分。
  • 市场营销:客户细分、推荐系统。
  • 医疗诊断:疾病预测、医学影像分析。

深度学习与机器学习的关系

  • 层次关系:深度学习是机器学习的一个子领域。机器学习包含了传统的统计方法和各种算法,而深度学习则专注于使用深度神经网络来处理更复杂的数据和任务。
  • 数据和计算需求:深度学习通常需要大量的数据和强大的计算资源,因为它依赖于训练深层的神经网络模型。而传统的机器学习算法,如线性回归、决策树等,通常可以在较少数据和计算资源的情况下有效运行。
  • 应用范围:深度学习在处理复杂模式识别任务(如图像和语音识别)方面表现尤为出色,而传统的机器学习算法在结构化数据的处理和中小型数据集上通常表现更佳。

深度学习和机器学习与其他学习方式的关系

  • 与监督学习的关系:深度学习和许多机器学习算法都可以应用于监督学习中。深度学习特别适合处理需要自动特征提取的大规模数据,而传统机器学习方法则依赖于手工特征工程。
  • 与无监督学习的关系:无监督学习可以使用深度学习技术(如自编码器、生成对抗网络)来提取数据特征或生成数据。机器学习中的聚类算法也是无监督学习的一种实现。
  • 与强化学习的关系:强化学习可以结合深度学习形成深度强化学习(Deep Reinforcement Learning),这使得智能体能够处理复杂的决策和控制问题。传统的机器学习方法通常不直接应用于强化学习,但可以用于策略初始化或特征提取。
  • 与自监督学习的关系:自监督学习大量依赖深度学习技术来从未标注数据中自动生成监督信号。这使得深度学习模型能够在数据稀缺的情况下仍然进行有效的训练。传统的机器学习方法通常不用于自监督学习,但可以受益于自监督学习生成的特征。

总结而言,深度学习是机器学习的一个分支,二者之间存在紧密的联系。深度学习专注于使用深层神经网络处理复杂的任务,而机器学习则涵盖了更广泛的算法和技术。它们都可以与不同的学习方式结合,解决多种实际问题。

Pytorch相关

PyTorch 是一个广泛使用的开源深度学习框架,由 Facebook 的人工智能研究团队开发。它以灵活的设计、动态计算图、易用的 API 以及对 GPU 加速的良好支持而著称,深受研究人员和开发者的喜爱。

Dataset&DataLoader

在 PyTorch 中,DatasetDataLoader 是数据处理和加载的重要工具。它们一起工作,用于高效地管理和处理大型数据集,为模型训练提供批量数据。以下是对它们的详细介绍:

1. Dataset

Dataset 是一个抽象类,用户可以通过继承它来自定义自己的数据集。它定义了数据集的基本结构,使得数据可以以统一的方式被加载和处理。

1.1 Dataset 的基本用法
  • 创建自定义数据集: 要创建一个自定义数据集,需要继承 torch.utils.data.Dataset 类,并实现两个方法:
    • __len__():返回数据集中样本的数量。
    • __getitem__():根据索引返回数据集中的一个样本和其对应的标签。
1.2 示例:创建一个简单的自定义数据集
import torch
from torch.utils.data import Dataset

class CustomDataset(Dataset):
    def __init__(self, transform=None):
        # 初始化数据集,这里可以进行数据加载或其他准备工作
        self.data = torch.rand(100, 4)  # 100个样本,每个样本4个特征
        self.labels = torch.randint(0, 2, (100,))  # 100个样本的标签,0或1
        self.transform = transform

    def __len__(self):
        # 返回数据集的总样本数量
        return len(self.data)

    def __getitem__(self, idx):
        # 根据索引idx返回一个样本和对应的标签
        sample = self.data[idx]
        label = self.labels[idx]

        if self.transform:
            sample = self.transform(sample)  # 如果指定了transform,则对样本进行预处理

        return sample, label
  • 参数说明

    • __init__: 用于初始化数据集。在此处可以进行数据加载、预处理步骤的定义等。
    • __len__: 返回数据集的总长度,使得我们可以用 len(dataset) 来获取数据集的大小。
    • __getitem__: 使得数据集可以通过索引访问,返回的通常是一个样本及其对应的标签。
  • 使用transform

    • transform 参数通常用于数据预处理,如归一化、数据增强等。可以在初始化 Dataset 时传入预处理函数。

2. DataLoader

DataLoader 是 PyTorch 中用于加载数据集的工具,能够自动地对数据进行批处理、打乱、并行处理等操作。它可以将 Dataset 中的数据打包成小批量(mini-batch),并在训练过程中逐批提供给模型。

2.1 DataLoader 的基本用法
  • 创建 DataLoader: 通过 torch.utils.data.DataLoader 类来创建数据加载器。常用参数包括:
    • dataset: 数据源,通常是自定义的 Dataset 对象。
    • batch_size: 每个批次的样本数。
    • shuffle: 是否在每个 epoch 重新打乱数据。
    • num_workers: 使用多少个子进程来加载数据。默认为 0,表示数据将在主进程中加载。
2.2 示例:使用 DataLoader 加载自定义数据集
from torch.utils.data import DataLoader

# 创建自定义数据集的实例
dataset = CustomDataset()

# 创建DataLoader
dataloader = DataLoader(dataset, batch_size=10, shuffle=True, num_workers=2)

# 迭代DataLoader
for data, labels in dataloader:
    # 在这里进行训练或推理
    print(data, labels)

参数说明

  • batch_size: 定义每个批次的样本数量。如果数据集有 1000 个样本,batch_size=32 则意味着每个 epoch 需要运行 1000/32 个批次。
  • shuffle: 如果设置为 True,每个 epoch 都会打乱数据,有助于防止模型过拟合。
  • num_workers: 定义加载数据时使用的子进程数量。num_workers > 0 可以加速数据加载,特别是当数据集较大时。

3. Dataset 和 DataLoader 的关系

  • Dataset 是数据的源头,负责提供数据的访问接口。而 DataLoader 则负责如何有效地从 Dataset 中取出数据,打包成批次,并在训练或推理时按需提供。
  • DataLoader 的核心是 Dataset,它调用 Dataset__getitem__ 方法获取数据,然后根据 batch_sizeshuffle 等参数进行批次处理和打乱等操作。

4. 实际应用中的使用场景

  • 批量处理:在训练深度学习模型时,一般不会一次性将所有数据送入模型,而是分成小批量,以减少内存使用并加速训练。
  • 数据增强:通过 transform,可以在 Dataset 中对数据进行实时增强(如随机裁剪、旋转等),这种操作通常在数据加载过程中完成,而不会将增强后的数据保存在磁盘。
  • 并行数据加载:对于大型数据集,通过 num_workers 参数可以并行地加载数据,加速训练过程。

Transforms

在 PyTorch 中,Transforms 是用于对图像或其他数据类型进行预处理和数据增强的工具。它们主要用于 torchvision 库中,用于处理图像数据,特别是在训练深度学习模型时对数据进行标准化、归一化、裁剪、旋转等操作。Transforms 使得数据预处理过程变得简单且模块化。

1. 使用 Transforms

Transforms 通常在加载数据时与 torchvision.datasetstorch.utils.data.DataLoader 一起使用。通过定义一组变换,然后将这些变换应用于数据集中的每个样本。

1.1 基本用法
  • 定义一个 Transform 列表
    • 通过 transforms.Compose() 来组合多个变换,这样它们会按照定义的顺序逐一应用于数据。
from torchvision import transforms

# 定义一组变换
transform = transforms.Compose([
    transforms.Resize((256, 256)),  # 调整图像大小
    transforms.RandomHorizontalFlip(),  # 随机水平翻转
    transforms.ToTensor(),  # 转换为张量
    transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])  # 标准化
])

应用 Transforms 到数据集

  • 在创建数据集时,将定义好的 transform 传递给数据集的 transform 参数。
from torchvision.datasets import CIFAR10

# 下载并应用变换到 CIFAR-10 数据集
dataset = CIFAR10(root='./data', train=True, download=True, transform=transform)

2. 常用的 Transforms

PyTorch 的 torchvision.transforms 模块中包含了许多常用的变换。下面介绍一些最常用的变换及其用途:

2.1 尺寸调整与裁剪
  • transforms.Resize(size)

    • 作用:调整图像大小到指定的尺寸。
    • 示例:transforms.Resize((256, 256)) 将图像调整为 256x256 像素。
  • transforms.CenterCrop(size)

    • 作用:从图像的中心裁剪指定大小的区域。
    • 示例:transforms.CenterCrop(224) 将图像中心裁剪为 224x224。
  • transforms.RandomCrop(size)

    • 作用:随机裁剪图像的一部分。
    • 示例:transforms.RandomCrop(224) 随机裁剪图像的 224x224 区域。
2.2 旋转与翻转
  • transforms.RandomHorizontalFlip(p=0.5)

    • 作用:以指定概率水平翻转图像。
    • 示例:transforms.RandomHorizontalFlip() 以 50% 的概率水平翻转图像。
  • transforms.RandomVerticalFlip(p=0.5)

    • 作用:以指定概率垂直翻转图像。
    • 示例:transforms.RandomVerticalFlip() 以 50% 的概率垂直翻转图像。
  • transforms.RandomRotation(degrees)

    • 作用:随机旋转图像一定角度。
    • 示例:transforms.RandomRotation(30) 随机旋转图像在 -30 到 30 度之间。
2.3 颜色调整
  • transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0)

    • 作用:随机改变图像的亮度、对比度、饱和度和色调。
    • 示例:transforms.ColorJitter(brightness=0.5, contrast=0.5) 随机调整图像的亮度和对比度。
  • transforms.Grayscale(num_output_channels=1)

    • 作用:将图像转换为灰度图像。
    • 示例:transforms.Grayscale() 将图像转换为单通道灰度图。
2.4 数据格式转换
  • transforms.ToTensor()

    • 作用:将图像转换为 PyTorch 张量,并自动将像素值从 [0, 255] 范围归一化到 [0, 1]。
    • 示例:transforms.ToTensor()
  • transforms.Normalize(mean, std)

    • 作用:使用给定的均值和标准差对图像进行标准化。
    • 示例:transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]) 对 RGB 三个通道进行标准化。
  • transforms.Lambda(lambda_function)

    • 作用:应用一个自定义的 lambda 函数。
    • 示例:transforms.Lambda(lambda x: x * 2)
2.5 合成与增强
  • transforms.Compose(transforms_list)

    • 作用:将多个变换组合在一起。
    • 示例:transforms.Compose([transforms.Resize(256), transforms.ToTensor()])
  • transforms.RandomApply(transforms, p=0.5)

    • 作用:以指定概率随机应用一组变换。
    • 示例:transforms.RandomApply([transforms.ColorJitter()], p=0.8)
  • transforms.RandomChoice(transforms)

    • 作用:随机选择一个变换来应用。
    • 示例:transforms.RandomChoice([transforms.Grayscale(), transforms.ColorJitter()])

 

3. 自定义 Transform

有时内置的 Transforms 不足以满足需求,可以通过定义自定义的 Transform 来实现特定的预处理操作。

3.1 创建自定义 Transform
class CustomTransform:
    def __init__(self, factor):
        self.factor = factor

    def __call__(self, img):
        # 在这里对图像进行自定义处理
        return img * self.factor

# 使用自定义Transform
custom_transform = CustomTransform(factor=2)
transform = transforms.Compose([
    custom_transform,
    transforms.ToTensor()
])
  • __call__() 方法:自定义 Transform 需要实现 __call__() 方法,当 Transform 被调用时,这个方法将会执行。

通过使用 Transforms,你可以对数据进行丰富的预处理和增强,从而提高模型的鲁棒性和泛化能力。这些操作在图像处理任务中尤其重要,帮助模型更好地适应训练数据和测试数据的差异。

torchvision中数据集使用

torchvision 是 PyTorch 的一个子库,专注于计算机视觉任务。它提供了常见的图像数据集、模型结构和图像处理工具。使用 torchvision 中的数据集,可以方便地进行图像分类、检测、分割等任务。

1. 加载数据集

torchvision.datasets 模块中包含了许多常见的图像数据集,如 CIFAR-10、MNIST、ImageNet 等。这些数据集可以通过简单的代码来加载和使用。

1.1 示例:加载 CIFAR-10 数据集
import torch
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

# 定义数据预处理操作
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))  # 对 RGB 三个通道分别进行标准化
])

# 下载并加载 CIFAR-10 数据集
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)

# 使用 DataLoader 进行批量加载
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True, num_workers=2)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False, num_workers=2)

神经网络

1. nn.Module 的基本使用

1.1 创建自定义神经网络

要创建一个自定义的神经网络,需要继承 nn.Module 类,并在 __init__ 方法中定义网络的各个层,然后在 forward 方法中定义数据的前向传播流程。

import torch
import torch.nn as nn

# 定义一个简单的神经网络
class SimpleNet(nn.Module):
    def __init__(self):
        super(SimpleNet, self).__init__()
        # 定义网络层
        self.fc1 = nn.Linear(784, 128)  # 输入层到隐藏层
        self.relu = nn.ReLU()           # ReLU激活函数
        self.fc2 = nn.Linear(128, 10)   # 隐藏层到输出层

    def forward(self, x):
        # 定义前向传播
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

# 创建网络实例
model = SimpleNet()

# 打印网络结构
print(model)
  • __init__ 方法:定义模型的结构和各个层。nn.Module 子类的每个实例会自动注册 __init__ 方法中定义的所有 nn.Module 类型的子模块。
  • forward 方法:定义数据在网络中的前向传播方式。每次调用模型时(例如 model(input)),都会执行这个方法。

2. 卷积层 (nn.Conv2d)

卷积层在处理图像数据时非常常用。它能够有效提取图像的局部特征,如边缘、纹理等。

2.1 卷积层的定义
conv = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, stride=1, padding=1)
  • 参数
    • in_channels: 输入通道数(例如 RGB 图像为 3)。
    • out_channels: 卷积产生的输出通道数。
    • kernel_size: 卷积核的大小,可以是整数(如 3x3 卷积核)或元组。
    • stride: 卷积核移动的步幅。
    • padding: 输入张量的边缘扩展,常用于保持输入和输出的大小一致。
2.2 卷积层的使用示例
class ConvNet(nn.Module):
    def __init__(self):
        super(ConvNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, 1, 1)  # 输入3通道,输出16通道,3x3卷积,步幅1,填充1
        self.pool = nn.MaxPool2d(2, 2)  # 2x2的最大池化
        self.fc1 = nn.Linear(16 * 32 * 32, 128)  # 全连接层,将池化后的输出展平并连接到128个神经元
        self.fc2 = nn.Linear(128, 10)  # 输出10类

    def forward(self, x):
        x = self.pool(self.conv1(x))  # 卷积+池化
        x = x.view(-1, 16 * 32 * 32)  # 展平
        x = torch.relu(self.fc1(x))  # 全连接+ReLU激活
        x = self.fc2(x)  # 输出层
        return x

model = ConvNet()

3. 池化层 (nn.MaxPool2dnn.AvgPool2d)

池化层用于减小特征图的尺寸,从而减少参数量,防止过拟合,同时保留重要的特征。

3.1 最大池化层 (nn.MaxPool2d)
pool = nn.MaxPool2d(kernel_size=2, stride=2)
  • 参数
    • kernel_size: 池化窗口的大小。
    • stride: 窗口移动的步幅。
3.2 平均池化层 (nn.AvgPool2d)

与最大池化不同,平均池化取池化窗口内所有数值的平均值。

avg_pool = nn.AvgPool2d(kernel_size=2, stride=2)

4. 非线性激活层

非线性激活函数用于引入非线性,使神经网络能够学习复杂的模式和函数。常见的激活函数包括 ReLU、Sigmoid 和 Tanh。

4.1 ReLU 激活 (nn.ReLU)
relu = nn.ReLU()
4.2 Sigmoid 激活 (nn.Sigmoid)
sigmoid = nn.Sigmoid()
4.3 Tanh 激活 (nn.Tanh)
tanh = nn.Tanh()

5. 线性层 (nn.Linear)

线性层(全连接层)是将输入与权重矩阵相乘并加上偏置的线性变换。它是神经网络的基本构件,常用于最后的分类或回归任务。

5.1 线性层的定义
fc = nn.Linear(in_features=128, out_features=10)
  • 参数
    • in_features: 输入的特征数量。
    • out_features: 输出的特征数量。

6. Sequential 容器

nn.Sequential 是一种简单的方法来构建神经网络,它允许按顺序定义网络层,而不需要显式地定义 forward 方法。

6.1 使用 Sequential 构建简单模型
model = nn.Sequential(
    nn.Conv2d(3, 16, 3, 1, 1),  # 卷积层
    nn.ReLU(),                  # 激活层
    nn.MaxPool2d(2, 2),         # 池化层
    nn.Flatten(),               # 展平层
    nn.Linear(16 * 32 * 32, 128), # 全连接层
    nn.ReLU(),
    nn.Linear(128, 10)          # 输出层
)
  • 特点
    • Sequential 按照定义的顺序逐层应用。适合构建简单的线性网络结构,不适合复杂的前向传播逻辑。

损失函数&反向传播

1. 损失函数(Loss Function)

1.1 概述

损失函数是用于衡量模型的预测输出与实际目标之间差距的函数。它在神经网络的训练过程中起着至关重要的作用。通过计算损失值,我们可以知道模型在当前的训练状态下表现如何。

1.2 常用的损失函数
  1. 均方误差损失(MSE Loss)

    • 用途:用于回归任务,也就是预测连续值时使用。
    • 功能:它计算预测值和实际值之间的差异,并返回差异的平方平均值,以衡量模型的预测准确性。
  2. 交叉熵损失(Cross Entropy Loss)

    • 用途:主要用于分类任务,尤其是多分类问题中。
    • 功能:它将模型的输出(通常是概率分布)与目标类别进行比较,评估模型输出与实际类别的匹配程度。
  3. 二元交叉熵损失(Binary Cross Entropy Loss)

    • 用途:用于二分类任务,适用于只有两类输出的情况。
    • 功能:评估模型预测的概率与实际类别之间的差异,常用于逻辑回归和二元分类模型。
  4. 负对数似然损失(Negative Log-Likelihood Loss)

    • 用途:常与 log_softmax 函数结合使用,用于分类任务。
    • 功能:通过将模型的预测值与实际标签对比,计算出对数似然的负值来评估模型的性能。
  5. 自定义损失函数

    • 如果预定义的损失函数不适合你的任务,可以通过继承 torch.nn.Module 并重写 forward 方法来自定义损失函数。

2. 反向传播(Backpropagation)

2.1 概述

反向传播是神经网络训练中的一个关键过程,用于根据损失函数计算模型参数的梯度。通过这些梯度,模型可以更新其参数,从而减少损失函数的值,进而提高模型的性能。

2.2 反向传播的过程
  1. 前向传播

    • 数据通过神经网络,从输入层经过隐藏层到输出层,最终得到预测值。接着通过损失函数计算预测值与实际值之间的差距,即损失值。
  2. 计算梯度

    • 通过反向传播算法,计算损失函数相对于每个模型参数的梯度。这些梯度表明了损失函数值相对于每个参数的变化率。
  3. 反向传播

    • 使用 loss.backward() 命令执行反向传播,自动计算所有参数的梯度。
  4. 参数更新

    • 使用优化器(如 SGD、Adam)根据计算出的梯度更新模型的参数。更新参数的目的是最小化损失函数,从而提高模型的预测精度。
2.3 反向传播的使用示例
import torch
import torch.nn as nn
import torch.optim as optim

# 定义简单的线性模型
model = nn.Linear(10, 1)

# 定义损失函数和优化器
loss_fn = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 模拟输入和目标输出
input = torch.randn(32, 10)  # 批量大小为32,特征数为10
target = torch.randn(32, 1)

# 前向传播
output = model(input)
loss = loss_fn(output, target)

# 反向传播
optimizer.zero_grad()  # 清除之前的梯度
loss.backward()        # 计算当前梯度
optimizer.step()       # 更新模型参数

3.损失函数和反向传播的联系

  • 损失函数:是训练过程中的目标,定义了模型预测输出与实际输出之间的差异。
  • 反向传播:是通过损失函数计算模型参数梯度的过程,进而指导参数更新以减少损失。

优化器是神经网络训练中的关键组件,它用于根据损失函数的梯度更新模型的参数,从而使模型逐渐逼近最优状态。不同的优化器在处理梯度和更新参数的方式上有所不同,这会影响训练的速度、收敛的稳定性以及最终的模型性能。

优化器

1. 什么是优化器?

优化器是用于根据损失函数计算出的梯度来调整模型参数的算法。其目标是通过不断调整参数,最小化损失函数,从而优化模型的预测能力。在深度学习中,常用的优化算法基于梯度下降法。

2. 常见的优化器

2.1 随机梯度下降(SGD)
  • 概述

    • 随机梯度下降(Stochastic Gradient Descent, SGD)是最基本的优化算法之一。它通过每次使用一个或少量的训练样本计算梯度,并更新参数。
  • 特点

    • 简单易用,计算开销小。
    • 更新可能不够稳定,容易陷入局部最优。
  • 用法

optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
  • 参数

    • lr:学习率,决定每次参数更新的步长。
    • momentum:动量,帮助加速收敛,避免陷入局部最优。
2.2 动量优化(Momentum)
  • 概述

    • 动量优化是在 SGD 的基础上增加了动量项,模拟物体的惯性,使得参数更新的方向更稳定,减少震荡。
  • 特点

    • 更快的收敛速度,尤其在深度网络中表现更好。
    • 有助于跨越局部最优,趋向于全局最优。
  • 用法

optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
  • 参数

    • momentum:常设为0.9或0.99,表示前几次更新的动量贡献度。
2.3 自适应学习率优化(AdaGrad)
  • 概述

    • AdaGrad 是一种自适应学习率优化器,根据参数的历史梯度自动调整每个参数的学习率,使得训练更加稳定。
  • 特点

    • 对稀疏数据效果较好。
    • 缺点是学习率会随着训练过程不断减小,可能导致训练过早停止。
  • 用法

optimizer = torch.optim.Adagrad(model.parameters(), lr=0.01)
2.4 RMSProp
  • 概述

    • RMSProp 是对 AdaGrad 的改进,它通过引入滑动平均的方式,解决了学习率持续减小的问题,使得模型在训练后期仍然能够保持较好的学习效率。
  • 特点

    • 稳定性较好,适用于深度神经网络。
    • 在处理非平稳目标时效果尤为出色。
  • 用法

optimizer = torch.optim.RMSprop(model.parameters(), lr=0.001)
2.5 Adam(Adaptive Moment Estimation)
  • 概述

    • Adam 是目前最常用的优化器之一,结合了动量优化和 RMSProp 的优点。它不仅使用了梯度的动量,也引入了对梯度平方的加权平均,从而实现了自适应学习率的调整。
  • 特点

    • 收敛速度快,能有效处理稀疏梯度问题。
    • 广泛应用于各种深度学习任务。
  • 用法

optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
  • 参数

    • betas:两个系数分别控制动量项和梯度平方的加权平均。一般默认值 betas=(0.9, 0.999)
    • eps:数值稳定性参数,防止除零错误。
2.6 AdamW
  • 概述

    • AdamW 是 Adam 的一个变体,在计算权重更新时考虑了权重衰减(Weight Decay),更好地实现了正则化,有助于防止模型过拟合。
  • 用法

optimizer = torch.optim.AdamW(model.parameters(), lr=0.001, weight_decay=0.01)
  •  

    W(model.parameters(), lr=0.001, weight_decay=0.01)

  • 参数

    • weight_decay:权重衰减系数,控制正则化强度。

3. 优化器的使用方法

无论使用哪种优化器,基本使用步骤都是相似的:

  1. 初始化优化器

    • 通过 torch.optim 模块选择合适的优化器,并传入模型的参数和相关超参数。
  2. 清除梯度

    • 在每次反向传播之前,使用 optimizer.zero_grad() 清除上一轮的梯度。
  3. 计算梯度

    • 通过损失函数的 backward() 方法执行反向传播,计算梯度。
  4. 更新参数

    • 使用 optimizer.step() 更新模型参数。
# 示例代码
import torch.optim as optim

# 定义模型和损失函数
model = MyModel()
criterion = torch.nn.CrossEntropyLoss()

# 初始化优化器
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 训练循环
for epoch in range(epochs):
    for inputs, targets in dataloader:
        # 前向传播
        outputs = model(inputs)
        loss = criterion(outputs, targets)
        
        # 清零梯度
        optimizer.zero_grad()
        
        # 反向传播计算梯度
        loss.backward()
        
        # 更新模型参数
        optimizer.step()

4. 如何选择合适的优化器

  • 小型数据集或简单任务:SGD 通常就足够了,可以通过增加动量(Momentum)来加速收敛。
  • 稀疏数据:AdaGrad 或 RMSProp 适用于处理稀疏数据的任务。
  • 深度网络:Adam 或 AdamW 是更普遍的选择,因为它们结合了多种优化策略,提供了更稳定的性能。
  • 防止过拟合:考虑使用 AdamW 或在 SGD 中增加权重衰减(Weight Decay)。

现有网络模型的使用&修改&保存

在深度学习领域,torchvision 提供了许多预训练的模型,这些模型可以用于各种计算机视觉任务,如图像分类、目标检测和分割。使用这些预训练模型,可以显著减少训练时间,特别是当数据集较小时,可以通过微调(fine-tuning)来适应新的任务。下面详细介绍如何使用现有的网络模型,以及如何对它们进行修改以适应特定任务。

1. 使用预训练模型

torchvision.models 提供了许多预训练的经典网络模型,如 ResNet、VGG、AlexNet 等。这些模型已经在大规模数据集(如 ImageNet)上进行过训练,用户可以直接使用这些模型进行推理或进一步微调。

1.1 加载预训练模型

以 ResNet-18 为例,以下是加载预训练模型的步骤:

import torch
import torchvision.models as models

# 加载预训练的 ResNet-18 模型
model = models.resnet18(pretrained=True)
  • pretrained=True:表示加载预训练权重。如果设为 False,则加载未训练的模型,所有参数将随机初始化。
1.2 模型推理

加载模型后,可以直接使用它进行推理(推断),即对新的图像进行预测:

from torchvision import transforms
from PIL import Image

# 加载图像并进行预处理
image = Image.open("path_to_image.jpg")
transform = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

image = transform(image).unsqueeze(0)  # 添加批次维度

# 推理
model.eval()  # 切换到评估模式
output = model(image)
_, predicted_class = torch.max(output, 1)

2. 微调预训练模型

微调是指在预训练模型的基础上,对某些层进行训练,以适应新的数据集和任务。通常做法是保留模型的大部分参数,只更新最后几层的参数。

2.1 修改模型的全连接层

以 ResNet-18 为例,假设我们要将模型的输出类别从原来的 1000 类(ImageNet)改为新的 10 类:

# 修改最后的全连接层
model.fc = torch.nn.Linear(model.fc.in_features, 10)
  • model.fc.in_features:获取原始全连接层的输入特征数。
  • torch.nn.Linear:创建一个新的全连接层,输出维度为 10(新的类别数)。
2.2 只训练部分层

为了加速训练并避免过拟合,通常只训练模型的部分层,而冻结其余层的参数:

# 冻结模型的所有参数
for param in model.parameters():
    param.requires_grad = False

# 只训练最后的全连接层
model.fc = torch.nn.Linear(model.fc.in_features, 10)

# 设置新的全连接层的 requires_grad 为 True
for param in model.fc.parameters():
    param.requires_grad = True
2.3 微调模型
import torch.optim as optim

# 定义损失函数和优化器
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.fc.parameters(), lr=0.001, momentum=0.9)

# 训练模型
model.train()  # 切换到训练模式
for epoch in range(epochs):
    for inputs, labels in dataloader:
        optimizer.zero_grad()  # 清除梯度
        outputs = model(inputs)  # 前向传播
        loss = criterion(outputs, labels)  # 计算损失
        loss.backward()  # 反向传播
        optimizer.step()  # 更新参数

3. 修改网络结构

除了修改全连接层外,还可以对网络的其他部分进行修改,以适应新的任务或架构要求。

3.1 替换网络的部分层

你可以替换现有网络模型的任意部分。例如,替换 ResNet 中的第一层卷积层,以适应不同的输入图像通道数:

# 假设我们要处理4通道的输入,而不是3通道
model.conv1 = torch.nn.Conv2d(4, 64, kernel_size=7, stride=2, padding=3, bias=False)
  • 注意:替换层时,需要确保新层的输出维度与后续层的输入维度匹配。
3.2 添加新的层

你可以在网络模型中插入新的层,以增加模型的复杂性或适应新的需求。例如,在 ResNet 中添加一个新的卷积层:

import torch.nn as nn

class ModifiedResNet(nn.Module):
    def __init__(self, original_model):
        super(ModifiedResNet, self).__init__()
        # 使用预训练的 ResNet-18 模型
        self.features = nn.Sequential(
            *list(original_model.children())[:-2],  # 去掉最后的全连接层和池化层
            nn.Conv2d(512, 512, kernel_size=3, padding=1),  # 添加新的卷积层
            nn.ReLU(inplace=True)
        )
        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Linear(512, 10)  # 新的全连接层

    def forward(self, x):
        x = self.features(x)
        x = self.avgpool(x)
        x = torch.flatten(x, 1)
        x = self.fc(x)
        return x

# 创建修改后的模型
modified_model = ModifiedResNet(models.resnet18(pretrained=True))

4. 模型保存与加载

在训练完成后,你可能希望保存模型的状态以便以后加载和使用。

4.1 保存模型
torch.save(model.state_dict(), 'model.pth')
  • model.state_dict():获取模型的参数字典。
4.2 加载模型
model = models.resnet18(pretrained=False)  # 初始化模型
model.fc = torch.nn.Linear(model.fc.in_features, 10)  # 修改最后的全连接层
model.load_state_dict(torch.load('model.pth'))  # 加载模型参数
model.eval()  # 切换到评估模式
  • torch.load:加载模型参数。
  • model.load_state_dict:将加载的参数字典应用于模型。

用GPU训练

在 PyTorch 中,使用 GPU 进行训练可以显著加快模型的计算速度,特别是在处理大型数据集或复杂的神经网络时。下面是详细步骤,介绍如何在 PyTorch 中利用 GPU 进行模型训练。

1. 检查 GPU 是否可用

在使用 GPU 之前,首先需要检查系统中是否有可用的 GPU,以及 PyTorch 是否可以检测到它们。

import torch

# 检查是否有可用的 GPU
if torch.cuda.is_available():
    device = torch.device("cuda")
    print("GPU is available")
else:
    device = torch.device("cpu")
    print("GPU not available, using CPU instead")

2. 将模型和数据移到 GPU

为了使用 GPU 进行训练,模型和数据都需要被显式地移动到 GPU 上。可以通过 to(device) 方法来完成这一操作。

2.1 将模型移动到 GPU
model = MyModel()  # 实例化你的模型
model.to(device)   # 将模型移动到 GPU
2.2 将数据移动到 GPU

在训练循环中,你需要将每个批次的数据移动到 GPU。

# 例如在训练循环中
for data, labels in dataloader:
    data = data.to(device)  # 将数据移动到 GPU
    labels = labels.to(device)  # 将标签移动到 GPU

    # 前向传播
    outputs = model(data)
    loss = loss_fn(outputs, labels)

    # 反向传播和优化
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

完整的模型训练&模型验证套路

在深度学习中,完整的模型训练和验证过程是确保模型性能的重要步骤。下面是一个常见的训练和验证套路,包含了数据加载、模型定义、损失函数设置、优化器选择、训练循环、验证步骤等。

1. 完整的模型训练套路

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset
from torchvision import transforms

# 假设你有一个自定义的数据集类
class CustomDataset(Dataset):
    def __init__(self, transform=None):
        # 初始化数据集,这里可以加载数据
        self.data = ...  # 加载数据
        self.labels = ...  # 加载标签
        self.transform = transform

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        sample = self.data[idx]
        label = self.labels[idx]
        if self.transform:
            sample = self.transform(sample)
        return sample, label

# 定义一个简单的神经网络
class SimpleNet(nn.Module):
    def __init__(self):
        super(SimpleNet, self).__init__()
        self.fc1 = nn.Linear(784, 128)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

# 设置设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 数据预处理和加载
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])

train_dataset = CustomDataset(transform=transform)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)

# 定义模型、损失函数和优化器
model = SimpleNet().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

# 训练循环
epochs = 10
for epoch in range(epochs):
    model.train()  # 设置模型为训练模式
    running_loss = 0.0
    for i, (inputs, labels) in enumerate(train_loader):
        inputs, labels = inputs.to(device), labels.to(device)

        # 前向传播
        outputs = model(inputs)
        loss = criterion(outputs, labels)

        # 反向传播和优化
        optimizer.zero_grad()  # 清除上一步的梯度
        loss.backward()  # 计算梯度
        optimizer.step()  # 更新参数

        # 累计损失
        running_loss += loss.item()

        if i % 100 == 99:  # 每100个批次打印一次
            print(f'Epoch [{epoch + 1}/{epochs}], Step [{i + 1}/{len(train_loader)}], Loss: {running_loss / 100:.4f}')
            running_loss = 0.0

print('Finished Training')

2. 完整的模型验证套路

验证过程用于评估模型在验证集上的表现,帮助我们了解模型是否过拟合或欠拟合。

# 这里假设你已经定义了模型、损失函数、设备等
val_dataset = CustomDataset(transform=transform)
val_loader = DataLoader(val_dataset, batch_size=64, shuffle=False)

# 验证循环
model.eval()  # 设置模型为评估模式
val_loss = 0.0
correct = 0
total = 0

with torch.no_grad():  # 在验证过程中,不需要计算梯度
    for inputs, labels in val_loader:
        inputs, labels = inputs.to(device), labels.to(device)

        # 前向传播
        outputs = model(inputs)
        loss = criterion(outputs, labels)

        # 累计损失
        val_loss += loss.item()

        # 计算准确度
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

# 计算平均损失和准确率
val_loss /= len(val_loader)
accuracy = 100 * correct / total

print(f'Validation Loss: {val_loss:.4f}, Validation Accuracy: {accuracy:.2f}%')

3. 总结与注意事项

  • 设备选择:确保数据和模型都在同一个设备上(CPU 或 GPU),否则会导致运行错误。
  • 训练模式和验证模式:在训练和验证时,分别使用 model.train()model.eval() 以设置不同的模式。train() 启用 dropout 和 batch normalization,eval() 则关闭它们。
  • 梯度计算:在验证阶段,使用 torch.no_grad() 关闭梯度计算,这样可以减少内存使用,加快计算速度。
  • 损失监控:在训练和验证过程中,监控损失和准确率,可以帮助判断模型的性能,并决定是否需要调整学习率、模型结构等。
  • 19
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值