【第⼀部分:代码练习】
1.验证Google Colab的可用性
PyTorch的常用用法
2.定义数据
一般定义数据使用torch.Tensor , tensor的意思是张量,是数字各种形式的总称
创建Tensor有多种方法,包括:ones, zeros, eye, arange, linspace, rand, randn, normal, uniform, randperm
3.定义操作
凡是用Tensor进行各种运算的,都是Function
最终,还是需要用Tensor来进行计算的,计算无非是
- 基本运算,加减乘除,求幂求余
- 布尔运算,大于小于,最大最小
- 线性运算,矩阵乘法,求模,求行列式
基本运算包括: abs/sqrt/div/exp/fmod/pow ,及一些三角函数 cos/ sin/ asin/ atan2/ cosh,及 ceil/round/floor/trunc 等具体在使用的时候可以百度一下
布尔运算包括: gt/lt/ge/le/eq/ne,topk, sort, max/min
线性计算包括: trace, diag, mm/bmm,t,dot/cross,inverse,svd 等
Spiral classifciation
下载绘图函数到本地。因为plot_lib.py文件中的部分函数使用到了原作者的相对路径的文件,导致调用时可能会报错,可以打开源文件将需要的三个函数拷贝到本地定义这三个函数即可,以下是源码:
from matplotlib import pyplot as plt
import numpy as np
import torch
from IPython.display import HTML, display
def set_default(figsize=(10, 10), dpi=100):
plt.style.use(['dark_background', 'bmh'])
plt.rc('axes', facecolor='k')
plt.rc('figure', facecolor='k')
plt.rc('figure', figsize=figsize, dpi=dpi)
def plot_data(X, y, d=0, auto=False, zoom=1):
X = X.cpu()
y = y.cpu()
plt.scatter(X.numpy()[:, 0], X.numpy()[:, 1], c=y, s=20, cmap=plt.cm.Spectral)
plt.axis('square')
plt.axis(np.array((-1.1, 1.1, -1.1, 1.1)) * zoom)
if auto is True: plt.axis('equal')
plt.axis('off')
_m, _c = 0, '.15'
plt.axvline(0, ymin=_m, color=_c, lw=1, zorder=0)
plt.axhline(0, xmin=_m, color=_c, lw=1, zorder=0)
def plot_model(X, y, model):
model.cpu()
mesh = np.arange(-1.1, 1.1, 0.01)
xx, yy = np.meshgrid(mesh, mesh)
with torch.no_grad():
data = torch.from_numpy(np.vstack((xx.reshape(-1), yy.reshape(-1))).T).float()
Z = model(data).detach()
Z = np.argmax(Z, axis=1).reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral, alpha=0.3)
plot_data(X, y)
初始化 X 和 Y。 X 可以理解为特征矩阵,Y可以理解为样本标签。 结合代码可以看到,X的为一个 NxC 行, D 列的矩阵。C 类样本,每类样本是 N个,所以是 N*C 行。每个样本的特征维度是2,所以是 2列。
在 python 中,调用 zeros 类似的函数,第一个参数是 y方向的,即矩阵的行;第二个参数是 x方向的,即矩阵的列,大家得注意下,不要搞反了。下面结合代码看看 3000个样本的特征是如何初始化的。最后对数据进行可视化
创建好数据之后开始建立模型进行训练,共建立了两个模型都为两层的网络,但是第二个比第一个网络中中间加了一层relu激活函数
模型1
因为模型没有使用激活函数,只是建立了线性划分故正确率并不是很高。
模型2:
模型2只是在model中加入了relu激活函数,正确率已经非常高了
思考与总结:编写风格比较像python和matlab,pytorch中的@
表示的是数学中的矩阵乘法,*
是数学中的Hadamard积(哈达玛积)-对应位置相乘。创建张量如果是tensor那么是不带小数点的,如果是Tensor就是带小数点的。考虑到ReLU激活函数可能会导致神经元死亡,尝试使用LeakyReLU作为激活函数,正确率有小幅度提升如下所示:
model = nn.Sequential(
nn.Linear(D, H),
nn.LeakyReLU(),
nn.Linear(H, C)
)
【第⼆部分:问题总结】思考下⾯的问题:
1、AlexNet有哪些特点?为什么可以⽐LeNet取得更好的性能?
AlexNet的特点:
使用了ReLU作为激活函数,更好的解决了梯度消失的问题;采用了层叠池化操作,有效防止过拟合;使用了Dropout丢失部分神经元来防止过拟合。
比LeNet好的原因:
AlexNet拥有8层网络而LeNet只有5层,故AlexNet的泛化性会比LeNet更好同时使用ReLU来解决网络加深导致的梯度消失的问题;AlexNet的训练数据比LeNet更大,增强了模型的性能;在AlexNet提出时GPU已经兴起,相对于CPU的训练模式,GPU拥有更高的算力,能够训练更加复杂的模型,使得AlexNet能够设计的更深更复杂。
2、激活函数有哪些作⽤?
神经元之间的信息传递必须大于某个阈值才能被激活,阈值由激活函数设置;如果没有激活函数那么只是在执行矩阵相乘,无法赋予网络非线性。
3、梯度消失现象是什么?
梯度消失指的是网络在反向传播中,前面的网络层所收到的梯度会逐层减小,以至于前面的层无法进行学习,如在使用Sigmoid等激活函数时,如果输入值过大或者是过小它的梯度都趋于0,再经过多层的传播,此时的梯度就趋于0了。
4、神经⽹络是更宽好还是更深好?
在神经元总数相当的情况下,增加网络深度可以比增加宽度带来更强的网络表示能力:产生更多的线性区域;深度和宽度对函数复杂的的贡献是不同的,深度的贡献是指数增长的,而宽度的贡献的线性的;但是网络也不是越深越好,网络过深了容易产生梯度消失问题。
5、为什么要使⽤Softmax?
Softmax函数可以将输入值转化为0-1之间的分布, Softmax函数的主要作用是将模型的原始输出转化为概率分布,使得这些输出更易于解释和处理。在多类别分类问题中,它能够有效地将网络输出与实际标签进行对比,并且与交叉熵损失函数的组合提供了高效的训练机制。这些特性使得Softmax成为深度学习中分类问题输出层的标准选择。
6、SGD 和 Adam 哪个更有效?
-
SGD:在大规模数据集和需要较低内存消耗的场景中,SGD具有优势。对于需要精细调节学习率的任务,SGD可以通过使用学习率调节策略来提高性能。
-
Adam:适用于大多数深度学习任务,尤其是当网络结构复杂或数据特征稀疏时。Adam的自适应学习率和动量机制使得它在许多情况下能更快地收敛,并且对超参数的选择比较鲁棒。