深度学习入门

更新时间:2020-11-12 15:41:26点击次数:277次

前言

随着计算机技术的发展以及相关硬件条件的不断进步,大数据成为当今社会发展的趋势,机器学习的相关算法已经不能很好的解决大数据场景中的需求,所以在机器学习的基础上,一种叫做深度学习的新研究方向出现了。此篇博客是我第一篇博客,主要目的是为了和大家分享自己的一些总结,同时也欢迎大家一起讨论学习。
 预备知识
由于Python有非常多的包,能为我们的coding提供极大便利,所以我们选择Python作为深度学习的编程语言,同时为了方便神经网络的搭建,我们需要选择一种深度学习框架(例如比较流行的Tensorflow,Cafe,Pytorch等等),我所使用的框架是Pytorch,这篇博客中也主要介绍Pytorch的使用。
Python
Python从官网直接下载即可,关于入门书籍我推荐《Python编程:从入门到实践》,深度学习算法的编写不需要很强的coding能力,只需要了解基本的语法即可,大概需要花费一周的时间,书籍pdf链接如下:
 链接:https://pan.baidu.com/s/1R3b-TJhIZqzvlCgRmb7LOw
提取码:6wgf
Anaconda的安装
Anaconda是一个开源的Python发行版本,包括了python,conda等180多个科学包及其依赖项。由于深度学习所需要的包的数量很大,通过自己逐一下载,不仅麻烦而且浪费时间,可以通过直接下载Anaconda,很好的解决这些问题。Anaconda的安装过程如下:
(1).首先前往官网下载合适自己电脑版本的Anaconda客户端(https://www.anaconda.com/download/#macos),因为我电脑上安装的python版本是3.7,所以选择64位版本的客户端安装,如下:

(2).下载结束后进行安装,前几步点击next,直至Advanced Options,为了方便以后我们自行创建环境,此时需要将添加环境变量选项勾选上,
(3).安装完成后我们通过将IDE中的编译环境设置为Anaconda,如图4-16,便可使用所有Anaconda中的科学包了
一些常用包的介绍
numpy
NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库所以在深度学习中进行矩阵的运算,我们都可以借助numpy包来完成。
1 创建矩阵
 矩阵的创建有多种方式,这里我们简要介绍numpy.array(),numpy.zeros(),numpy.ones(),numpy.full(),numpy.arange(),numpy.linspace(),numpy.random。
1.1 numpy.array()
 numpy.array是一种最直接的创建矩阵的方式,在括弧中,我们可以直接输入我们想要的矩阵元素,例如
import numpy as np
A=np.array([1,2,3,4,5])
print(A)
这样我们可以得到一个名为A的向量,打印出来是这样的
[1,2,3,4,5]

或许我们想创建一个多维矩阵,可以通过输入每个维度的元素来实现,例如
B=np.array([[1,2,3],[4,5,6]])
print(B)
--------------------------------------------------------------------
[[1,2],
[3,4]]
这里我们有一个需要注意的点是假如我们所要创建的矩阵是n维的,就需要从外到内一层一层的创建,外层的[]需要使用n-1组,例如
C=np.array([[[1,2],[3,4]],[[5,6],[7,8]]])
print(C)
print("C的维度是"+str(C.shape))
--------------------------------------------------------------------
[[[1,2]
[3,4]]
[[5,6]
[7,8]]]
C的维度是(2,2,2) //这里我们使用了两层外层[]
1.2 numpy.zeros()
 numpy.zeros()这个函数的作用是生成一个元素全为0的矩阵,矩阵的大小由我们自己设置,例如
D=np.zeros((3,4))
print(D)
--------------------------------------------------------------------
[[0.,0.,0.,0.]
[0.,0.,0.,0.]
[0.,0.,0.,0.]]
注意:括号内输入矩阵的维度必须是元组的形式,不然会报错。
1.3 numpy.ones()
 numpy.zeros()这个函数的作用是生成一个元素全为1的矩阵,矩阵的大小由我们自己设置,例如
E=np.ones((2,3))
print(E)
--------------------------------------------------------------------
[[1.,1.,1.]
[1.,1.,1.]]
这里生成矩阵的数据类型和numpy.zeros()一样都是float64,如果需要指定数据类型可以在生成矩阵时,设置dtype的类型。
1.4 numpy.full()
 numpy.full()中有两个关键参数,第一个参数是shape用于设置矩阵维度,第二个参数是full_value用于设置矩阵元素,例如
F=np.full(shape=(2,3),full_value=312)
print(F)
--------------------------------------------------------------------
[[312,312,312]
[312,312,312]]
1.5 numpy.arange()
和matlab中的arange函数相似,通过设置一个范围再通过改变步长对矩阵初始化,例如
G=numpy.arange(0,12,2)
print(G)
G.reshape(3,-1) //可以通过reshape变成我们想要的形状
--------------------------------------------------------------------
[0,2,4,6,8,10]
1.6 numpy.linspace()
和matlab中的linspace函数相似,通过设置一个范围再通过设置元素个数对矩阵初始化,例如
H=np.linspace(0,12,6)
print(H)
H.reshape(3,-1)//可以通过reshape变成我们想要的形状
--------------------------------------------------------------------
[0,2.4,4.8,7.2,9.6,12]
1.7 numpy.random
 numpy.random主要通过生成的随机数初始化矩阵,例如
a=np.random.rand(3,4) //用0-1之间的随机数初始化矩阵
a1=np.ranom.randn(3.4) //用一组满足高斯分布的随机数初始化矩阵
a2=np.random.ranint(1,5,3) //用给定范围内的整数初始化矩阵
2 矩阵的数学运算
numpy支持数学中的各种运算,比如加减乘除等等。同时由于我们运算的对象是矩阵,在进行运算时需要注意运算对象的维度,尤其是在进行叉乘运算时,这一小节主要介绍叉乘运算。
 两个矩阵的叉乘在numpy中可以通过numpy.dot()函数实现,在使用函数时要遵循矩阵乘法的规则,例如
A=np.array([[1,2],[3,4],[5,6]])
B=np.ones((2,2))
C=np.dot(A,B) #也可以写成A.dot(B)
print(C)
--------------------------------------------------------------------
[[3.,3.]
[7.,7.]
[11.,11.]]
3 矩阵的拼接和拆分
 有时候我们需要对矩阵进行拼接操作,numpy为我们提供了.concatenate(),.vstack(),.hstack()等函数
A=np.array([[1,2],[3,4]])
B=np.array([5,6])
print(np.concatenate((A,B.reshape(1,-1)))) #axis默认为0
print(np.concatenate((A,B.reshape(-1,1)),axis=1)) #沿列拼接
print(np.vstack((A,B)))#沿行拼接
print(np.hstack((A,B.reshape(-1,1)))) #沿列拼接
--------------------------------------------------------------------
[[1 2]
 [3 4]
 [5 6]]
[[1 2 5]
 [3 4 6]]
注意:输入的矩阵应该变成元组的形式,同时需要注意矩阵的维度应当相等。
 若要对矩阵进行分割操作,我们可以使用.split()函数
C=np.array([[1,2,3],[4,5,6]])
C1,C2=np.split(C,[1])
print("C1:"+str(C1))
print("C2:"+str(C2))
C3,C4,C5=np.split(C,[1,2],axis=1) #axis默认为0,为1时沿列分割
print("C3:"+str(C3))
print("C4:"+str(C4))
print("C5:"+str(C5))
--------------------------------------------------------------------
C1:[[1 2 3]]
C2:[[4 5 6]]
C3:[[1]
 [4]]
C4:[[2]
 [5]]
C5:[[3]
 [6]]
matplotlib
matplotlib是python中的一个绘图库,我们可以使用它来绘制各种我们需要的图形。其中matplotlib.pyplot.plot()可以用来绘制折线图,matplotlib.pyplot.scatter()可以绘制散点图,matplotlib.pyplot.bar()可以用来绘制条形图,下面来依此介绍这些函数。
matplotlib.pyplot.plot()
下图是官方文档中给出的函数介绍,我们可以通过改变color,linestyle,maker等参数的值来改变绘制图形的外形,例如
import numpy as np
import matplotlib.pyplot as plt
x=np.linspace(0,10,100)
plt.plot(x,np.sin(x),color='b',linestyle=':')
plt.plot(x,np.cos(x))
plt.show()
这里我们在一幅图里绘制了两条曲线,我们改变了sin(x)的线性和颜色,为了使图像显示的更加容易被理解,我们还可以添加如下语句
plt.xlabel("x")
plt.ylabel("y") #为两个坐标轴增加一些注释
plt.legend() #给图像加上图例
plt.title("Pic of sin and cos")  #增加一个标题
plt.show()
matplotlib.pyplot.scatter()
用于绘制散点图
x=np.random.randn(100)
y=np.linspace(-3,3,100)
plt.scatter(x,y)
plt,show()
matplotlib.pyplot.bar()
用于绘制条形图
x=[1,2,3,4]
y=[4,6,2,7]
plt.bar(x,y)
plt.xlabel("x")
plt.ylabel("y")
plt.show()
Pytorch
PyTorch是一个基于Torch的Python开源机器学习库,用于自然语言处理等应用程序。
Pytorch基础
Tensor
张量是Pytorch中的基本运算单位,和numpy中的array相似,但是numpy中生成的矩阵只能在CPU中运行,而tensor则可以在电脑GPU中运行大大提升了计算速度。
1 初始化
tensor的生成方式和array相类似,可以直接初始化
import torch as t
A=t.tensor([1,2],[3,4])
print(A)
print(A.size()) #和numpy中的.shape类似
--------------------------------------------------------------------
tensor([[1, 2],
        [3, 4]])
torch.Size([2, 2])
用满足[0,1]分布的随机数初始化tensor
B=t.rand(3,4) #矩阵维度不需要表示成元组的形式
print(B)
--------------------------------------------------------------------
tensor([[0.5880, 0.9161, 0.8885, 0.6110],
        [0.1940, 0.5355, 0.7517, 0.8142],
        [0.2610, 0.1683, 0.1684, 0.0994]])
用符合正态分布的随机数初始化tensor
C=t.randn(2,3)
print(C)
--------------------------------------------------------------------
tensor([[-0.2420, -0.0596, -1.2083],
        [ 1.1968,  0.6357, -1.3943]])
用1填充tensor
D=t.ones(2,2)
print(D)
--------------------------------------------------------------------
tensor([[1., 1.],
        [1., 1.]])
用0填充tensor
E=t.zeros(3,3)
print(E)
--------------------------------------------------------------------
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])
初始化一个单位矩阵
F=t.eye(4,4)
print(F)
--------------------------------------------------------------------
tensor([[1., 0., 0., 0.],
        [0., 1., 0., 0.],
        [0., 0., 1., 0.],
        [0., 0., 0., 1.]])
若不特别声明,初始化的矩阵默认保存在CPU中,可以通过.cuda的方法将它保存到GPU中,因为我的电脑显卡不支持cuda,所以这里不进行演示。
tensor和array的相互转换
 通过.numpy()可以将tensor转换为array,同样通过from_numpy可以将array转换为tensor。
A=t.rand(3,4)
print(A.type())
numpy_A=A.numpy()
print(numpy_A)
tensor_A=t.from_numpy(numpy_A)
print(tensor_A.type())
--------------------------------------------------------------------
torch.FloatTensor
[[0.3733294  0.3904935  0.20588875 0.55970335]
 [0.46081507 0.9074856  0.27559114 0.17122763]
 [0.50491863 0.48301417 0.8219007  0.43779963]] #numpy没有type
torch.FloatTensor
1Pytorch的求导机制

众所周知,训练一个神经网络的关键就在于对损失函数求导,使用Pytorch可以很轻松的求出计算过程中的导数,只要我们初始化张量时,设置requires_grad为True
import torch as t
a=t.tensor([1,2,3],dtype=float,requires_grad=True)
print(a)
--------------------------------------------------------------------
tensor([1., 2., 3.], dtype=torch.float64, requires_grad=True)
注意:只有float类型的tensor才能设置requires_grad,如果我们输入的tensor是其他类型记得要先进行转换。
 设置好requires_grad后,通过.backward()便可以自动计算出计算过程中每一步的梯度。
b=t.tensor([2,2,2])
c=a**2+b**2
y=t.sum(c)
y.backward()
print(a.grad)
print(b.grad)
print(c.grad)
--------------------------------------------------------------------
tensor([2., 4., 6.], dtype=torch.float64)
None # 因为b没有设置requires_grad,所以默认为False,无法自动求得导数
为了验证求导的正确性,我们自己验算一下,发现结果正确
注意:自动求导的过程中每次求得的梯度会累加,所以我们在使用梯度下降法时,每次更新完参数后需要将梯度归0。

我们所创建的张量在计算过程中叫做叶子节点,其他的中间计算结果叫做结果变量。在进行.backward()时,grad_fn属性计算了我们的计算过程,并且可以通过next_functions查看前面的计算过程.
print(y.grad_fn)
print(y.grad_fn.next_functions)
--------------------------------------------------------------------
<SumBackward0 at 0x1d3072c6bc8>
((<AddBackward0 at 0x1d3072c60c8>, 0),)
在自动求导的过程中,就是按照这样的顺序一步步向前求导,直至到达叶子节点。
神经网络包nn
torch.nn是专门为神经网络设计的模块化接口。在nn里包含了很多构成神经网络的基本函数,其中nn.Module是搭建神经网络重要的一个基类,在nn.functional这个类中包含了很多没有可学习参数的方法,例如ReLu,pool等。
import torch.nn as nn
import torch.nn.functional as f
class net(nn.Module):
 def __init__(self):
  super().__init__()
  self.fc1=nn.Linear(100,50)
  self.fc2=nn.Linear(50,20)
  self.fc2=nn.Linear(20,3)
 def forward(self,x):
  x=self.fc1(x)
  x=f.ReLu(x)
  x=self.fc2(x)
  x=f.ReLu(x)
  x=self.fc3(x)
  x=f.sigmoid(x)
  return x
Net=net()
print(Net)
--------------------------------------------------------------------
net(
  (fc1): Linear(in_features=100, out_features=50, bias=True)
  (fc2): Linear(in_features=20, out_features=3, bias=True)
)
深度学习

深度学习是机器学习中一个新的分支,最早的机器学习算法可以追溯到20世纪初,到今天为止,已经发展了100多年了。随着计算机的不断发展以及现代社会数据量的不断增多,深度学习诞生了。深度学习的概念源于人工神经网络的研究,后产生了很多深层的神经网络,例如卷积神经网络,循环神经网络等等,其中卷积神经网络常被用来处理图像,而循环神经网络多用于语音识别,视频处理。

基本原理

深度学习就是搭建一个深层的神经网络,通过不断向这个网络喂数据,计算出损失值后,进行反向传播以达到更新网络参数的目的。只要网络层数够多,在理论上我们的网络可以拟合出任意的曲线,以达到分类预测的目的。
 神经网络一般分成输入层,中间层和输出层,单个的神经元是网络的基本组成单位。

如上图所示,每个神经元包含一个权重矩阵,偏差和一个激活函数,其中z为输入特征和权重矩阵相乘的结果。

其中上标l代表当前输入的层数,g( )代表不同的激活函数。

激活函数
 激活函数的主要作用于加权后的特征变量,并赋予他们非线性,增加模型的非线性拟合程度,如果将所有隐藏层中的激活函数都选择为线性函数,那么这个模型的输出一直在做输入的线性变换,无论增加多少隐藏层,都与训练单层前馈网络的效果差不多。
 常用的激活函数有sigmoid,tanh,ReLu,LeakyReLu等,各函数表达式如下:
 其中sigmoid函数很少使用,因为此激活函数容易发生梯度消失导致学习速率变慢甚至停止,一般多用于二分类问题的输出处。ReLu和LeakyReLu函数的缺点是在0处的导数不存在,但是一般来说输入不会恰好为0,所以这个缺点可以忽略。模型的训练速度往往会因为激活函数的不同而不同。

反向传播
 深度学习中学习的过程其实就是更新参数的过程,而更新参数的过程就是反向传播的过程一般与梯度下降法一起使用。当输入变量到模型后会得到一个预测值,一般用表示,此时需要利用损失函数来计算预测值与真实值之间的差值,损失函数如式1。梯度下降法就会对网络中所有权重计算损失函数的梯度,分别设置好学习率,并沿着梯度下降的方向更新权重和偏差,如式2和3,以减小损失值。

本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息