第一次作业:深度学习基础
目录
- 视频学习心得及问题总结
- 1.1 心得
- 1.2 问题
- 代码练习
- 2.1 代码1
- 2.2 代码2
- 2.3 代码3
- 2.4 代码4
1. 视频学习心得及问题总结
1.1 心得
第一部分
-
机器学习:模型,策略与算法,模型是对问题进行建模,策略是确定目标函数,算法求解模型参数
-
监督/无监督学习模型根据是否具有确定的标记来区分,半监督学习则是部分具有标记,一般是由于数据难以获得造成的,强化学习则是知道标记的反馈。
-
生成模型:对输入X和输出Y的联合分布P(X,Y)建模
判别模型:对已知输入X条件下输出Y的条件分布P(Y|X)建模
-
深度学习模型是深层次的神经网络模型,最简单的神经网络模型是感知机。对深度学习模型进行训练使用BP算法
第二部分
- 深度学习的几点限制
- 算法输出不稳定
- 模型复杂度高,难以纠错调试
- 模型层级复合程度高,参数不透明
- 对数据依赖性强
- 推理能力有待加强
- 存在机器偏见
- 常用激活函数:sigmoid函数,ReLU函数,tanh函数,Leaky ReLU函数
- \(\color{red}{sigmoid函数一般用于二分类问题}\)
- 万有逼近定理
- 如果\(\color{#FF0000}{一个}\)隐层包含\(\color{red}{足够多}\)的神经元,\(\color{#FF0000}{三层}\)前馈神经网络(输入-隐层-输出)能以任意精度逼近任意预定的\(\color{#FF0000}{连续}\)函数
- 当隐层足够\(\color{#FF0000}{宽}\)时,\(\color{#FF0000}{双隐层}\)感知器(输入-隐层1-隐层2-输出)可以逼近任意\(\color{#FF0000}{非连续函数}\),可以解决任何复杂的分类问题
- 神经网络各层的作用
- 线性变换(Wx)
- 升/降维度
- 放大/缩小
- 旋转
- 偏置(+b)
- 平移
- 激活函数a(·)
- 弯曲
- 线性变换(Wx)
- 神经网络深度对逼近函数的贡献是指数上升的,而增加宽度则是线性上升的。
- 深度过深会引起梯度消失问题。对sigmoid函数更为明显
- 梯度下降法
- 对凸函数(局部极值点则为全局最优点),可以使用梯度下降法找到函数的最值
- 对非凸函数,使用梯度下降法有可能会陷入到局部极值点,导致学习效果不理想
- BP(反向传播)算法是首先前馈神经网络,计算出当前预测值和实际值的差值,计算出loss(损失),而后将该loss反向传播,更新每一个结点的权重。在反向传播时使用梯度下降法逐步逼近loss函数的极值(凸函数则是最值),直至训练过程收敛。可以参阅代码3部分。
- 可以采用逐层预训练与微调的方式改善陷入局部极小值的窘境,逐层预训练的效果较好。逐层预训练的方法主要有自编码器和受限玻尔兹曼机。
- \(\color{red}{自编码器可以用于图像去噪}\)
第三部分
-
pytorch, tensorflow为深度学习框架,pytorch流行于学术界,而tensorflow则流行于工业界
pytorch为动态图,而tensorflow为静态图。pytorch较容易上手。
-
pytorch等一系列科学计算库具有两个核心问题:
- 如何表示数据?
- 如何对数据进行运算?
pytorch使用张量(torch.Tensor)表示数据,使用定义在Tensor类上的torch.autograd.Function函数类对Tensor进行运算。
-
各种运算的使用参见教程。
-
有关函数backward()
>>>import torch >>>x = torch.rand(2,2,requires_grad=True) >>>y = x + 2 >>>z = 3 * y**2 >>>out = z.mean() >>>out.backward() >>>x.gradtensor([[3.6051, 4.1434], [3.4039, 3.5650]])>>>xtensor([[0.4034, 0.7622], [0.2692, 0.3767]], requires_grad=True)>>>c = (3/2)*(x+2) #这部分计算的是∂out/∂x,省略了步骤>>>ctensor([[3.6051, 4.1434], [3.4039, 3.5650]], grad_fn=<MulBackward0>)我们可以得到backword()的功能是计算
其中 i,j,··· 为张量x的维度指标。
1.2 问题
- 如何根据问题的类型和规模确定神经网络的基本模型(即深度和每一层次的神经元个数)
- backward()的功能比较容易理解,结合运算的动态图表示也比较易于理解其求解的大体步骤。但其具体是如何实现的?
- 逐层预处理部分两个模型(自编码器、受限玻尔兹曼机)的实现机理。
2. 代码练习
2.1 代码1
-
黑白图像处理
camera[30:100, 10:100] = 0 #camera为某黑白图像,30-99行,10-99列亮度置为0 camera[:10] = 0 #起始行-第9行,所有列亮度置为0 mask = camera < 80 #将亮度值低于80的改为255,即高亮显示 camera[mask] = 255 -
彩色图像处理
reddish = cat[:, :, 0] > 160 #所有行所有列,选中第一通道(即RGB中的R)值大于160的点 #其中cat为一张猫的图像 red_cat[reddish] = [255, 0, 0] #将这些点的RGB值设为255,0,0,即为大红色 BGR_cat = cat[:, :, ::-1] #将RGB转换为BGR,即翻转,-1表示从最后一个元素到第一个元素 #反向 -
显示图像直方图
plt.hist(img.ravel(), bins=256, histtype='step', color='black') #分为256个单位 -
填补空洞
ndi.binary_fill_holes(img_edges) -
改变对比度
p2, p98 = np.percentile(img, (2, 98)) #寻找分位点 exposure.rescale_intensity(img, in_range=(p2, p98)) #in_range表示可以输入的亮度范围 -
直方图均衡化
img_eq = exposure.equalize_hist(img) -
自适应直方图均衡
img_adapteq = exposure.equalize_adapthist(img, clip_limit=0.03)
2.2 代码2
-
创建Tensor
torch.tensor(666) torch.tensor([1,2,3,4,5,6]) torch.ones(2,3) torch.ones(2,3,4) torch.empty(5,3) torch.rand(5,3) torch.zeros(5,3) torch.arange(1, 5) #[1,2,3,4],没有5 x.new_ones(5,3) #x为已存在的张量,该函数饭会一个dtype,device相同的张量 torch.randn_like(x, dtype=torch.float) #返回与x同样维度但重定义了dtype的张量 torch.linspace(3, 8, 20) #从3.0~8.0等距分割20个点(含有3.0和8.0) -
张量操作
m = torch.Tensor([[2, 5, 3, 7], [4, 2, 1, 9]]) #元素个数 m.numel() m[0][2] m[:, 1] m[0, :] #标量积 m @ v #转置 m.t() # matlabplotlib 只能显示numpy类型的数据,下面展示了转换数据类型,然后显示 # 注意 randn 是生成均值为 0, 方差为 1 的随机数 # 下面是生成 1000 个随机数,并按照 100 个 bin 统计直方图 plt.hist(torch.randn(1000).numpy(), 100); # 创建两个 1x4 的tensor a = torch.Tensor([[1, 2, 3, 4]]) b = torch.Tensor([[5, 6, 7, 8]]) # 在 0 方向拼接 (即在 Y 方各上拼接), 会得到 2x4 的矩阵 torch.cat((a,b), 0) tensor([[1., 2., 3., 4.], [5., 6., 7., 8.]]) # 在 1 方向拼接 (即在 X 方各上拼接), 会得到 1x8 的矩阵 torch.cat((a,b), 1) tensor([[1., 2., 3., 4., 5., 6., 7., 8.]]) -
对张量内部的数据进行数据转换可以使用type_as()函数
tensor1=torch.FloatTensor(4) tensor2=torch.IntTensor(3) tensor1=tensor1.type_as(tensor2)该方法用于解决以下错误
RuntimeError: Expected object of scalar type Float but got scalar type Long for argument #3 'vec' in call to _th_addmv_out
2.3 代码3
-
对模型进行训练的一种样例
for t in range(迭代次数): # 把数据输入模型,得到预测结果 y_pred = model(数据集) #model为定义好的模型 # 计算损失 loss = criterion(y_pred, Y) # 反向传播前把梯度置 0 optimizer.zero_grad() # 反向传播优化 loss.backward() # 更新全部参数 optimizer.step() -
损失函数和优化器
损失函数的选取根据数据的分布情况决定,一般有交叉熵和均方方差等
\(\color{red}{优化器主要有SGD和Adam两种,一般而言,使用Adam就可以,效果比较好。}\)
-
两种模型的对比
第一种模型为:
\[h_\theta(x)=f(\boldsymbol{w^Tx}+b) \]其中激活函数为:
\[a(x)=x \]第二种激活函数则为:
\[a(x)=ReLU(x)=max(0,x) \]选择非线性的激活函数可以拟合非线性的模型,而选择线性激活函数仅能升降维度、放大缩小、旋转或平移,难以拟合非线性的模型。
-
存在的问题
- 如何进行损失函数和优化器的选取?
2.4 代码4
-
绘制散点图
import numpy as np import matplotlib.pyplot as plt plt.scatter(x,y) #x,y为数组,张量和numpy矩阵都可以 tensor1.numpy() -
绘制折线图,如果参照点比较多,则会看起来像光滑的
x = torch.linspace(0,10,12) #看起来会有点不光滑,可以将12调到100,则会变光滑 y = x*x plt.plot(x,y) plt.plot(x,y,'r-') #红色折线 plt.plot(x,y,'y-') #黄色折线 -
还有的问题
- ReLU拟合出来为什么是类似折线的函数?
- tanh激活函数为什么没有ReLU收敛速度快?
- 绘制散点图时的一些参数的含义不明确。
- 权重衰减(weight_decay)的含义以及如何设置其值。
浙公网安备 33010602011771号