什么是深度学习
机器学习是实现人工智能的一种途径。
深度学习是机器学习的一个子集,也就是说深度学习是实现机器学习的一种方法
传统机器学习算术依赖人工设计特征,并进行特征提取,而深度学习方法不需要人工,而是依赖算法自动提取特征。
深度学习模仿人类大脑的运行方式,从经验中学习获取知识。这也是深度学习被看做黑盒子,可解释性差的原因。
应用场景
Pytorch
一个 Python 深度学习框架,它将数据封装成张量( Tensor )来进行处理。 PyTorch 中的张量就是元素为同一种数据类 型的多维矩阵。在 PyTorch 中,张量以 " 类 " 的形式封装起来,对张量的一些运算、处理的方法被封装在类中。
张量的创建
1.基本创建方式
torch.tensor 根据指定数据创建张量
torch.Tensor 根据形状创建张量, 其也可用来创建指定数据的张量
torch.IntTensor、torch.FloatTensor、torch.DoubleTensor 创建指定类型的张量
2.创建线性和随机张量
torch.arange 和 torch.linspace 创建线性张量
torch.random.init_seed 和 torch.random.manual_seed 随机种子设置
torch.randn 创建随机张量
3.创建0和1张量
torch.ones 和 torch.ones_like 创建全 1 张量
torch.zeros 和 torch.zeros_like 创建全 0 张量
torch.full 和 torch.full_like 创建全为指定值张量
4.张量的元素类型转换
data.type(torch.DoubleTensor)
data.double()
代码示例
python
import torch
import numpy as np
# 1. torch.tensor() 根据指定数据创建张量
print(10)
print(torch.tensor(10))
data_np = np.random.rand(2,3)
print(data_np)
print(torch.tensor(data_np))
data = [[1.,2,3],[2,3,4]]
print(data)
print(torch.tensor(data))
print('-'*60)
# 2. torch.Tensor() 根据指定形状创建张量
print(torch.Tensor(2))
print(torch.Tensor([2])) # float32
print('-'*60)
# 3. 创建指定类型的张量
print(torch.IntTensor(2,3)) #创建2行3列, dtype 为 int32 的张量
print(torch.ShortTensor((2,3))) # int16
print(torch.LongTensor([2,3])) # int64
print(torch.FloatTensor([2,3])) # float32
print(torch.DoubleTensor([2,3])) # float64
print('-'*60)
# 4. 创建线性张量
print(torch.arange(0,10,2)) # 在指定区间按照步长生成元素
print(torch.linspace(0,10,10)) # 在指定区间按照元素个数生成
print('-'*60)
# 5. 随机种子设置
print(torch.randn(2,3)) # 每次都是随机的
seed = torch.random.initial_seed() ## 查看随机数种子
print(seed)
torch.random.manual_seed(seed) ## 设置随机数种子
print(torch.random.manual_seed(seed))
print('-'*60)
# 6. 创建0-1张量
# 全0
data = torch.randn(4,5)
print(data)
print(torch.zeros(2,3))
print(torch.zeros_like(data))
# 全1
print(torch.ones(2,3))
print(torch.ones_like(data))
# 指定值
print(torch.full([2,3],100))
print(torch.full_like(data,10))
print('-'*60)
# 7. 张量的类型转换
data = torch.randn(4,5)
print(data)
print(data.dtype) # torch.float32
print(data.type(torch.IntTensor).dtype) # 转为torch.int32
print('-'*60)
张量的类型转换
1.张量转为numpy数组
使用 Tensor.numpy 函数可以将张量转换为 ndarray 数组,但是共享内存,可
以使用 copy 函数避免共享 。
2.numpy数组转为张量
使用 from_numpy 可以将 ndarray 数组转换为 Tensor,默认共享内存,使用 copy 函数避
免共享。
使用 torch.tensor 可以将 ndarray 数组转换为 Tensor,默认不共享内存。
3.标量张量和数字转换
对于只有一个元素的张量,使用 item() 函数将该值从张量中提取出来
代码示例
python
import torch
torch.random.manual_seed(100) # 设置随机数
data = torch.randn(2,3)
# 1. 张量转换为NumPy数组
print(type(data)) # 查看类型 torch.Tensor
data_numpy = data.numpy().copy() # 转换为numpy类型
print(type(data_numpy)) # 查看转换后的类型 'numpy.ndarray
# 更改数值
print(data)
data[0][1] = 100 # 它更改 共享内存 两个都更改
print(data)
print(data_numpy) # 若copy()不共享内存 numpy不更改
print('-'*60)
# 2. NumPy数组转换为张量
# from_numpy()
torch.random.manual_seed(200) # 设置随机数
data1 = torch.randn(2,3) # Tensor类型
data_numpy = data1.numpy().copy() # 转换为numpy类型
# 将ndarray数组转换为Tensor,共享内存
# copy() 不共享内存
data_tensor = torch.from_numpy(data_numpy.copy())
data_tensor[0][1] = 500
print(data_tensor)
print(data_numpy)
print('-'*60)
# 用torch.tensor()
torch.random.manual_seed(300) # 设置随机数
data2 = torch.randn(2,3) # Tensor类型
data_numpy = data2.numpy().copy() # 转换为numpy类型
# 将ndarray数组转换为Tensor,不共享内存
# torch.tensor 不用copy()
data_tensor = torch.tensor(data_numpy)
data_tensor[0][1] = 600
print(data_tensor)
print(data_numpy)
print('-'*60)
# 3. 标量张量和数字转换
# 当张量只包含一个元素时, 可以通过 item() 函数提取出该值
data = torch.tensor([30,])
print(data.item())
data = torch.tensor((30))
print(data.item())
张量的数值计算
1.基本运算
加减乘除取负号:
add、sub、mul、div、neg
add_、sub_、mul_、div_、neg_(其中带下划线的版本会修改原数据)
2.点乘运算
点乘指(Hadamard)的是两个同维矩阵对应位置的元素相乘,使用 mul 和运算符 * 实现 。
3.矩阵乘法运算
矩阵乘法运算要求第一个矩阵 shape: (n, m),第二个矩阵 shape: (m, p), 两个矩阵点积运算 shape 为: (n, p)。
1.运算符 @ 用于进行两个矩阵的乘积运算
2.torch.matmul 对进行乘积运算的两矩阵形状没有限定.对数输入的 shape 不同的张量, 对应的最后几个维度必须符合矩阵运算规则
代码示例
python
import torch
# 1. 基本运算
torch.random.manual_seed(10)
data = torch.randint(0,10,[2,3])
print(data)
# 不修改原数据
new_data = data.add(10) # 加法
print(new_data)
# 直接修改原数据
data.add_(10) # 带下划线
print(data)
# 其他函数
print(data.sub(100))
print(data.mul(100))
print(data.div(100))
print(data.neg())
# 2. 点乘运算
data1 = torch.tensor([[1,2],[3,4]])
data2 = torch.tensor([[5,6],[7,8]])
# 第一种
data = torch.mul(data1,data2)
print(data)
# 第二种
data = data1*data2
print(data)
# 3. 矩阵相乘
data1 = torch.tensor([[1, 2], [3, 4], [5, 6]])
data2 = torch.tensor([[5, 6], [7, 8]])
# 第一种
data = torch.matmul(data1,data2)
print(data)
# 第二种
data = data1@data2
print(data)
张量运算函数
PyTorch 为每个张量封装很多实用的计算函数: 均值 平方根 求和 指数计算 对数计算等等
代码示例
python
import torch
torch.random.manual_seed(10)
data=torch.randint(0,10,[2,3],dtype=torch.float64)
print(data)
print('-'*60)
# 1. 求和
print(data.sum())
print(data.sum(dim=0)) # 按列求和
print(data.sum(dim=1)) # 按行求和
print('-'*60)
# 2. 求均值
print(data.mean())
print(data.mean(dim=0)) # 按列均值
print(data.mean(dim=1)) # 按行均值
print('-'*60)
# 3. 求指数
print(data.exp()) # 右上角 exp固定的数
print('-'*60)
# 4. 求平方
print(torch.pow(data,2)) # 2次方
print('-'*60)
# 5. 平方根
print(torch.pow(data,0.5))
print(data.sqrt())
# 对数
print(data.log()) # 以log为底
print(data.log2()) # 以2为底
print(data.log10()) # 以10为底
张量索引操作
我们在操作张量时, 经常需要去获取某些元素就进行处理或者修改操作,在这里我们需要了解在torch中的索引操作
代码示例
python
import torch
torch.random.manual_seed(10)
data = torch.randint(0,10,[4,5])
print(data)
print('-'*60)
# 1. 简单行 简单列
print(data[0])
print(data[:,0])
print('-'*60)
# 2. 列表索引
# 返回 (0, 1)、(1, 2) 两个位置的元素
print(data[[0,1],[1,2]])
# 返回 0、1 行的 1、2 列共4个元素
print(data[[[0],[1]],[1,2]])
# 3. 范围索引
# 前3行的前2列数据
print(data[:3,:2])
# 第2行到最后的前2列数据
print(data[2:,:2])
# 4. 布尔索引
# 第三列大于5的行数据
print(data[data[:,2]>5])
# 第二行大于5的列数据
print(data[:,data[1]>5])
# 5. 多维索引
torch.random.manual_seed(10)
data = torch.randint(0,10,[3,4,5])
print(data)
# 获取0轴上的第一个数据
print(data[0,:,:])
# 获取1轴上的第一个数据
print(data[:,0,:])
# 获取2轴上的第一个数据
print(data[:,:,0])
张量的形状操作
1.reshape()函数
reshape 函数可以在保证张量数据不变的前提下改变数据的维度,将其转换成指定的形状。
2.squeeze()和unsqueeze()函数
squeeze 函数删除形状为 1 的维度(降维), unsqueeze 函数添加形状为 1 的维度(升维)。
3.transpose()和permute()函数
transpose 函数可以实现交换张量形状的指定维度 , 例如 : 一个张量的形状为 (2, 3, 4) 可以通过 transpose 函数把 3 和 4 进行交换, 将张量的形状变为 (2, 4, 3) 。
permute 函数可以一次交换更多的维度。
4.view()和contiguous()函数
view 函数也可以用于修改张量的形状,只能用于存储在整块内存中的张量。在 PyTorch 中,有些张量是由不同的数据 块组成的,它们并没有存储在整块的内存中,view 函数无法对这样的张量进行变形处理,例如: 一个张量经过了 transpose 或者 permute 函数的处理之后,就无法使用 view 函数进行形状操作。
代码示例
python
import torch
torch.random.manual_seed(10)
data = torch.randint(0,10,[3,4])
print(data.size()) # 查看维度
print('-'*60)
# 1. reshape()
# 转换维度
print(data.reshape(2,6).size()) # 改变维度
print(data.reshape(2,2,3).size()) # 个数相同 可改变维度
print(data.reshape(2,2,-1).size()) # -1自动转换为个数相同的维度
print('-'*60)
# 2. squeeze()删除 unsqueeze()增加
print(data.unsqueeze(dim=0).shape)
print(data.unsqueeze(dim=-1).unsqueeze(dim=1).shape)
print(data.unsqueeze(dim=-1).squeeze(dim=-1).shape)
print('-'*60)
# 3. transpose()交换一次位置 permute()交换多个
# 创造张量
torch.random.manual_seed(10)
data = torch.randint(0,10,[2,3,4,5])
print(data.size()) # 查看维度
# transpose()
print(torch.transpose(data,1,2).shape)
# permute()
print(torch.permute(data,[3,2,1,0]).shape)
print(data.permute([3,2,1,0]).shape)
print('-'*60)
# 3. view()连续 不连续先转换 contiguous()
# 创造张量
torch.random.manual_seed(10)
data = torch.randint(0,10,[3,4,5,6])
print(data.size())
# view() 连续情况下
print(data.view(2,4,-1).shape)
# 不连续情况下: 先 contiguous() 再 view()
data1 = torch.transpose(data,1,2)
## 可以先判断是否连续
print(data1.is_contiguous()) # 判断
print(data1.contiguous().view(2,4,-1).shape) # 转换
张量拼接操作
torch.cat() 函数可以将两个张量根据指定的维度拼接起来,不改变维度数。
代码示例
python
import torch
torch.random.manual_seed(10)
data1 = torch.randint(0,10,[3,4,5,6])
print(data1.shape)
torch.random.manual_seed(10)
data2 = torch.randint(0,10,[3,4,3,6])
print(data2.shape)
# 拼接 cat() 除拼接数以外 其他维度的数都要相同
print(torch.cat([data1,data2],dim=2).shape)
自动微分模块
训练神经网络时,最常用的算法就是反向传播。在该算法中,参数(模型权重)会根据损失函数关于对应 参数的梯度进行调整。为了计算这些梯度,PyTorch内置了名为 torch.autograd 的微分引擎。它支持任意 计算图的自动梯度计算:
接下来我们使用这个结构进行自动微分模块的介绍。我们使用 backward 方法、 grad 属性来实
现梯度的计算和访问 .
代码示例
python
import torch
## 标量
# 设置x,y
x = torch.tensor(5)
y = torch.tensor(0.)
# requires_grad 是否计算权重
w = torch.tensor(1.,requires_grad=True)
b = torch.tensor(3.,requires_grad=True)
# 输出值
z = x*w + b
# 设置损失函数 计算损失
loss = torch.nn.MSELoss()
loss = loss(z,y)
# 自动微分
loss.backward()
# w.b 的梯度
print(w.grad)
print(b.grad)
print("-"*35)
## 数组
x = torch.ones(2,5)
y= torch.zeros(2,3)
w = torch.randn(5,3,requires_grad=True)
b = torch.randn(3,requires_grad=True)
z = torch.matmul(x,w) +b
loss = torch.nn.MSELoss()
loss = loss(z,y)
loss.backward()
print(w.grad)
print(b.grad)