深度学习报告

一、学习目标

1、学习使用google Colab编写代码

2、学习pytorch深度学习的基础代码

3、⽤神经⽹络实现简单数据分类

二、学习内容

列出实验的关键步骤、代码解析、截图。

2.1 pytorch 基础练习

定义数据使用torch.Tensor , tensor的意思是张量,是数字各种形式的总称
在这里插入图片描述

Tensor支持各种各样类型的数据,包括:torch.float32, torch.float64, torch.float16, torch.uint8, torch.int8, torch.int16, torch.int32, torch.int64 。

创建Tensor有多种方法,

在这里插入图片描述

使用matplotlib作图
在这里插入图片描述

2.2 螺旋数据分类

1.导入需要用到的画图脚本plot_lib.py

!wget https://raw.githubusercontent.com/Atcold/pytorch-Deep-Learning/master/res/plot_lib.py

显示导入成功:

在这里插入图片描述

在content目录下可见:

在这里插入图片描述

2.引入基本的库,然后初始化重要参数

tips:plot_lib.py文件额外引用了一张图片,直接引入该文件会报错,因为接下来所需要用的方法与该图片无关,选择注释。

在这里插入图片描述

import random
import torch
from torch import nn, optim
import math
from IPython import display
from plot_lib import plot_data, plot_model, set_default

# 因为colab是支持GPU的,torch 将在 GPU 上运行
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print('device: ', device)

# 初始化随机数种子。神经网络的参数都是随机初始化的,
# 不同的初始化参数往往会导致不同的结果,当得到比较好的结果时我们通常希望这个结果是可以复现的,
# 因此,在pytorch中,通过设置随机数种子也可以达到这个目的
seed = 12345
random.seed(seed)
torch.manual_seed(seed)

N = 1000  # 每类样本的数量
D = 2  # 每个样本的特征维度
C = 3  # 样本的类别
H = 100  # 神经网络里隐层单元的数量

随机种子是为了确保实验的可重复性,当下一次运行时设置seed=12345随机生成的数据还是一致的。

结果:

在这里插入图片描述

3.初始化 X 和 Y。 X 可以理解为特征矩阵,Y可以理解为样本标签。 结合代码可以看到,X的为一个 NxC 行, D 列的矩阵。C 类样本,每类样本是 N个,所以是 N*C 行。每个样本的特征维度是2,所以是 2列。

在 python 中,调用 zeros 类似的函数,第一个参数是 y方向的,即矩阵的行;第二个参数是 x方向的,即矩阵的列,不要搞反了。

X = torch.zeros(N * C, D).to(device)
Y = torch.zeros(N * C, dtype=torch.long).to(device)
for c in range(C):
    index = 0
    t = torch.linspace(0, 1, N) # 在[0,1]间均匀的取10000个数,赋给t
    # 下面的代码不用理解太多,总之是根据公式计算出三类样本(可以构成螺旋形)
    # torch.randn(N) 是得到 N 个均值为0,方差为 1 的一组随机数,注意要和 rand 区分开
    inner_var = torch.linspace( (2*math.pi/C)*c, (2*math.pi/C)*(2+c), N) + torch.randn(N) * 0.2

    # 每个样本的(x,y)坐标都保存在 X 里
    # Y 里存储的是样本的类别,分别为 [0, 1, 2]
    for ix in range(N * c, N * (c + 1)):
        X[ix] = t[index] * torch.FloatTensor((math.sin(inner_var[index]), math.cos(inner_var[index])))
        Y[ix] = c
        index += 1

print("Shapes:")
print("X:", X.size())
print("Y:", Y.size())

结果:

在这里插入图片描述

4.构建线性模型分类

learning_rate = 1e-3
lambda_l2 = 1e-5

# nn 包用来创建线性模型
# 每一个线性模型都包含 weight 和 bias
model = nn.Sequential(
    nn.Linear(D, H),
    nn.Linear(H, C)
)
model.to(device) # 把模型放到GPU上

# nn 包含多种不同的损失函数,这里使用的是交叉熵(cross entropy loss)损失函数
criterion = torch.nn.CrossEntropyLoss()

# 这里使用 optim 包进行随机梯度下降(stochastic gradient descent)优化
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate, weight_decay=lambda_l2)

# 开始训练
for t in range(1000):
    # 把数据输入模型,得到预测结果
    y_pred = model(X)
    # 计算损失和准确率
    loss = criterion(y_pred, Y)
    score, predicted = torch.max(y_pred, 1)
    acc = (Y == predicted).sum().float() / len(Y)
    print('[EPOCH]: %i, [LOSS]: %.6f, [ACCURACY]: %.3f' % (t, loss.item(), acc))
    display.clear_output(wait=True)

    # 反向传播前把梯度置 0 
    optimizer.zero_grad()
    # 反向传播优化 
    loss.backward()
    # 更新全部参数
    optimizer.step()

准确率仅有0.504,可见对于这样复杂的一个数据分布,线性模型难以实现准确分类
在这里插入图片描述

5.添加激活函数

ReLU(Rectified Linear Unit)函数

  • 公式:
    R e L U ( x ) = m a x ⁡ ( 0 , x ) ReLU(x)=max⁡(0,x) ReLU(x)=max(0,x)
    特点:当输入大于0时输出输入值,否则输出0。它解决了梯度消失问题,计算效率高,是目前最常用的激活函数之一。

    在这里插入图片描述

仅有此处代码不同,其余一样

# 这里可以看到,和上面模型不同的是,在两层之间加入了一个 ReLU 激活函数
model = nn.Sequential(
    nn.Linear(D, H),
    nn.ReLU(),
    nn.Linear(H, C)
)

准确率也上来了,达到0.955

在这里插入图片描述

三、程序运行结果

列出程序的最终运行结果及截图。

1.根据特征矩阵X和样本标签Y作图

# visualise the data
plot_data(X, Y)

在这里插入图片描述

2.使用线性模型分类结果:

在这里插入图片描述

3.使用两层神经网络分类(加入激活函数)

在这里插入图片描述

四、问题总结与体会

AlexNet的特点及为何优于LeNet:

  • 特点:
    • 比LeNet 网络更深、更宽。
    • 使用了 ReLU 和 Dropout,AlexNet 在训练时更稳定,不易过拟合。
    • 使用了数据增强技术,通过对训练图像进行随机变换来增加数据多样性。
    • 采用了 GPU 加速训练,显著提高了训练速度。
  • 为何优于LeNet:
    • AlexNet 的网络结构更深,有更多的卷积层和全连接层,能够学习更复杂的特征。
    • 由于使用了 ReLU 和 Dropout,AlexNet 在训练时更稳定,且不易过拟合。
    • 数据增强和 GPU 加速使得 AlexNet 能够处理更大的数据集和更快地训练。

激活函数的作用:

  • 引入非线性,使得神经网络能够学习复杂的函数映射。
  • 有助于缓解梯度消失问题。

梯度消失现象:

  • 参数梯度无限趋近于0,导致网络中的权重更新非常缓慢或几乎不更新,从而使得网络难以训练。。

神经网络的宽度与深度:

  • 宽度:指的是每层的神经元数量,增加宽度可以提供更多的参数来学习数据的特征,但同时也会增加计算复杂度和过拟合的风险。
  • 深度:指的是增加网络的层数,增加深度可以增加网络的学习能力,使其能够学习更复杂的特征层次,但可能会导致梯度消失或梯度爆炸问题。
  • 一般来说,深度的贡献是指数增加,而宽度的贡献是线性增加。
  • 在这里插入图片描述

为什么要使用Softmax:

  • Softmax 函数可以将神经网络输出的 logits 转换为概率分布,使得每个类别的预测概率都在 0 到 1 之间,且所有类别的概率之和为 1。

SGD与Adam的有效性:

  • SGD(随机梯度下降):是最基础的优化算法,它在每次迭代中使用一个样本或一个批次的样本来估计梯度。SGD 简单且在很多情况下都很有效,但可能需要更多的迭代次数来收敛。
  • Adam(自适应矩估计):是一种更高级的优化算法,它结合了动量方法和自适应学习率的优点。Adam 能够自动调整每个参数的学习率,通常收敛速度更快,对超参数的选择更不敏感。
  • 两者的有效性取决于具体任务和数据。在某些情况下,SGD 可能更有效,因为它更简单,而 Adam 可能在其他情况下表现更好,因为它提供了更快的收敛速度和更好的稳定性。通常,Adam 在实践中更受欢迎,因为它通常能够更快地收敛,并且对超参数的调整要求较低。

代码问题1:在引入plot_lib文件时报错

解决:先稳住,看报错信息,根据报错信息去原文件修改。

代码问题2:print(y_pred[10, :])输出的概率为负数

解决:查阅资料得知y_pred 是模型的原始输出,也就是logits。这些值可以是正的、负的或零。

  • 26
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值