深度学习入门之PyTorch学习笔记

  • 绪论
  • 1 深度学习介绍
  • 2 深度学习框架
  • 3 多层全连接网络
    • 3.1 PyTorch基础
    • 3.2 线性模型
      • 3.2.1 问题介绍
      • 3.2.2 一维线性回归
      • 3.2.3 多维线性回归
      • 3.2.4 一维线性回归的代码实现
      • 3.2.5 多项式回归
    • 3.3 分类问题
      • 3.3.1 问题介绍
      • 3.3.2 Logistic 起源
      • 3.3.3 Logistic 分布
      • 3.3.4 二分类的Logistic回归
      • 3.3.5 模型的参数估计
      • 3.3.6 Logistic回归的代码实现
    • 3.4 简单的多层全连接前向网络
    • 3.5 深度学习的基石:反向传播算法
      • 3.5.1 链式法则
      • 3.5.2 反向传播算法
      • 3.5.3 Sigmoid 函数举例
    • 3.6 各种优化算法的变式
    • 3.7 处理数据和训练模型的技巧
    • 3.8 多层全连接神经网络实现MNIST手写数字分类
  • 参考资料

绪论

  • 深度学习如今已经称为科技领域最炙手可热的技术,帮助你入门深度学习。
  • 本文从机器学习与深度学习的基础理论入手,从零开始学习PyTorch以及如何使用PyTorch搭建模型。
  • 学习机器学习中的线性回归、Logistic回归、深度学习的优化方法、多层全连接神经网络、卷积神经网络、循环神经网络、以及生成对抗网络,最后通过实战了解深度学习前沿的研究成果。
  • 将理论与代码结合,帮助更好的入门机器学习。

1 深度学习介绍

https://hulin.blog.csdn.net/article/details/107733777

2 深度学习框架

https://hulin.blog.csdn.net/article/details/107746239

3 多层全连接网络

  • 深度学习的前身是多层全连接神经网络,神经网络领域最开始主要是用来模拟人脑神经元系统,随后逐渐发展成为一项机器学习技术。
  • 先从PyTorch基础入手,介绍PyTorch的处理对象、运算操作、自动求导、以及数据处理方法,接着从线性模型开始进入机器学习的内容,然后由Logistic回归引入分类问题,介绍多层全连接神经网络、反向传播算法、各种基于梯度的优化算法、数据预处理和训练技巧,最后用PyTorch实现多层全连接神经网络。

3.1 PyTorch基础

https://hulin.blog.csdn.net/article/details/107797807

3.2 线性模型

3.2.1 问题介绍

  • 线性模型就是给定很多个数据点,找到一个函数来拟合这些数据点,使其误差最小。

  • 找出一条直线,使得直线尽可能与这些点接近,即点到直线的距离之和尽可能小。用数学语言来表达,给定由d个属性描述的示例x={x1,x2,x3,⋯,xd}x=\{x_1,x_2,x_3,\cdots,x_d\}x={x1​,x2​,x3​,⋯,xd​},其中xix_ixi​表示x在第i个属性上面的取值。线性模型就是试图学习一个通过属性的线性组合来进行预测的函数。

f(x)=w1x1+w2x2+⋯+wdxd+bf(x)=w_1x_1+w_2x_2+\cdots+w_dx_d+bf(x)=w1​x1​+w2​x2​+⋯+wd​xd​+b

  • 一般可以用向量形式表达。w和b都是学习的参数,通过不断调整w和b,得到一个最优的模型。

f(x)=wTx+bf(x)=w^Tx+bf(x)=wTx+b

  • 线性模型形式简单,易于建模,却孕育着机器学习领域最重要的基本思想,同时线性模型还具有特别好的解释性,因为权重的大小就直接可以表示这个属性的重要程度。

3.2.2 一维线性回归

给定数据集 D={(x1,y1),(x2,y2),(x3,y3),(x4,y4),⋯,(xm,ym)}D = \{(x_1,y_1), (x_2,y_2), (x_3,y_3), (x_4,y_4),\cdots,(x_m,y_m)\}D={(x1​,y1​),(x2​,y2​),(x3​,y3​),(x4​,y4​),⋯,(xm​,ym​)},线性回归希望能够优化出一个好的函数f(x)f(x)f(x),使得f(xi)=w⋅xi+bf(x_i) = w\cdot x_i + bf(xi​)=w⋅xi​+b能够与 yiy_iyi​ 尽可能接近。

均方误差

要衡量 f(x)f(x)f(x) 和 yyy 之间的差别,可以用它们之间的距离差异Loss=∑i=1m(f(xi)−yi)2Loss=\sum_{i=1}^m(f(x_i)-y_i)^2Loss=i=1∑m​(f(xi​)−yi​)2来衡量误差,取平方是因为误差有正负,取平方将它们全部变为正。

均方误差非常直观,有着很好的几何意义,对应于常用的欧几里得距离,基于均方误差最小化来进行模型求解的办法也称为最小二乘法

要做的事情就是找到w∗w^*w∗和b∗b^*b∗,使得(w∗,b∗)=argw,bmin∑i=1m(f(xi)−yi)2=argw,bmin∑i=1m(yi−wxi−b)2(w^*,b^*)=arg_{w,b}min\sum_{i=1}^m(f(x_i)-y_i)^2=arg_{w,b}min\sum_{i=1}^m(y_i-wx_i-b)^2(w∗,b∗)=argw,b​mini=1∑m​(f(xi​)−yi​)2=argw,b​mini=1∑m​(yi​−wxi​−b)2

求解的办法非常简单,如果求这个连续函数的最小值,那么只需要求它的偏导数,让它的偏导数等于0来估计它的参数,即:
∂Loss(w,b)∂w=2(w∑i=1mxi2−∑i=1m(yi−b)xi)=0{{\partial Loss_{(w,b)}}\over{\partial w}}=2(w\sum_{i=1}^mx_i^2-\sum_{i=1}^m(y_i-b)x_i)=0 ∂w∂Loss(w,b)​​=2(wi=1∑m​xi2​−i=1∑m​(yi​−b)xi​)=0
∂Loss(w,b)∂b=2(mb−∑i=1m(yi−wxi))=0{{\partial Loss_{(w,b)}}\over{\partial b}}=2(mb-\sum_{i=1}^m(y_i-wx_i))=0 ∂b∂Loss(w,b)​​=2(mb−i=1∑m​(yi​−wxi​))=0

可以得到www和bbb的最优解:
w=∑i=1myi(xi−xˉ)∑i=1mxi2−1m(∑i=1mxi)2w={{\sum_{i=1}^m}y_i(x_i-\bar{x})\over{{\sum_{i=1}^m}x_i^2-{{1}\over{m}}({\sum_{i=1}^m}x_i)^2}}w=∑i=1m​xi2​−m1​(∑i=1m​xi​)2∑i=1m​yi​(xi​−xˉ)​
b=1m∑i=1m(yi−wxi)b={{1}\over{m}}{\sum_{i=1}^m}(y_i-wx_i)b=m1​i=1∑m​(yi​−wxi​)

3.2.3 多维线性回归

更一般的情况是多维线性回归,有d个属性,试图学得最优模型f(x)f(x)f(x):f(xi)=wTxi+bf(x_i)=w^Tx_i+bf(xi​)=wTxi​+b,使得 ∑i=1m(f(xi)−yi)2\sum_{i=1}^m(f(x_i)-y_i)^2∑i=1m​(f(xi​)−yi​)2 最小,称为多元线性回归。同样可以使用最小二乘法对w和b进行估计,

数据集D表示为 m*(d+1) 的矩阵X
X=(x11x12⋯x1d1x21x22⋯x2d1⋮⋮⋱⋮⋮xm1xm2⋯xmd1)=(x1T1x2T1⋮⋮xmT1)X= \begin{pmatrix} x_{11} & x_{12} & \cdots & x_{1d} & 1 \\ x_{21} & x_{22} & \cdots & x_{2d} & 1 \\ \vdots & \vdots & \ddots & \vdots & \vdots \\ x_{m1} & x_{m2} & \cdots & x_{md} & 1 \\ \end{pmatrix}= \begin{pmatrix} x_1^T & 1 \\ x_2^T & 1 \\ \vdots & \vdots \\ x_m^T & 1 \\ \end{pmatrix} X=⎝⎜⎜⎜⎛​x11​x21​⋮xm1​​x12​x22​⋮xm2​​⋯⋯⋱⋯​x1d​x2d​⋮xmd​​11⋮1​⎠⎟⎟⎟⎞​=⎝⎜⎜⎜⎛​x1T​x2T​⋮xmT​​11⋮1​⎠⎟⎟⎟⎞​
将目标y也写成向量形式y=(y1,y2,⋯,ym)y=(y_1,y_2,\cdots,y_m)y=(y1​,y2​,⋯,ym​),能够得到
w∗=argwmin(y−Xw)T(y−Xw)w^*=arg_w min(y-X_w)^T(y-X_w)w∗=argw​min(y−Xw​)T(y−Xw​)

3.2.4 一维线性回归的代码实现

找一条直线去逼近这些点,就是直线离这些点的距离之和最小,

import torch
from torch import nn, optim
from torch.autograd import Variable
import numpy as np
import matplotlib.pyplot as plt# 读入数据 x 和 y
x_train = np.array([[3.3], [4.4], [5.5], [6.71], [6.93], [4.168],[9.779], [6.182], [7.59], [2.167], [7.042],[10.791], [5.313], [7.997], [3.1]], dtype=np.float32)y_train = np.array([[1.7], [2.76], [2.09], [3.19], [1.694], [1.573],[3.366], [2.596], [2.53], [1.221], [2.827],[3.465], [1.65], [2.904], [1.3]], dtype=np.float32)# 转换成 Tensor
x_train = torch.from_numpy(x_train)
y_train = torch.from_numpy(y_train)"""
首先,定义一个简单的线性模型 $y=wx+b$ ,输入参数是一维,输出参数也是一维,即一条直线,
优化参数w和b能够使得这条直线尽可能地接近这些点。如果支持GPU加速,
可以通过`model.cuda()`将模型放到GPU上。
"""class LinearRegression(nn.Module):def __init__(self):super(LinearRegression, self).__init__()# inputs and outputs is 1 dimensionself.linear = nn.Linear(1, 1)def forward(self, x):out = self.linear(x)return outif torch.cuda.is_available():model = LinearRegression().cuda()
else:model = LinearRegression()criterion = nn.MSELoss()  # 定义损失函数:均方误差
optimizer = optim.SGD(model.parameters(), lr=1e-3)  # 使用随机梯度下降进行优化# 开始训练模型
num_epochs = 1000for epoch in range(num_epochs):# 将数据Variable放入计算图if torch.cuda.is_available():inputs = Variable(x_train).cuda()target = Variable(y_train).cuda()else:inputs = Variable(x_train)target = Variable(y_train)# forwardout = model(inputs)  # 得到网络前向传播地结果loss = criterion(out, target)  # 得到损失函数# backward# 归零梯度,做反向传播和更新参数# 每次做反向传播之前,都要归零梯度# 不然梯度会累加,造成结果不收敛optimizer.zero_grad()loss.backward()optimizer.step()# 在训练过程中,每隔一段时间就将损失函数的值打印出来,确保误差越来越小if (epoch + 1) % 20 == 0:print('Epoch[{}/{}],loss {:.6f}'.format(epoch + 1, num_epochs, loss.data))# 预测结果
"""
有一些层操作如Dropout,BatchNormalization在训练和测试的时候不一样
通过model.eval()来转换这些不一样的层操作
"""
model.eval()  # 将模型变成测试模式
# 将测试数据放入网络做前向传播
predict = model(Variable(x_train).cuda())
predict = predict.cpu()
plt.plot(x_train.numpy(), y_train.numpy(), 'ro', label='Original Data')
plt.plot(x_train.numpy(), predict.data.numpy(), label='Fitting Line')
plt.show()

3.2.5 多项式回归

  • 对于一般的线性回归,由于该函数拟合出来的是一条直线,所以精度欠佳。可以考虑多项式回归,提高每个属性的次数,而不再是只使用一次回归目标函数。

  • 想要拟合的方程y=0.9+0.5×x+3×x2+2.4×x3y=0.9+0.5×x+3×x^2+2.4×x^3y=0.9+0.5×x+3×x2+2.4×x3

  • 设置参数方程y=b+w1×x+w2×x2+w3×x3y=b+w_1×x+w_2×x^2+w_3×x^3y=b+w1​×x+w2​×x2+w3​×x3

  • 首先预处理数据,将数据变成一个矩阵的形式:
    X=(x1x12x13x2x22x23⋮⋱⋮xnxn2xn3)X= \begin{pmatrix} x_{1} & x_{1}^2 & x_{1}^3 \\ x_{2} & x_{2}^2 & x_{2}^3 \\ \vdots & \ddots & \vdots \\ x_{n} & x_{n}^2 & x_{n}^3 \\ \end{pmatrix} X=⎝⎜⎜⎜⎛​x1​x2​⋮xn​​x12​x22​⋱xn2​​x13​x23​⋮xn3​​⎠⎟⎟⎟⎞​

import torch
from torch import nn, optim
from torch.autograd import Variable
import numpy as np
import matplotlib.pyplot as pltdef make_features(x):"""Builds features i.e. a matrix with columns [x,x^2,x^3].:param x::return:"""x = x.unsqueeze(1)# 使用torch.cat()实现Tensor的拼接return torch.cat([x ** i for i in range(1, 4)], 1)# unsqueeze(1)将原来Tensor大小由3变成(3,1)
w_target = torch.FloatTensor([0.5, 3, 2.4]).unsqueeze(1)
b_target = torch.FloatTensor([0.9])def f(x):"""Approximated Function:param x::return:"""# x.mm() 矩阵乘法return x.mm(w_target) + b_target[0]def get_batch(batch_size=32):"""Build a batch i.e. (x,f(x)) pair:param batch_size::return:"""random = torch.randn(batch_size)x = make_features(random)y = f(x)if torch.cuda.is_available():return Variable(x).cuda(), Variable(y).cuda()else:return Variable(x), Variable(y)class poly_model(nn.Module):def __init__(self):super(poly_model, self).__init__()self.poly = nn.Linear(3, 1)def forward(self, x):out = self.poly(x)return outif torch.cuda.is_available():model = poly_model().cuda()
else:model = poly_model()criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=1e-3)epoch = 0
while True:batch_x, batch_y = get_batch()# Forward passoutput = model(batch_x)loss = criterion(output, batch_y)print("epoch {},loss {}".format(epoch, loss.data))# Reset gradientsoptimizer.zero_grad()# Backwardloss.backward()# Update Parameteroptimizer.step()epoch += 1if loss.data < 1e-4:breakmodel.eval()
numpy_x = np.arange(-5, 5, 0.5).astype(np.float32)tensor_x = torch.from_numpy(numpy_x)feature_x = make_features(tensor_x)if torch.cuda.is_available():variable_x = Variable(feature_x).cuda()
else:variable_x = Variable(feature_x)tensor_y = f(feature_x)numpy_y = tensor_y.numpy()
output = model(variable_x)
output = output.cpu()
numpy_output = output.detach().numpy()plt.plot(numpy_x, numpy_y, 'bo', label='real curve')
plt.plot(numpy_x, numpy_output, label='fitting curve', color='r')
plt.show()

3.3 分类问题

3.3.1 问题介绍

  • 机器学习中的监督学习主要分为回归问题和分类问题,回归问题希望预测的结果是连续的,分类问题希望预测的结果是离散的。监督学习从数据中学习一个分类模型或者决策函数被称为分类器(Classifier)。
  • 分类器对新的输入进行输出预测,这个过程即称为分类(classification)。同时分类问题包括二分类和多分类问题,最著名的二分类算法:Logistic回归。

3.3.2 Logistic 起源

  • Logistic起源于对人口数量增长情况的研究,后来被应用到微生物生长情况的研究,以及解决经济学相关的问题,现在作为回归分析的一个分支来处理分类问题。

3.3.3 Logistic 分布

  • 设X是连续的随机变量,服从Logistic分布是指X的积累分布和密度函数如下。
    F(x)=P(X≤x)=11+e−(x−μ)/γF(x)=P(X\le x)={1\over{1+e^{-(x-\mu)/\gamma}}}F(x)=P(X≤x)=1+e−(x−μ)/γ1​

  • 其中μ\muμ影响中心对称点的位置,γ\gammaγ越小,中心点附近的增长速度越快

  • Logistic(Sigmoid)函数的表达式如下。
    p(x)=11+e−xp(x)={1\over{1+e^{-x}}}p(x)=1+e−x1​

  • Sigmoid函数图像

3.3.4 二分类的Logistic回归

  • Logistic回归不仅可以解决二分类问题,也可以解决多分类问题,但是二分类问题最常见,同时也具有良好的解释性。对于二分类问题,Logistic回归的目标是希望找到一个区分度足够好的决策边界,能够将两类很好的分开。

  • 假设输入的数据的特征向量 x∈Rnx\in R^nx∈Rn,那么决策边界可以表示为∑i=1nwixi+b=0\sum_{i=1}^n w_ix_i+b=0∑i=1n​wi​xi​+b=0。假设存在一个样本点使得 hw(x)=∑i=1nwixi+b>0h_w(x)=\sum_{i=1}^n w_ix_i+b\gt0hw​(x)=∑i=1n​wi​xi​+b>0,那么可以判定它的类别是1;假设存在一个样本点使得 hw(x)=∑i=1nwixi+b<0h_w(x)=\sum_{i=1}^n w_ix_i+b\lt0hw​(x)=∑i=1n​wi​xi​+b<0,那么可以判定它的类别是0.

  • 这个过程其实是一个感知机的过程,通过决策函数的符号来判断其属于哪一类。而Logistic回归要更进一步,通过找到分类概率P(Y=1)P(Y=1)P(Y=1)与输入变量x的直接关系,然后通过比较概率值来判断类别,简单来说就是通过计算下面两个概率分布:
    P(Y=0∣x)=11+ew⋅x+bP(Y=0|x)={1\over{1+e^{w\cdot x+b}}} P(Y=0∣x)=1+ew⋅x+b1​
    P(Y=1∣x)=ew⋅x+b1+ew⋅x+bP(Y=1|x)={e^{w\cdot x+b}\over{1+e^{w\cdot x+b}}} P(Y=1∣x)=1+ew⋅x+bew⋅x+b​
    ,其中w是权重,b是偏置

  • 一个事件发生的几率(odds)是指该事件发生的概率和不发生的概率的比值,比如一个事件发生的概率是P,那么该事件发生的几率是p/(1-p),该事件的对数几率或logit函数是:
    logit(p)=logp1−plogit(p)=log{{p}\over{1-p}}logit(p)=log1−pp​

  • 对于Logistic回归而言,可以得到:
    logP(Y=1∣x)1−P(Y=1∣x)=w⋅x+blog{{P(Y=1|x)}\over{1-P(Y=1|x)}}=w\cdot x+b log1−P(Y=1∣x)P(Y=1∣x)​=w⋅x+b

  • 在Logistic回归模型中,输出Y=1的对数几率是输入x的线性函数,这也就是Logistic回归名称的原因。

  • 由p(x)=11+e−xp(x)={{1}\over{1+e^{-x}}}p(x)=1+e−x1​,则可以得到另一种Logistic回归的定义,即线性函数的值越接近正无穷,概率值就越接近1;线性函数的值越接近负无穷,概率值越接近0。因此Logistic回归的思路是先拟合决策边界,这里的决策边界不局限于线性,还可以是多项式,在建立这个边界和分类概率的关系,从而得到二分类情况下的概率。

3.3.5 模型的参数估计

上面介绍了Logistic回归模型的建立,下面通过极大似然估计来求出模型中的参数。对于给定的数据训练集T={(x1,y1),(x2,y2),⋯,(xn,yn)}T=\{(x_1,y_1),(x_2,y_2),\cdots,(x_n,y_n)\}T={(x1​,y1​),(x2​,y2​),⋯,(xn​,yn​)},其中xi∈Rn,yi∈{0,1}x_i\in R^n,y_i\in\{0,1\}xi​∈Rn,yi​∈{0,1},假设P(Y=1∣x)=π(x)P(Y=1|x)=\pi(x)P(Y=1∣x)=π(x),那么P(Y=0∣x)=1−π(x)P(Y=0|x)=1-\pi(x)P(Y=0∣x)=1−π(x),所以似然函数可以有如下的表达式:∏i=1n[π(xi)]yi[1−π(xi)]1−yi\prod_{i=1}^n[\pi(x_i)]^{y_i}[1-\pi(x_i)]^{1-y_i}i=1∏n​[π(xi​)]yi​[1−π(xi​)]1−yi​
取对数之后的对数似然函数为:
L(w)=∑i=1n[yilogπ(xi)+(1−yi)log(1−π(xi))]=∑i=1n[yilogπ(xi)1−π(xi)+log(1−π(xi))]=∑i=1n[yi(w⋅xi+b)−log(1+ew⋅xi+b)]L(w)=\sum_{i=1}^n[y_ilog\pi(x_i)+(1-y_i)log(1-\pi(x_i))] \\ =\sum_{i=1}^n[y_ilog{\pi{(x_i)}\over{1-\pi(x_i)}}+log(1-\pi(x_i))] \\ =\sum_{i=1}^n[y_i(w\cdot x_i+b)-log(1+e^{w\cdot x_i+b})] L(w)=i=1∑n​[yi​logπ(xi​)+(1−yi​)log(1−π(xi​))]=i=1∑n​[yi​log1−π(xi​)π(xi​)​+log(1−π(xi​))]=i=1∑n​[yi​(w⋅xi​+b)−log(1+ew⋅xi​+b)]
对L(w)L(w)L(w)求极大值就能够得到w的估计值,可以使用最简单的梯度下降法求得。
求出梯度之后就可用迭代的梯度下降来求解。

3.3.6 Logistic回归的代码实现

  • 先从data.txt文件中读取数据,然后通过Matplotlib将数据点画出来
import matplotlib.pyplot as plt# 每个数据点是一行,每行中前面两个数据表示x坐标和y坐标,最后一个数据表示其类别
with open('data.txt', 'r') as f:data_list = f.readlines()data_list = [i.split('\n')[0] for i in data_list]data_list = [i.split(',') for i in data_list]data = [(float(i[0]), float(i[1]), float(i[2])) for i in data_list]x0 = list(filter(lambda x: x[-1] == 0.0, data))
x1 = list(filter(lambda x: x[-1] == 1.0, data))
plot_x0_0 = [i[0] for i in x0]
plot_x0_1 = [i[1] for i in x0]
plot_x1_0 = [i[0] for i in x1]
plot_x1_1 = [i[1] for i in x1]
plt.plot(plot_x0_0, plot_x0_1, 'ro', label='x_0')
plt.plot(plot_x1_0, plot_x1_1, 'bo', label='x_1')
plt.legend(loc='best')
plt.show()
  • 每个数据点是一行,每行中前面两个数据表示x坐标和y坐标,最后一个数据表示其类别,numpy中的loadtxt方法可以方便的读取CSV格式的文件,如下所示
import matplotlib.pyplot as plt
import numpy as np# # 每个数据点是一行,每行中前面两个数据表示x坐标和y坐标,最后一个数据表示其类别
data = np.loadtxt('data.txt', delimiter=',', dtype=np.float32)x0 = list(filter(lambda x: x[-1] == 0.0, data))
x1 = list(filter(lambda x: x[-1] == 1.0, data))
plot_x0_0 = [i[0] for i in x0]
plot_x0_1 = [i[1] for i in x0]
plot_x1_0 = [i[0] for i in x1]
plot_x1_1 = [i[1] for i in x1]
plt.plot(plot_x0_0, plot_x0_1, 'ro', label='x_0')
plt.plot(plot_x1_0, plot_x1_1, 'bo', label='x_1')
plt.legend(loc='best')
plt.show()
  • 这些数据点被分为两类,一类是红色的点,一类是蓝色的点,希望通过Logistic回归将其分开
  • 在进行逻辑斯蒂回归之前,我们先来看一下如何利用SVM进行分类。
import numpy as np
from sklearn import svm# 每个数据点是一行,每行中前面两个数据表示x坐标和y坐标,最后一个数据表示其类别
data = np.loadtxt('data.txt', delimiter=',', dtype=np.float32)
x_data = data[:, :-1]
y_data = data[:, -1]# 训练线性支持向量机来学习类边界
svc = svm.LinearSVC(C=1, loss='hinge', max_iter=1000000)
print(svc)
svc.fit(X=x_data, y=y_data)
accuracy = svc.score(X=x_data, y=y_data)
print(accuracy) # 0.998
  • 定义Logistic回归的模型,以及二分类问题的损失函数和优化方法。
import torch
from torch.autograd import Variable
from torch import nn
import torch.optim as optim
import matplotlib.pyplot as plt
import numpy as np# 每个数据点是一行,每行中前面两个数据表示x坐标和y坐标,最后一个数据表示其类别
with open('data.txt', 'r') as f:data_list = f.readlines()data_list = [i.split('\n')[0] for i in data_list]data_list = [i.split(',') for i in data_list]data = [(float(i[0]), float(i[1]), float(i[2])) for i in data_list]# 分类
x0 = list(filter(lambda x: x[-1] == 0.0, data))
x1 = list(filter(lambda x: x[-1] == 1.0, data))plot_x0_0 = [i[0] for i in x0]
plot_x0_1 = [i[1] for i in x0]
plot_x1_0 = [i[0] for i in x1]
plot_x1_1 = [i[1] for i in x1]
plt.plot(plot_x0_0, plot_x0_1, 'ro', label='x_0')
plt.plot(plot_x1_0, plot_x1_1, 'bo', label='x_1')
plt.legend(loc='best')x_data = [[i[:2] for i in data]]
y_data = [[i[2] for i in data]]
x_data = np.array(x_data).astype('float32')
x_data = x_data.reshape(100, 2)
print(x_data)
y_data = np.array(y_data).astype('float32')
y_data = y_data.reshape(100, 1)
print(y_data)
x_data = torch.tensor(x_data)
y_data = torch.tensor(y_data)if torch.cuda.is_available():x_data = x_data.cuda()y_data = y_data.cuda()# 定义Logistic回归模型
class LogisticRegression(nn.Module):def __init__(self):super(LogisticRegression, self).__init__()self.lr = nn.Linear(2, 1)self.sm = nn.Sigmoid()def forward(self, x):x = self.lr(x)x = self.sm(x)return xlogistic_model = LogisticRegression()
if torch.cuda.is_available():logistic_model.cuda()criterion = nn.BCELoss()  # 二分类的损失函数
# 随机梯度下降优化函数
optimizer = torch.optim.SGD(logistic_model.parameters(), lr=1e-3, momentum=0.9)# 训练模型
num_epochs = 50000
for epoch in range(num_epochs):if torch.cuda.is_available():x = Variable(x_data).cuda()y = Variable(y_data).cuda()else:x = Variable(x_data)y = Variable(y_data)########################### forward ###########################out = logistic_model(x)loss = criterion(out, y)# 判断输出结果,如果大于0.5就等于1,小于0.5就等于0,通过这个来计算模型分类的准确率mask = out.ge(0.5).float()correct = (mask == y).sum()acc = correct.data / x.size(0)########################### backward ###########################optimizer.zero_grad()loss.backward()optimizer.step()if (epoch + 1) % 1000 == 0:print('epoch {},loss {:.2f},acc {}/{}'.format(epoch + 1, loss.data, correct.data, x.size(0)))

模型中学习的参数w1,w2,bw_1,w_2,bw1​,w2​,b其实构成了一条直线w1x+w2y+b=0w_1x+w_2y+b=0w1​x+w2​y+b=0,在直线上方的点是一类,在直线下方点的又是一类。

w = logistic_model.lr.weight
w = w.data.cpu()
w0 = w.numpy()[0][0]
w1 = w.numpy()[0][1]
b = logistic_model.lr.bias
b = b.data.cpu()
b = b.numpy()[0]
plot_x = np.arange(30, 100, 0.1)
plot_y = (-w0 * plot_x - b) / w1
plt.plot(plot_x, plot_y)
plt.savefig('logistic_regression_result.png')

3.4 简单的多层全连接前向网络

https://hulin.blog.csdn.net/article/details/107816060

3.5 深度学习的基石:反向传播算法

反向传播算法就是一个有效的求解梯度的算法,本质上就是一个链式求导法则的应用,然而这个如此简单且显而易见的方法,却是在Roseblatt提出感知器算法后近30年才被发明和普及的。

3.5.1 链式法则

考虑一个简单的函数f(x,y,z)=(x+y)zf(x,y,z)=(x+y)zf(x,y,z)=(x+y)z,当然可以直接求出这个函数的微分,但是这里要使用链式法则,令q=x+yq=x+yq=x+y,那么f=qzf=qzf=qz,对于这两个算式,分别求出它们的微分,∂f∂q=z,∂f∂z=q{{\partial f}\over{\partial q}}=z,{{\partial f}\over{\partial z}}=q∂q∂f​=z,∂z∂f​=q,同时q是x和y的和,所以能够得到∂qx=1,∂qy=1{{\partial q}\over x}=1,{{\partial q}\over y}=1x∂q​=1,y∂q​=1。链式法则告诉我们如何来计算出它们的值:

∂f∂x=∂f∂q∂q∂x{{\partial f}\over{\partial x}}={{\partial f}\over{\partial q}}{{\partial q}\over{\partial x}}∂x∂f​=∂q∂f​∂x∂q​
∂f∂y=∂f∂q∂q∂y{{\partial f}\over{\partial y}}={{\partial f}\over{\partial q}}{{\partial q}\over{\partial y}}∂y∂f​=∂q∂f​∂y∂q​
∂f∂z=q{{\partial f}\over{\partial z}}=q∂z∂f​=q

  • 通过链式法则知道,如果需要对其中的元素求导,可以一层一层求导,最后将结果乘起来,这就是链式法则的核心,也是反向传播算法的核心。

3.5.2 反向传播算法

本质上反向传播算法只是链式法则的一个应用,使用之前的例子:q=x+yq=x+yq=x+y, f=qzf=qzf=qz,通过计算图可以将这个过程表达出来。

上面的数字表示数值,下面的数字表示求出的梯度,我们可以一步一步地看反向传播算法的实现。首先从最后开始,梯度当然是1,然后计算
∂f∂q=z=−4,∂f∂z=3{{\partial f}\over{\partial q}}=z=-4,{{\partial f}\over{\partial z}}=3∂q∂f​=z=−4,∂z∂f​=3
,接着计算
∂f∂x=∂f∂q∂q∂x=−4×1=−4{{\partial f}\over{\partial x}}={{\partial f}\over{\partial q}}{{\partial q}\over{\partial x}}=-4\times 1=-4∂x∂f​=∂q∂f​∂x∂q​=−4×1=−4
∂f∂y=∂f∂q∂q∂y=−4×1=−4{{\partial f}\over{\partial y}}={{\partial f}\over{\partial q}}{{\partial q}\over{\partial y}}=-4\times 1=-4∂y∂f​=∂q∂f​∂y∂q​=−4×1=−4

直观上看,反向传播算法是一个优雅的局部过程,每次求导只是对当前的运算求导,求解每层网络的参数都是通过链式法则,将前面的结果求出不断迭代到这一层,所以说这是一个传播过程。

3.5.3 Sigmoid 函数举例

  • 通过Sigmoid函数来演示反向传播过程在一个复杂函数上是如何进行的。

f(w,x)=11+e−(w0x0+w1x1+w2)f(w,x)={1\over{1+e^{-(w_0x_0+w_1x_1+w_2)}}}f(w,x)=1+e−(w0​x0​+w1​x1​+w2​)1​

需要求解出

∂f∂w0,∂f∂w1,∂f∂w2{\partial f\over \partial w_0},{\partial f\over \partial w_1},{\partial f\over \partial w_2}∂w0​∂f​,∂w1​∂f​,∂w2​∂f​

  • 首先将这个函数抽象成一个计算图表示。

f(x)=1xf(x)={1\over x}f(x)=x1​
fc(x)=c+xf_c(x)={c+x}fc​(x)=c+x
f(x)=exf(x)={e^x}f(x)=ex
f(x)=axf(x)={ax}f(x)=ax

这样就能画出如图所示的计算图

同样图中的数字表示数值,下面的数字表示梯度,从后往前计算一下各个参数的梯度。首先最后面的梯度是1,然后经过1x1\over xx1​这个函数,这个函数的梯度是−1x2-{1\over x^2}−x21​,所以往前传播的梯度是1×−11.372=−0.531\times -{1\over 1.37^2}=-0.531×−1.3721​=−0.53,然后+1这个操作,梯度不变,接着是exe^xex这个运算,它的梯度就是−0.53×e−1=−0.2-0.53\times e^{-1}=-0.2−0.53×e−1=−0.2,这样不断往后传播就能求得每个参数的梯度。

3.6 各种优化算法的变式

https://hulin.blog.csdn.net/article/details/107815873

3.7 处理数据和训练模型的技巧

https://hulin.blog.csdn.net/article/details/107824845

3.8 多层全连接神经网络实现MNIST手写数字分类

https://hulin.blog.csdn.net/article/details/107825032

参考资料

  1. 廖星宇《深度学习入门之PyTorch》电子工业出版社

深度学习入门之PyTorch学习笔记:多层全连接网络相关推荐

  1. 深度学习入门之PyTorch学习笔记:卷积神经网络

    深度学习入门之PyTorch学习笔记 绪论 1 深度学习介绍 2 深度学习框架 3 多层全连接网络 4 卷积神经网络 4.1 主要任务及起源 4.2 卷积神经网络的原理和结构 4.2.1 卷积层 1. ...

  2. 深度学习入门之PyTorch学习笔记:深度学习框架

    深度学习入门之PyTorch学习笔记 绪论 1 深度学习介绍 2 深度学习框架 2.1 深度学习框架介绍 2.1.1 TensorFlow 2.1.2 Caffe 2.1.3 Theano 2.1.4 ...

  3. 深度学习入门之PyTorch学习笔记:深度学习介绍

    深度学习入门之PyTorch学习笔记:深度学习介绍 绪论 1 深度学习介绍 1.1 人工智能 1.2 数据挖掘.机器学习.深度学习 1.2.1 数据挖掘 1.2.2 机器学习 1.2.3 深度学习 第 ...

  4. 深度学习入门之PyTorch学习笔记

    深度学习入门之PyTorch学习笔记 绪论 1 深度学习介绍 2 深度学习框架 3 多层全连接网络 4 卷积神经网络 5 循环神经网络 6 生成对抗网络 7 深度学习实战 参考资料 绪论 深度学习如今 ...

  5. 干货|《深度学习入门之Pytorch》资料下载

    深度学习如今已经成为了科技领域中炙手可热的技术,而很多机器学习框架也成为了研究者和业界开发者的新宠,从早期的学术框架Caffe.Theano到如今的Pytorch.TensorFlow,但是当时间线来 ...

  6. 深度学习入门教程UFLDL学习实验笔记三:主成分分析PCA与白化whitening

     深度学习入门教程UFLDL学习实验笔记三:主成分分析PCA与白化whitening 主成分分析与白化是在做深度学习训练时最常见的两种预处理的方法,主成分分析是一种我们用的很多的降维的一种手段,通 ...

  7. 深度学习入门教程UFLDL学习实验笔记一:稀疏自编码器

     深度学习入门教程UFLDL学习实验笔记一:稀疏自编码器 UFLDL即(unsupervised feature learning & deep learning).这是斯坦福网站上的一篇 ...

  8. Pytorch深度学习入门与实战(笔记)

    目录 第二章 1.张量数据类型 (1)查看张量数据类型 (2)修改张量数据类型

  9. 深度学习(七十三)pytorch学习笔记

    先吐槽一下,深度学习发展速度真的很快,深度学习框架也在逐步迭代,真的是苦了俺这搞深度学习程序员.本人从三年前开始学深度学习开始,这些深度学习框架也是一个换过一个,从keras.theano.caffe ...

最新文章

  1. 当老板说要把公司当家时,他在说...
  2. NoDrives-显示与隐藏驱动器【盘符的显示与隐藏】
  3. 基于PI Pico一些基础实验
  4. (0054)iOS开发之制作静态库详解
  5. scala使用reduce和fold方法遍历集合的所有元素
  6. SunPinyin: Linux下最好用的拼音输入法,MacOSX下也是不错的,还免费,可以不用买IMKQIM了...
  7. python颜色识别算法_纯Python编写K-means算法,提取图片中的主体颜色
  8. python 命令行 模块_深入浅析Python 命令行模块 Click
  9. Haproxy相关概念解析
  10. 2012.4.16总结(三)
  11. 数据库的基本操作(增删改查)
  12. 下载并打开Github源码教程
  13. 一次搞懂 Android 音频开发
  14. 计算机绘图实训体会,CAD实习心得体会
  15. Python_Python遍历列表的四种方法
  16. iOS-使用Masonry布局不能立即获取到frame
  17. 西方金融交易员揭露行业潜规则
  18. 常用CASE工具介绍 1
  19. 解决禅道(ZenTao)Mysql启动不了的问题
  20. c语言 拷入pdf,怎么样才能把PDF文档从电脑拷到U盘

热门文章

  1. MS SQL 获取字符串最后出现的字符串及位置
  2. 《构建之法》阅读笔记4
  3. Kettle 合并记录报错!
  4. Google Chrome v48.0.2564.
  5. C++用递归方式实现在对不更改随机数组的情况下查找最大值
  6. CakePHP下使用paginator需要对多个字段排序的做法
  7. jquery1.9学习笔记 之选择器(基本元素五)
  8. poj 1041(欧拉回路+输出字典序最小路径)
  9. Delphi匿名方法(三):扩展本地变量的生命周期
  10. ASP.NET MVC中使用AJAX(XMLHttpRequest、Microsoft AJAX Library......)