资讯详情

Pytorch实践

Pytorch基础

Pytorch官网在线文档

Torch 类似于意义上的TensorFlow中的Tensor,可以看做是能在GPU计算中的矩阵

熟悉numpy也可以理解为ndarray的GPU版;

在使用深度学习框架后,我们需要做的是设计任务流程和网络框架;

安装Pytorch

CPU版本:

pip install torch1.3.0 cpu torchvision0.4.1 cpu -f https://download.pytorch.org/whl/torch_stable.html

GPU版本:

pip install torch1.3.0 torchvision0.4.1 -f https://download.pytorch.org/whl/torch_stable.html (默认是CUDA10版本)

具体安装可查看官网,视频版本为1.3.实际上,我的机器安装了1.7.0版本(应安装)GPU版本没有专门安装CPU版本命令),主要是为了学习pytorch的使用;

安装相应的版本CUDA

CUDA:Nvidia显卡的GPU加速库,下载链接

基础操作

import torch  torch.__version__ torch.version.cuda torch.cuda.is_available() 
'1.7.0' 
!pip show torch 
Name: torch Version: 1.7.0 Summary: Tensors and Dynamic neural networks in Python with label GPU acceleration Home-page: https://pytorch.org/ Author: PyTorch Team Author-email: packages@pytorch.org License: BSD-3 Location: /Users/huaqiang/anaconda3/lib/python3.7/site-packages Requires: future, numpy, typing-extensions, dataclasses Required-by: torchvision, torchaudio, pytorch-pretrained-bert 

我们注意到当地依赖torch的库:torchvision, torchaudio, pytorch-pretrained-bert

# 创建矩阵 x = torch.empty(5, 3) x # 类型为tensor,即张量 # 转换数据类型 x.to(torch.float) 
tensor([[1.1210e-44, 0.0000e 00, 0.0000e 00],         [0.0000e 00, 0.0000e 00, 0.0000e 00],         [0.0000e 00, 0.0000e 00, 0.0000e 00],         [0.0000e 00, 0.0000e 00, 0.0000e 00],         [0.0000e 00, 0.0000e 00, 0.0000e 00]]) 
# 随机生成矩阵 torch.rand(5,3) 
tensor([[0.4939, 0.6952, 0.3724],         [0.3051, 0.1697, 0.6733],         [0.2311, 0.2673, 0.2252],         [0.0205, 0.5017, 0.8799],         [0.6741, 0.4258, 0.1572]]) 
# 全0矩阵 torch.zeros(5,3,dtype=torch.long)  
tensor([[0, 0, 0],         [0, 0, 0],         [0, 0, 0],         [0, 0, 0],         [0, 0, 0]]) 
# 使用多种方法和方法numpy很类似 torch.randn_like(x, dtype=torch.float)  
tensor([[-0.7219, -1.0058,  0.1401],         [-0.1806, -0.3656,  0.8092],         [ 0.8398,  0.2060,  0.9734],         [-0.1092,  0.4415, -0.0103],         [-0.6904, -1.5415,  0.1186]]) 
torch.randn_like?
# 检查矩阵大小 x.size() 
torch.Size([5, 3])
# 基本运算

x + x

torch.add(x,x)

tensor([[2.2421e-44, 0.0000e+00, 0.0000e+00],
        [0.0000e+00, 0.0000e+00, 0.0000e+00],
        [0.0000e+00, 0.0000e+00, 0.0000e+00],
        [0.0000e+00, 0.0000e+00, 0.0000e+00],
        [0.0000e+00, 0.0000e+00, 0.0000e+00]])
# 索引和切片
x[:, 1]
tensor([0., 0., 0., 0., 0.])
# 常用方法

# view:改变矩阵维度
x = torch.randn(4,4)
y = x.view(16)
z = x.view(-1, 8)
z
tensor([[ 0.2263, -0.2230, -0.1979,  1.1429, -0.6950,  0.2761, -0.1115, -0.1601],
        [ 0.5172,  0.3535,  1.6254,  0.2054,  0.5812,  0.3431,  0.1358, -1.4275]])
 # 与numpy的协同操作
a = torch.ones(5)
a
tensor([1., 1., 1., 1., 1.])
b = a.numpy()
b
array([1., 1., 1., 1., 1.], dtype=float32)
c = torch.from_numpy(b)
c
tensor([1., 1., 1., 1., 1.])

自动求导机制

反向传播算法

import torch

# 指定求导张量:方法1
x = torch.randn(3,4,requires_grad=True)

# 指定求导张量:方法2
y = torch.randn(3,4)
y.requires_grad = True

# 定义算式过程
t = x + y
t = t.sum()
# 调用反向传播 
t.backward()
# 查看 梯度(自动计算求导)
# t.retain_grad 
t.grad 
<bound method Tensor.retain_grad of tensor(-3.9155, grad_fn=<SumBackward0>)>

计算流程举例

y = w * x

z = y + b

# 用z对x求偏导 = 用z对y求偏导 * 用y对x求偏导
x = torch.rand(1)
x
tensor([0.6581])
b = torch.rand(1, requires_grad=True)
w = torch.rand(1, requires_grad=True)
y = w * x
z = y + b
z
tensor([1.3465], grad_fn=<AddBackward0>)
# 查看是否需要计算梯度
x.requires_grad,b.requires_grad,w.requires_grad, y.requires_grad
(False, True, True, True)
# 查看是否是叶节点(不重要)
x.is_leaf, b.is_leaf, w.is_leaf, y.is_leaf, z.is_leaf
(True, True, True, False, False)
# 反向传播:梯度清0 如果不清空 梯度会累加 
z.backward(retain_graph=True)
# 计算梯度
w.grad
tensor([0.6581])
b.grad # 反向传播中 如果梯度不清零 多次计算梯度的结果会累加
tensor([1.])
# 清零
# 计算
# 更新

线性回归Demo

import torch
import torch.nn as nn
import numpy as np

x_values = [i for i in range(11)]
x_train = np.array(x_values, dtype=np.float32)
x_train = x_train.reshape(-1,1)
x_train.shape
(11, 1)
y_values = [2*i + 1 for i in x_values]
y_train = np.array(y_values, dtype=np.float32)
y_train = y_train.reshape(-1,1)
y_train.shape
(11, 1)
  • 线性回归模型:就是一个不加激活函数的全连接层
 class LinearRegressionModel(nn.Module):
        """ 线性回归模型 """
        def __init__(self, input_dim, output_dim):
            super(LinearRegressionModel, self).__init__()
            # 全连接层
            self.linear = nn.Linear(input_dim, output_dim)
        def forward(self, x):
            """ 前向传播过程 """
            out = self.linear(x)
            return out
input_dim = 1
output_dim = 1

# 一元一次方程 输入输出参数维度都是1
model = LinearRegressionModel(input_dim, output_dim)
  • 指定参数 优化器 和损失函数
epochs = 1000
learning_rate = 0.01
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) # 指定要优化的模型参数和学习率
criterion = nn.MSELoss() # 回归的损失函数 使用均方差


  • 训练模型
for epoch in range(epochs):
# 转张量
    inputs = torch.from_numpy(x_train)
    labels = torch.from_numpy(y_train)
# 梯度清零(每一次迭代都要做)
    optimizer.zero_grad()
# 前向传播
    outputs = model(inputs)
# 计算损失
    loss = criterion(outputs, labels)
# 反向传播
    loss.backward()
# 更新权重参数
    optimizer.step()
    
    if (epoch % 50) == 0:
        print("epoch {}, loss {}".format(epoch, loss.item()))
    
    
epoch 0, loss 1.5593505653388462e-11
epoch 50, loss 1.5593505653388462e-11
epoch 100, loss 1.5593505653388462e-11
epoch 150, loss 1.5593505653388462e-11
epoch 200, loss 1.5593505653388462e-11
epoch 250, loss 1.5593505653388462e-11
epoch 300, loss 1.5593505653388462e-11
epoch 350, loss 1.5593505653388462e-11
epoch 400, loss 1.5593505653388462e-11
epoch 450, loss 1.5593505653388462e-11
epoch 500, loss 1.5593505653388462e-11
epoch 550, loss 1.5593505653388462e-11
epoch 600, loss 1.5593505653388462e-11
epoch 650, loss 1.5593505653388462e-11
epoch 700, loss 1.5593505653388462e-11
epoch 750, loss 1.5593505653388462e-11
epoch 800, loss 1.5593505653388462e-11
epoch 850, loss 1.5593505653388462e-11
epoch 900, loss 1.5593505653388462e-11
epoch 950, loss 1.5593505653388462e-11
  • 模型测试 进行预测
# 测试数据 转张量 取消梯度
# 支持数据集的批量预测
predicted = model(torch.from_numpy(x_train).requires_grad_(False))
# 结果转为numpy
predicted = predicted.data.numpy() 
# 打印
predicted
array([[ 0.99999267],
       [ 2.9999938 ],
       [ 4.999995  ],
       [ 6.9999967 ],
       [ 8.999997  ],
       [10.999998  ],
       [13.        ],
       [15.000001  ],
       [17.000002  ],
       [19.000004  ],
       [21.000004  ]], dtype=float32)
  • 模型的保存和读取
torch.save(model.state_dict(), './model.pkl') # 使用 .pkl .pth 后缀均可
model.load_state_dict(torch.load('./model.pkl'))
<All keys matched successfully>

使用GPU进行训练

只需要把数据模型传入到cuda里面就可以了

注意:只要想用GPU做训练,model和输入张量 就需要 .to(device)下,用cpu基本可以忽略!

train_on_gpu = torch.cuda.is_available()

if not train_on_gpu:
    print('CUDA is not available, use CPU')
else:
    print('CUDA is available, use GPU')
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

# 模型
model.to(device)

LinearRegressionModel(
  (linear): Linear(in_features=1, out_features=1, bias=True)
)
# 数据
# ...
for epoch in range(epochs):
# 转张量
    inputs = torch.from_numpy(x_train).to(device)
    labels = torch.from_numpy(y_train).to(device)
# ...


这是一个最简单的结果,后续的会进行延伸

常见tensor形式

  • scalar 数值
  • vector 向量
  • matrix 矩阵
  • n-dimensional tensor 高维
from torch import tensor

x = tensor(100) # scalar
x
tensor(100)
x = tensor([1,2,3,4,5,6]) # vector
x.dim(), x.size()
(1, torch.Size([6]))
x = tensor([[1,2],[3,4]]) # matrix
x.dim(), x.size()
(2, torch.Size([2, 2]))
# 矩阵运算
x.matmul(x) # 矩阵相乘:行列 * 列行 = 行行
x*x # 矩阵内积:元素相乘(逐个对应)
tensor([[ 1,  4],
        [ 9, 16]])
x = tensor([[[1,2],[3,4]],[[1,2],[3,4]]]) # 3-dimensional tensor
x.dim(), x.size()
(3, torch.Size([2, 2, 2]))

强大的hub模块

调用集成可用的网络模型架构及参数 直接使用;

比如 基于ResNet进行了图形分割 获取到的一个 同簇下的模型,就可以使用hub模块进行加载,然后直接使用;

import torch
# 实例1
model = torch.hub.load("pytorch/vision:v:0.4.2", "deeplabv3_resnet101", pretrained=True)

使用Pytorch训练模型,一定要注意一个细节:有时候明明训练很好,测试时候出问题? 这时候我们要找一下Model里是否有BN或者 Dropout层,如果存在了,那就要小心了!!! 测试之前加入下面这句话!!!! 注意为了排除BN和Dropout对测试影响 model = model.eval()

  • 一般在训练模型时 加上 model.train(),这样可以正常使用 Batch Normalization 和 Dropout
  • 测试的时候一般使用 model.eval(),这样就不会使用 Batch Normalization 和 Dropout
# 实例2
# 具体怎么用 请参考官网 这里只是一个使用示例
# 要注意 resnet默认的卷积核是3*3 也就是说 对应的是图片的3通道 如果要修改卷积核大小 可以下载源码然后自定义
model = torch.hub.load('pytroch/vision:v0.4.2', 'resnet18', pretrained = True)

 # 查看指定版本所支持的模型
torch.hub.list("pytorch/vision:v1.7.0")

预处理过程组合举例

from torchvision import transforms
preprocess = transforms.Compose([
    transforms.Normalize(mean=[0.485,0.456,0.406], std=[0.229,0.224,0.225]),
    transforms.ToTensor(),
    lambda x: torch.tensor(x), # or
])

Pytorch神经网 进行气温预测

# 读取数据
features = pd.read_csv('temps.csv') # 数据来源未知 仅仅是个示例

features.head()

# 数据可视化
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')

# 设置布局
fig, ((ax1,ax2),(ax3,ax4)) = plt.subplots(nrows=2, ncols=2, figsize=(10,10))
fig.autofmt_xdate(rotation = 45)

# 标签值
ax1.plot(dates, features['temp_1']) # 这里 dates 是一个 datetime.datetime类型的 Series
ax1.set_xlabel('')
ax1.set_ylabel('Temp')
ax1.set_title('temp_1')

...

plt.tight_layout(pad=2)


# 实质性数据 量化处理:one-hot编码
features = pd.get_dummies(features) # 会自动将 实质性数据(即分类数据)进行one-hot编码 有几个类就会加几列;

# 标签
labels = np.array(features['actual'])

# 特征
features = features.drop('actual', axis=1)
features = np.array(features)

数据特征工程

这是一个专门的领域,这里仅做简单的标准化处理

关于归一化:

  • 归一化后加快了梯度下降求最优解的速度
  • 归一化有可能提高精度

标准差标准化(standardScale)使得经过处理的数据符合标准正态分布,即均值为0,标准差为1(减均值除方差)

注意:会对每个特征都进行处理

from sklearn import preprocessing
# 预处理模块的标准化处理
scaler = preprocessing.StandardScaler()
input_features = scaler.fit_transform(features)

相对复杂的一种构建方式

# 尝试构建网络模型

# 特征和标签 转张量
x = torch.tensor(input_features, dtype=torch.float)
y = torch.tensor(labels, dtype=torch.float)

# 权重参数初始化
w1 = torch.randn((14,128), dtype=float, requires_grad=True) # 输入输出节点数 即对应权重参数数
b1 = torch.randn(128, dtype=float, requires_grad=True) # 偏置参数个数 与 输出节点数同
w2 = torch.randn((128,1), dtype=float, requires_grad=True)
b2 = torch.randn(1, dtype=float, requires_grad=True)

learning_rate = 0.01
losses = []


for i in range(1000):
# 前向传播
# 计算隐藏层
    hidden1 = x.mm(w1) + b1
# 激活函数
    hidden1 = torch.relu(hidden1)
# 计算输出层(输出层 一般不加激活函数)
    predictions = hidden.mm(w2) + b2
    
# 计算损失
    loss = torch.mean((predictions - y) ** 2)
    losses.append(loss.data.numpy())
    
    if i%100 == 0:
        print('loss ', loss)
    
    # 反向传播:计算更新后w和b的梯度值
    loss.backward()
    
# 更新参数:使用计算后的梯度值进行更新
    w1.data.add_(- learning_rate * w1.grad.data) # 沿着梯度反方向 更新 即 梯度下降!
    b1.data.add_(- learning_rate * b1.grad.data)
    w2.data.add_(- learning_rate * w2.grad.data)
    b1.data.add_(- learning_rate * b2.grad.data)
    
# 每次迭代将梯度清空
    w1.grad.data.zero_()
    b1.grad.data.zero_()
    w2.grad.data.zero_()
    b2.grad.data.zero_()
    

更简单的构建方式


input_size = input_features.shape[1] # 14
hidden_size = 128
output_size = 1
batch_size = 16

my_nn = torch.nn.Sequential(
    torch.nn.Linear(input_size, hidden_size), # 14 128
    torch.nn.Sigmoid(),
    torch.nn.Linear(hidden_size, output_size) # 128 1
)

cost = torch.nn.MSELoss(reduction='mean')
# Adam 支持动态衰减 学习率
optimizer = torch.optim.Adam(my_nn.parameters(), lr = 0.001)


losses = []
for i in range(1000):
    batch_loss = []
    
    for start in range(0, len(input_features), batch_size):
        end = start + batch_size if start + batch_size < len(input_features) else len(input_features)
        
        xx = torch.tensor(input_features[start:end], dtype=torch.float, requires_grad=True)
        yy = torch.tensor(labels[start:end], dtype=torch.float, requires_grad=True)
        
        prediction = my_nn(xx)
# 计算损失
        loss = cost(prediction, yy)
# 梯度清零
        optimizer.zero_grad()
# 反向传播
        loss.backward(retain_graph=True)
# 更新权重
        optimizer.step()
        batch_loss.append(loss.data.numpy())

    losses.append(np.mean(batch_loss))
     

对retain_graph参数的理解

# 假如你有两个Loss,先执行第一个的backward,再执行第二个backward
loss1.backward(retain_graph=True)
loss2.backward() # 执行完这个后,所有中间变量都会被释放,以便下一次的循环
optimizer.step() # 更新参数

预测结果的可视化举例

predictions_data = pd.DataFrame(data={ 
        'date': test_dates, 'predictions':predict.reshape(-1)})
# 真实值
plt.plot(true_data['date'], true_data['actual'], 'b-', label='actual')

# 预测值
plt.plot(predictions_data['date'], predictions_data[<

标签: 0228连接器1601连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台