前言
如何逐渐掌握深度学习呢,是一个难题,网上参差不齐没有一个非常好非常全面的教程,只能一点一点自己累计,寻找例程来模仿主要理解他是怎么一步步完成任务的、思考一个普遍性的解决问题的过程,如何搭建深度学习的神经网络框架,现在暂时选择pytorch
。
然后,目前推荐搭建框架过程使用jupyter notebook
,所以也要学习如何使用它,那么我想在每一阶段都解决和思考一些问题记录下来,来一步步稳扎稳打的学习深度学习
个人思路
其实,深度学习说难不难,说简单肯定不简单,你真的可以甚至1天快速入门、上手,只要你懂一些python语法,稍微看看比较通俗的神经网络的介绍文章,学一种搭建框架的方式就能让你用上你设计的网络结构,大批量的规则化的图像信息甚至也可以从网上获取,然后非常方便的使用、训练、测试。
但是你想真正用神经网络来解决问题你自己的实际问题,那么这些将远远不够,至少我是这样认为的,所以我寻找了很多比较有顺序的深度学习教程(pytorch的),都需要一篇篇的仔细阅读,深化概念,让之后的进阶操作能更快理解。
学习阶段————初次接触
思考:
- 如何将一大批尺寸不一、随机的图像统一标准化的作为深度学习的输入、以及同时集合这些输入的label–对应的解,即真实值(来和输出层的计算值比较损失)?
- 神经网络的框架如何根据自己的要求、向适合解决问题的网络结构改进?
- 学习如何使用GPU来训练模型?
- jupyter notebook 中如何正常运行pytorch网络?
一、在Morvan莫烦的pytorch教程中,再次理解神经网络
1.1 神经网络是什么
- 之前虽然理解了一种说法,好像没提出来,这里讲一讲,但不讲太多,没啥意义
- 首先,人们希望模仿人类的大脑,即生物神经网络,人类如何形成条件反射?如何学习?如何记忆?大脑内神经元如何工作?神经元之间有什么样的联系?
- 人工神经网络相比,相似,又不相似,所有神经元的连接在同一时间都是固定的,不会凭空产生新联结,它是一种逐次接近正确答案的训练手段,其中“误差反向传递”起到关键作用
1.2 神经网络的简单结构概念
Gradient Descent
:梯度下降Cost Function
:损失函数- 输入层、隐含层(第1层。。。第n层)、输出层就对应着特征–>代表特征1–>…–>代表特征n–>输出,这些代表特征是越来越抽象的,人越来越无法理解,但计算机就对他比较敏感了
- 迁移学习:即在当你现有的一般神经网络足够处理比如图片内容种类识别、字符识别的任务后。如果我们在输出层前再加入几层神经网络来训练,就能来完成进阶的任务,比如不仅识别数字,还能知道数字的书写字体。。等等
2.1 选择Pytorch
- 好用、使用广泛、新颖、直观、动态建立框架
torchvision
里已经有一些它搭建好的网络,比如resnet(可以可以,我知道例程是这样用的了),然后你用这个已有的网络来训练自己的任务
将
jupyter notebook
工作目录更改为自定义,即在属性栏启动目录将userprofile/
..双引号内的内容改为自己希望前往的目录地址,重启即可
2.2 什么是Variable
它在神经网络的训练中是一个关键,为什么这么说?思考一下,神经网络的反向传播算法常用梯度下降法,那其中如何求梯度呢?
大家都知道就是求偏导数,导数就是梯度,torch里求导数的小帮手就是variable
,将tensor张量放进variable中,开启自动求梯度的配置1
variable = Variable(tensor,requires_grad=True) #requires_grad = True
那么,你以后含variable的运算就都和variable本身建立了某种联系,可以快速得到以后的结果相对variable的梯度
1
2v_out = torch.mean(variable*variable) #例如求个平均数的运算
v_out.backward() #求梯度variable
变量不同于tensor
,但是variable.data
可以得到tensor,如果想进行tensor和numpy_array的转换,那么就要xx.data
先得到tensorvariable
的运算和tensor
相似,但不完全相同
2.3 激励函数(AF–activation function)?
- 激励函数广泛应用在各种层,各种用,可是为什么要激励函数呢?因为复杂问题中,输入输出往往都不是线性关系,不是线性,你就不能简单在他们中间乘个系数。
进阶的操作就是,在输入做完简单线性处理(乘k)的结果代入一个非线性函数
- 常用的非线性激活函数由
relu
、sigmoid
、tanh
方程,甚至可以自己创造激励函数来求解,不过要注意,这些激励函数必须都是可以微分的,因为需要求梯度求导
- 当隐藏层不多时,可以尝试任意一个激励函数;不过当隐藏层中含有非常多个
layer
,就有慎重选择,可能出现梯度爆炸、梯度消失(我也不太懂,再学学)。其次,具体案例中,少量隐藏层可以有多种选择,卷积神经网络首选relu
,循环神经网络首选relu
、tanh
如何应用activation function
- 理解代码然后实验即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import torch
import torch.nn.functional as F
from torch.autograd import Variable
import matplotlib.pyplot as plt
# fake data
x = torch.linspace(-5, 5, 200) # x data (tensor), shape=(100, 1)
x = Variable(x)
x_np = x.data.numpy() # numpy array for plotting
# following are popular activation functions
y_relu = torch.relu(x).data.numpy()
y_sigmoid = torch.sigmoid(x).data.numpy()
y_tanh = torch.tanh(x).data.numpy()
y_softplus = F.softplus(x).data.numpy() # there's no softplus in torch
3.1 构建网络:回归
利用
Pytorch
建立一个简单的神经网络1
2
3
4
5
6
7
8class Net(torch.nn.Module):
def __init__(self, xxx, xxx, xxx, ...):
super(Net, self).__init__()
# xxxxxxxx
def forward(self, x):
# xxxxxxxx
return x定义一个实际的神经网络
1
net = Net(xxx=1, xxx=10, xxx=1, ...)
定义优化器
optimizer
和损失函数loss function
1
2optimizer = torch.optim.SGD(net.parameters(), lr=0.2) #net.parameters():包含了神经网络的所有参数 lr:学习率(步长)
loss_func = torch.nn.MSELoss() # this is for regression mean squared loss那么在训练的时候
- 首先定义网络的输出位置
prediction
,真正计算损失loss
- 每次利用优化器清除掉网络中之前计算的梯度
- 然后开始运行反向传播算法
- 最后向正确方向迈出一步,用计算出的梯度再计算出新一轮的网络参数
1
2
3
4
5prediction = net(x) # input x and predict based on x
loss = loss_func(prediction, y) # must be (1. nn output, 2. target)
optimizer.zero_grad() # clear gradients for next train
loss.backward() # backpropagation, compute gradients
optimizer.step() # apply gradients当然本节是对于简单的回归问题,所以定义输出量的变量简单,损失计算也是简单的均方差算法
- 首先定义网络的输出位置
3.2 构建网络:分类
- 与简单的回归神经网络不同的是,分类神经网络的输入量和输出量都不只有一个
- 输入量可以是一组坐标,甚至可以是一张图片的一个三维张量,而输出则可以是一个输入张量对所有类别的概率判断
- 分类的损失函数选择和回归是不一样的,教程中选择了
loss_func = torch.nn.CrossEntropyLoss()
- 当然,对于我要解决的字符识别问题而言,输入就要复杂得多,远不是一对坐标那么简单,输出的类别也会有很多,所以更透彻的学习将在第二阶段进行