2024年夏季《深度学习》学习报告
姓名 | *** |
---|---|
学号 | *** |
课程 | 深度学习基础-算法与实践 |
内容 | 深度学习基础 |
博客地址 |
课程视频链接:网易云课堂:深度学习
一、学习目标
1、从机器学习到深度学习
2、浅层神经网络:单层感知器、多层感知器、反向传播和梯度消失
3、神经网络到深度学习:逐层预训练、自编码器和受限玻尔兹曼机
4、pytorch的入门使用
二、学习内容
1.理论内容
人工智能、机器学习、深度学习三者关系
传统的机器学习缺点:需要人工进行特征处理工作,往往需要耗费大量时间来手工设计特征才能保证模型表现出良好的性能。
深度学习:仅仅需要简单标注几张图片便可以让模型自主学习特征并进行优化参数,并表现出良好的性能。
深度学习的“不能”:(1)算法输出不稳定,容易被“攻击”。比如,一个图像中随机改变一个像素后, 输出就可能改变。(2)模型复杂度高,难以纠错和调试。(3)模型层级复杂度高,参数不透明。(4)端到端训练方式对数据依赖性强,模型增量性差,需要大量数据来训练才能保证良好性能。(5)现阶段对开放推理问题无能为力,专注于直观感知类问题。(6)机器偏见难以避免
神经网络启发于人类大脑神经元的结构:
数学表达:t=f(WTA+b)
单层感知器->多层感知器:神经网络的起始,实现简单的分类问题。
神经网络学习如何利用矩阵的线性变换加激活函数的非线性变换,将原始输入空间投影到线性可分的空间去分类或者回归。其中增加节点数是增加线性转换能力,增加层数是增加非线性转换能力。
神经网络更深相比于更宽对于性能提升是更大的
逐层预训练:受限玻尔兹曼机和自编码器
受限玻尔兹曼机:通过对比散度算法来近似梯度进行参数更新,应用到了数据降维、协同滤波等问题,为后续其他深度生成模型奠定了基础。
自编码器:一种无监督的压缩数据维度和数据特征的方法。核心是编码器和解码器。
2.实验部分
(1)定义数据+数据操作
(2)螺旋数据分类
#引入画图函数
!wget https://raw.githubusercontent.com/Atcold/pytorch-Deep-Learning/master/res/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 # 神经网络里隐层单元的数量
报错:FileNotFoundError: [Errno 2] No such file or directory: ‘res/ziegler.png’****
解决办法:
#解决上述找不到该文件的问题 在工作目录下新建res目录将该文件放入
!wget https://raw.githubusercontent.com/Atcold/pytorch-Deep-Learning/master/res/ziegler.png
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())
# visualise the data
plot_data(X, Y)
首先采用线性模型分类
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()
[EPOCH]:999, [LOSS]:0.861541, [ACCURACY]:0.504
print(y_pred.shape)
print(y_pred[10, :])
print(score[10])
print(predicted[10])
# Plot trained model
print(model)
plot_model(X, Y, model)
接着采用两层神经网络分类
learning_rate = 1e-3
lambda_l2 = 1e-5
# 加入了一个 ReLU 激活函数
model = nn.Sequential(
nn.Linear(D, H),
nn.ReLU(),
nn.Linear(H, C)
)
model.to(device)
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate, weight_decay=lambda_l2) # built-in 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)
# zero the gradients before running the backward pass.
optimizer.zero_grad()
# Backward pass to compute the gradient
loss.backward()
# Update params
optimizer.step()
[EPOCH]: 999, [LOSS]: 0.178409, [ACCURACY]: 0.949
# Plot trained model
print(model)
plot_model(X, Y, model)
三、程序运行结果
1.线性分类模型分类的结果
2.加入非线性的激活函数后的结果
加入激活函数后,分类的效果提高很多!
四、问题总结与体会
1、问题总结
(1)做第二个实验时候出现找不到文件的问题
#解决上述找不到该文件的问题 在工作目录下新建res目录将该文件放入
!wget https://raw.githubusercontent.com/Atcold/pytorch-Deep-Learning/master/res/ziegler.png
(2)概率统计的相关公式推导需要加强学习,只有扎实的基础知识才能做出更好的创新成果。
2、AlexNet有哪些特点?为什么可以比LeNet取得更好的性能?
AlexNet主要的特点如下:(1)采用ReLU激活函数,加快了训练速度。(2)加入Dropout正则化来防止过拟合(3)其网络相比于LeNet加入了多个卷积层以及池化层,展现出更好的性能。
3、激活函数有哪些作用?
为模型加入了非线性因素,可以处理更加复杂的问题
4、梯度消失现象是什么?
梯度在反向传播过程中随着网络层数增加而迅速减小,导致训练困难。
5、神经网络是更宽好还是更深好?
更深对于性能提升是更大的。
6、为什么要使用Softmax?
可以实现多分类问题的激活函数,用于网络的输出层,将向量映射到概率分布上。
7、SGD 和 Adam 哪个更有效?
SGD:适用于大规模数据集,需要较长时间训练的模型,以及那些需要跳出局部最小值的场景。
Adam:适用于需要快速收敛,或者参数更新规模差异较大的模型。
为模型加入了非线性因素,可以处理更加复杂的问题
4、梯度消失现象是什么?
梯度在反向传播过程中随着网络层数增加而迅速减小,导致训练困难。
5、神经网络是更宽好还是更深好?
更深对于性能提升是更大的。
6、为什么要使用Softmax?
可以实现多分类问题的激活函数,用于网络的输出层,将向量映射到概率分布上。
7、SGD 和 Adam 哪个更有效?
SGD:适用于大规模数据集,需要较长时间训练的模型,以及那些需要跳出局部最小值的场景。
Adam:适用于需要快速收敛,或者参数更新规模差异较大的模型。
需要根据不同的模型需求来选择相应的算法。