本文主要介绍将pytorch模型准确导出为可用的onnx模型。以方便OpenCV Dnn,NCNN,MNN,TensorRT等框架调用。所有代码见:Python-Study-Notes

1 使用说明

本文示例为调用pytorch预训练的mobilenetv2模型,将其导出为onnx模型。主要步骤如下:

  1. 读取模型
  2. 检测图像
  3. 导出为onnx模型
  4. 模型测试
  5. 模型简化
# 需要调用的头文件
import torch
from torchvision import models
import cv2
import numpy as np
from torchsummary import summary
import onnxruntime
from onnxsim import simplify
import onnx
from matplotlib import pyplot as plt # 判断使用CPU还是GPU
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

1.1 读取模型

该部分主要为调用训练好的模型。主要内容如下

  1. 直接读取预训练模型
  2. 将模型转换为推理模型
  3. 查看模型的结构
# ----- 1 读取模型
print("----- 1 读取模型 -----")
# 载入模型并读取权重
model = models.mobilenet_v2(pretrained=True)
# 将模型转换为推理模式
model.eval()
# 查看模型的结构,(3,224,224)为模型的图像输入
summary(model, (3, 224, 224))
----- 1 读取模型 -----
----------------------------------------------------------------
Layer (type) Output Shape Param #
================================================================
Conv2d-1 [-1, 32, 112, 112] 864
BatchNorm2d-2 [-1, 32, 112, 112] 64
ReLU6-3 [-1, 32, 112, 112] 0
Conv2d-4 [-1, 32, 112, 112] 288
BatchNorm2d-5 [-1, 32, 112, 112] 64
ReLU6-6 [-1, 32, 112, 112] 0
Conv2d-7 [-1, 16, 112, 112] 512
BatchNorm2d-8 [-1, 16, 112, 112] 32
InvertedResidual-9 [-1, 16, 112, 112] 0
Conv2d-10 [-1, 96, 112, 112] 1,536
BatchNorm2d-11 [-1, 96, 112, 112] 192
ReLU6-12 [-1, 96, 112, 112] 0
Conv2d-13 [-1, 96, 56, 56] 864
BatchNorm2d-14 [-1, 96, 56, 56] 192
ReLU6-15 [-1, 96, 56, 56] 0
Conv2d-16 [-1, 24, 56, 56] 2,304
BatchNorm2d-17 [-1, 24, 56, 56] 48
InvertedResidual-18 [-1, 24, 56, 56] 0
Conv2d-19 [-1, 144, 56, 56] 3,456
BatchNorm2d-20 [-1, 144, 56, 56] 288
ReLU6-21 [-1, 144, 56, 56] 0
Conv2d-22 [-1, 144, 56, 56] 1,296
BatchNorm2d-23 [-1, 144, 56, 56] 288
ReLU6-24 [-1, 144, 56, 56] 0
Conv2d-25 [-1, 24, 56, 56] 3,456
BatchNorm2d-26 [-1, 24, 56, 56] 48
InvertedResidual-27 [-1, 24, 56, 56] 0
Conv2d-28 [-1, 144, 56, 56] 3,456
BatchNorm2d-29 [-1, 144, 56, 56] 288
ReLU6-30 [-1, 144, 56, 56] 0
Conv2d-31 [-1, 144, 28, 28] 1,296
BatchNorm2d-32 [-1, 144, 28, 28] 288
ReLU6-33 [-1, 144, 28, 28] 0
Conv2d-34 [-1, 32, 28, 28] 4,608
BatchNorm2d-35 [-1, 32, 28, 28] 64
InvertedResidual-36 [-1, 32, 28, 28] 0
Conv2d-37 [-1, 192, 28, 28] 6,144
BatchNorm2d-38 [-1, 192, 28, 28] 384
ReLU6-39 [-1, 192, 28, 28] 0
Conv2d-40 [-1, 192, 28, 28] 1,728
BatchNorm2d-41 [-1, 192, 28, 28] 384
ReLU6-42 [-1, 192, 28, 28] 0
Conv2d-43 [-1, 32, 28, 28] 6,144
BatchNorm2d-44 [-1, 32, 28, 28] 64
InvertedResidual-45 [-1, 32, 28, 28] 0
Conv2d-46 [-1, 192, 28, 28] 6,144
BatchNorm2d-47 [-1, 192, 28, 28] 384
ReLU6-48 [-1, 192, 28, 28] 0
Conv2d-49 [-1, 192, 28, 28] 1,728
BatchNorm2d-50 [-1, 192, 28, 28] 384
ReLU6-51 [-1, 192, 28, 28] 0
Conv2d-52 [-1, 32, 28, 28] 6,144
BatchNorm2d-53 [-1, 32, 28, 28] 64
InvertedResidual-54 [-1, 32, 28, 28] 0
Conv2d-55 [-1, 192, 28, 28] 6,144
BatchNorm2d-56 [-1, 192, 28, 28] 384
ReLU6-57 [-1, 192, 28, 28] 0
Conv2d-58 [-1, 192, 14, 14] 1,728
BatchNorm2d-59 [-1, 192, 14, 14] 384
ReLU6-60 [-1, 192, 14, 14] 0
Conv2d-61 [-1, 64, 14, 14] 12,288
BatchNorm2d-62 [-1, 64, 14, 14] 128
InvertedResidual-63 [-1, 64, 14, 14] 0
Conv2d-64 [-1, 384, 14, 14] 24,576
BatchNorm2d-65 [-1, 384, 14, 14] 768
ReLU6-66 [-1, 384, 14, 14] 0
Conv2d-67 [-1, 384, 14, 14] 3,456
BatchNorm2d-68 [-1, 384, 14, 14] 768
ReLU6-69 [-1, 384, 14, 14] 0
Conv2d-70 [-1, 64, 14, 14] 24,576
BatchNorm2d-71 [-1, 64, 14, 14] 128
InvertedResidual-72 [-1, 64, 14, 14] 0
Conv2d-73 [-1, 384, 14, 14] 24,576
BatchNorm2d-74 [-1, 384, 14, 14] 768
ReLU6-75 [-1, 384, 14, 14] 0
Conv2d-76 [-1, 384, 14, 14] 3,456
BatchNorm2d-77 [-1, 384, 14, 14] 768
ReLU6-78 [-1, 384, 14, 14] 0
Conv2d-79 [-1, 64, 14, 14] 24,576
BatchNorm2d-80 [-1, 64, 14, 14] 128
InvertedResidual-81 [-1, 64, 14, 14] 0
Conv2d-82 [-1, 384, 14, 14] 24,576
BatchNorm2d-83 [-1, 384, 14, 14] 768
ReLU6-84 [-1, 384, 14, 14] 0
Conv2d-85 [-1, 384, 14, 14] 3,456
BatchNorm2d-86 [-1, 384, 14, 14] 768
ReLU6-87 [-1, 384, 14, 14] 0
Conv2d-88 [-1, 64, 14, 14] 24,576
BatchNorm2d-89 [-1, 64, 14, 14] 128
InvertedResidual-90 [-1, 64, 14, 14] 0
Conv2d-91 [-1, 384, 14, 14] 24,576
BatchNorm2d-92 [-1, 384, 14, 14] 768
ReLU6-93 [-1, 384, 14, 14] 0
Conv2d-94 [-1, 384, 14, 14] 3,456
BatchNorm2d-95 [-1, 384, 14, 14] 768
ReLU6-96 [-1, 384, 14, 14] 0
Conv2d-97 [-1, 96, 14, 14] 36,864
BatchNorm2d-98 [-1, 96, 14, 14] 192
InvertedResidual-99 [-1, 96, 14, 14] 0
Conv2d-100 [-1, 576, 14, 14] 55,296
BatchNorm2d-101 [-1, 576, 14, 14] 1,152
ReLU6-102 [-1, 576, 14, 14] 0
Conv2d-103 [-1, 576, 14, 14] 5,184
BatchNorm2d-104 [-1, 576, 14, 14] 1,152
ReLU6-105 [-1, 576, 14, 14] 0
Conv2d-106 [-1, 96, 14, 14] 55,296
BatchNorm2d-107 [-1, 96, 14, 14] 192
InvertedResidual-108 [-1, 96, 14, 14] 0
Conv2d-109 [-1, 576, 14, 14] 55,296
BatchNorm2d-110 [-1, 576, 14, 14] 1,152
ReLU6-111 [-1, 576, 14, 14] 0
Conv2d-112 [-1, 576, 14, 14] 5,184
BatchNorm2d-113 [-1, 576, 14, 14] 1,152
ReLU6-114 [-1, 576, 14, 14] 0
Conv2d-115 [-1, 96, 14, 14] 55,296
BatchNorm2d-116 [-1, 96, 14, 14] 192
InvertedResidual-117 [-1, 96, 14, 14] 0
Conv2d-118 [-1, 576, 14, 14] 55,296
BatchNorm2d-119 [-1, 576, 14, 14] 1,152
ReLU6-120 [-1, 576, 14, 14] 0
Conv2d-121 [-1, 576, 7, 7] 5,184
BatchNorm2d-122 [-1, 576, 7, 7] 1,152
ReLU6-123 [-1, 576, 7, 7] 0
Conv2d-124 [-1, 160, 7, 7] 92,160
BatchNorm2d-125 [-1, 160, 7, 7] 320
InvertedResidual-126 [-1, 160, 7, 7] 0
Conv2d-127 [-1, 960, 7, 7] 153,600
BatchNorm2d-128 [-1, 960, 7, 7] 1,920
ReLU6-129 [-1, 960, 7, 7] 0
Conv2d-130 [-1, 960, 7, 7] 8,640
BatchNorm2d-131 [-1, 960, 7, 7] 1,920
ReLU6-132 [-1, 960, 7, 7] 0
Conv2d-133 [-1, 160, 7, 7] 153,600
BatchNorm2d-134 [-1, 160, 7, 7] 320
InvertedResidual-135 [-1, 160, 7, 7] 0
Conv2d-136 [-1, 960, 7, 7] 153,600
BatchNorm2d-137 [-1, 960, 7, 7] 1,920
ReLU6-138 [-1, 960, 7, 7] 0
Conv2d-139 [-1, 960, 7, 7] 8,640
BatchNorm2d-140 [-1, 960, 7, 7] 1,920
ReLU6-141 [-1, 960, 7, 7] 0
Conv2d-142 [-1, 160, 7, 7] 153,600
BatchNorm2d-143 [-1, 160, 7, 7] 320
InvertedResidual-144 [-1, 160, 7, 7] 0
Conv2d-145 [-1, 960, 7, 7] 153,600
BatchNorm2d-146 [-1, 960, 7, 7] 1,920
ReLU6-147 [-1, 960, 7, 7] 0
Conv2d-148 [-1, 960, 7, 7] 8,640
BatchNorm2d-149 [-1, 960, 7, 7] 1,920
ReLU6-150 [-1, 960, 7, 7] 0
Conv2d-151 [-1, 320, 7, 7] 307,200
BatchNorm2d-152 [-1, 320, 7, 7] 640
InvertedResidual-153 [-1, 320, 7, 7] 0
Conv2d-154 [-1, 1280, 7, 7] 409,600
BatchNorm2d-155 [-1, 1280, 7, 7] 2,560
ReLU6-156 [-1, 1280, 7, 7] 0
Dropout-157 [-1, 1280] 0
Linear-158 [-1, 1000] 1,281,000
================================================================
Total params: 3,504,872
Trainable params: 3,504,872
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.57
Forward/backward pass size (MB): 152.87
Params size (MB): 13.37
Estimated Total Size (MB): 166.81
----------------------------------------------------------------

1.2 检测图像

该部分主要为检测图像,查看模型结果。一般来说pytorch导出的onnx模型都是用于C++调用,所以基于OpenCV直接读取图像,进行图像通道转换以及图像归一化以模拟实际C++调用情况,而不是用pillow和pytorch的transform。通常C++提供的图像都是经由OpenCV调用而来。主要内容如下:

  1. 基于OpenCV读取图像,进行通道转换
  2. 将图像进行归一化
  3. 进行模型推理,查看结果
# ----- 2 检测图像
print("----- 2 检测图像 -----")
# 待检测图像路径
img_path = './image/rabbit.jpg' # 读取图像
img = cv2.imread(img_path)
# 图像通道转换
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 展示图像
plt.imshow(img)
plt.show()
# 图像大小重置为模型输入图像大小
img = cv2.resize(img, (224, 224)) # 图像归一化
mean = np.array([0.485, 0.456, 0.406], dtype=np.float32)
std = np.array([0.229, 0.224, 0.225], dtype=np.float32)
img = np.array((img / 255.0 - mean) / std, dtype=np.float32) # 图像通道转换
img = img.transpose([2, 0, 1])
# 获得pytorch需要的输入图像格式NCHW
img_ = torch.from_numpy(img).unsqueeze(0)
img_ = img_.to(device)
# 推理
outputs = model(img_) # 得到预测结果,并且按概率从大到小排序
_, indices = torch.sort(outputs, descending=True)
# 返回top5每个预测标签的百分数
percentage = torch.nn.functional.softmax(outputs, dim=1)[0] * 100
print(["预测标签为: {},预测概率为:{};".format(idx, percentage[idx].item()) for idx in indices[0][:5]]) # 保存/载入整个pytorch模型
# torch.save(model, 'model.ckpt')
# model = torch.load('model.ckpt') # 仅仅保存/载入pytorch模型的参数
# torch.save(model.state_dict(), 'params.ckpt')
# model.load_state_dict(torch.load('params.ckpt'))
----- 2 检测图像 -----

['预测标签为: 331,预测概率为:54.409969329833984;', '预测标签为: 330,预测概率为:33.62083435058594;', '预测标签为: 332,预测概率为:11.84182071685791;', '预测标签为: 263,预测概率为:0.05221949517726898;', '预测标签为: 264,预测概率为:0.027525480836629868;']

1.3 导出为onnx模型

该部分主要为导出onnx模型,两行代码就可以搞定,onnx模型导出路径为当前目录下mobilenet_v2.onnx。具体如下:

x = torch.rand(1, 3, 224, 224)
torch_out = torch.onnx._export(model, x, output_name, export_params=True,
input_names=["input"], output_names=["output"])
# ---- 3 导出为onnx模型
print("----- 3 导出为onnx模型 -----")
# An example input you would normally provide to your model's forward() method
# x为输入图像,格式为pytorch的NCHW格式;1为图像数一般不需要修改;3为通道数;224,224为图像高宽;
x = torch.rand(1, 3, 224, 224)
# 模型输出名
output_name = "mobilenet_v2.onnx"
# Export the model
# 导出为onnx模型
# model为模型,x为模型输入,"mobilenet_v2.onnx"为onnx输出名,export_params表示是否保存模型参数
# input_names为onnx模型输入节点名字,需要输入列表
# output_names为onnx模型输出节点名字,需要输入列表;如果是多输出修改为output_names=["output1","output2"]
torch_out = torch.onnx._export(model, x, output_name, export_params=True,
input_names=["input"], output_names=["output"])
print("模型导出成功")
----- 3 导出为onnx模型 -----
模型导出成功

1.4 模型测试

该部分主要为测试模型,一般可以跳过,不需要这部分代码,通常模型转换不会出错。另外onnx模型可以通过Netron查看结构。

# ---- 4 模型测试(可跳过)
print("----- 4 模型测试 -----") # 可以跳过该步骤,一般不会有问题 # 检查输出
def check_onnx_output(filename, input_data, torch_output):
session = onnxruntime.InferenceSession(filename)
input_name = session.get_inputs()[0].name
result = session.run([], {input_name: input_data.numpy()})
for test_result, gold_result in zip(result, torch_output.values()):
np.testing.assert_almost_equal(
gold_result.cpu().numpy(), test_result, decimal=3,
)
return result # 检查模型
def check_onnx_model(model, onnx_filename, input_image):
with torch.no_grad():
torch_out = {"output": model(input_image)}
check_onnx_output(onnx_filename, input_image, torch_out)
onnx_model = onnx.load(onnx_filename)
onnx.checker.check_model(onnx_model)
print("模型测试成功")
return onnx_model # 检测导出的onnx模型是否完整
# 一般出现问题程序直接报错,不过很少出现问题
onnx_model = check_onnx_model(model, output_name, x)
----- 4 模型测试 -----
模型测试成功

1.5 模型简化

一般来说导出后的onnx模型会有一堆冗余操作,需要简化。推荐使用onnx-simplifier进行onnx模型简化。onnx简化模型导出路径为当前目录下mobilenet_v2.onnxsim.onnx
调用onnx-simplifier有三种办法:

  1. 调用代码,调用onnx-simplifier的simplify接口
  2. 命令行简化,直接输入python3 -m onnxsim input_onnx_model output_onnx_model
  3. 在线调用,调用onnx-simplifier作者的https://convertmodel.com/直接进行模型简化。

具体来说推荐第三种在线使用,第三种在线调用方便,还能将onnx模型转换为ncnn,mnn等模型格式。

P.S. onnx-simplifier对于高版本pytorch不那么支持,转换可能失败,所以设置skip_fuse_bn=True跳过融合bn层。这种情况下onnx-simplifier转换出来的onnx模型可能比转换前的模型大,原因是补充了shape信息。

# ----- 5 模型简化
print("----- 5 模型简化 -----")
# 基于onnx-simplifier简化模型,https://github.com/daquexian/onnx-simplifier
# 也可以命令行输入python3 -m onnxsim input_onnx_model output_onnx_model
# 或者使用在线网站直接转换https://convertmodel.com/ # 输出模型名
filename = output_name + "sim.onnx"
# 简化模型
# 设置skip_fuse_bn=True表示跳过融合bn层,pytorch高版本融合bn层会出错
simplified_model, check = simplify(onnx_model, skip_fuse_bn=True)
onnx.save_model(simplified_model, filename)
onnx.checker.check_model(simplified_model)
# 如果出错
assert check, "简化模型失败"
print("模型简化成功")
----- 5 模型简化 -----
模型简化成功

1.6 全部代码

全部工程代码如下

# -*- coding: utf-8 -*-
"""
Created on Tue Dec 8 19:44:42 2020 @author: luohenyueji
""" import torch
from torchvision import models
import cv2
import numpy as np
from torchsummary import summary
import onnxruntime
from onnxsim import simplify
import onnx
from matplotlib import pyplot as plt # 判断使用CPU还是GPU
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") # ----- 1 读取模型
print("----- 1 读取模型 -----")
# 载入模型并读取权重
model = models.mobilenet_v2(pretrained=True)
# 将模型转换为推理模式
model.eval()
# 查看模型的结构,(3,224,224)为模型的图像输入
# summary(model, (3, 224, 224)) # ----- 2 检测图像
print("----- 2 检测图像 -----")
# 待检测图像路径
img_path = './image/rabbit.jpg' # 读取图像
img = cv2.imread(img_path)
# 图像通道转换
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 展示图像
# plt.imshow(img)
# plt.show()
# 图像大小重置为模型输入图像大小
img = cv2.resize(img, (224, 224)) # 图像归一化
mean = np.array([0.485, 0.456, 0.406], dtype=np.float32)
std = np.array([0.229, 0.224, 0.225], dtype=np.float32)
img = np.array((img / 255.0 - mean) / std, dtype=np.float32) # 图像通道转换
img = img.transpose([2, 0, 1])
# 获得pytorch需要的输入图像格式NCHW
img_ = torch.from_numpy(img).unsqueeze(0)
img_ = img_.to(device)
# 推理
outputs = model(img_) # 得到预测结果,并且按概率从大到小排序
_, indices = torch.sort(outputs, descending=True)
# 返回top5每个预测标签的百分数
percentage = torch.nn.functional.softmax(outputs, dim=1)[0] * 100
print(["预测标签为: {},预测概率为:{};".format(idx, percentage[idx].item()) for idx in indices[0][:5]]) # 保存/载入整个pytorch模型
# torch.save(model, 'model.ckpt')
# model = torch.load('model.ckpt') # 仅仅保存/载入pytorch模型的参数
# torch.save(model.state_dict(), 'params.ckpt')
# model.load_state_dict(torch.load('params.ckpt')) # ---- 3 导出为onnx模型
print("----- 3 导出为onnx模型 -----")
# An example input you would normally provide to your model's forward() method
# x为输入图像,格式为pytorch的NCHW格式;1为图像数一般不需要修改;3为通道数;224,224为图像高宽;
x = torch.rand(1, 3, 224, 224)
# 模型输出名
output_name = "mobilenet_v2.onnx"
# Export the model
# 导出为onnx模型
# model为模型,x为模型输入,"mobilenet_v2.onnx"为onnx输出名,export_params表示是否保存模型参数
# input_names为onnx模型输入节点名字,需要输入列表
# output_names为onnx模型输出节点名字,需要输入列表;如果是多输出修改为output_names=["output1","output2"]
torch_out = torch.onnx._export(model, x, output_name, export_params=True,
input_names=["input"], output_names=["output"])
print("模型导出成功") # ---- 4 模型测试(可跳过)
print("----- 4 模型测试 -----") # 可以跳过该步骤,一般不会有问题 # 检查输出
def check_onnx_output(filename, input_data, torch_output):
session = onnxruntime.InferenceSession(filename)
input_name = session.get_inputs()[0].name
result = session.run([], {input_name: input_data.numpy()})
for test_result, gold_result in zip(result, torch_output.values()):
np.testing.assert_almost_equal(
gold_result.cpu().numpy(), test_result, decimal=3,
)
return result # 检查模型
def check_onnx_model(model, onnx_filename, input_image):
with torch.no_grad():
torch_out = {"output": model(input_image)}
check_onnx_output(onnx_filename, input_image, torch_out)
onnx_model = onnx.load(onnx_filename)
onnx.checker.check_model(onnx_model)
print("模型测试成功")
return onnx_model # 检测导出的onnx模型是否完整
# 一般出现问题程序直接报错,不过很少出现问题
onnx_model = check_onnx_model(model, output_name, x) # ----- 5 模型简化
print("----- 5 模型简化 -----")
# 基于onnx-simplifier简化模型,https://github.com/daquexian/onnx-simplifier
# 也可以命令行输入python3 -m onnxsim input_onnx_model output_onnx_model
# 或者使用在线网站直接转换https://convertmodel.com/ # 输出模型名
filename = output_name + "sim.onnx"
# 简化模型
# 设置skip_fuse_bn=True表示跳过融合bn层,pytorch高版本融合bn层会出错
simplified_model, check = simplify(onnx_model, skip_fuse_bn=True)
onnx.save_model(simplified_model, filename)
onnx.checker.check_model(simplified_model)
# 如果出错
assert check, "简化模型失败"
print("模型简化成功")
----- 1 读取模型 -----
----- 2 检测图像 -----
['预测标签为: 331,预测概率为:54.409969329833984;', '预测标签为: 330,预测概率为:33.62083435058594;', '预测标签为: 332,预测概率为:11.84182071685791;', '预测标签为: 263,预测概率为:0.05221949517726898;', '预测标签为: 264,预测概率为:0.027525480836629868;']
----- 3 导出为onnx模型 -----
模型导出成功
----- 4 模型测试 -----
模型测试成功
----- 5 模型简化 -----
模型简化成功

2 参考

[深度学习] Pytorch模型转换为onnx模型笔记的更多相关文章

  1. [深度学习] Pytorch(三)—— 多/单GPU、CPU,训练保存、加载模型参数问题

    [深度学习] Pytorch(三)-- 多/单GPU.CPU,训练保存.加载预测模型问题 上一篇实践学习中,遇到了在多/单个GPU.GPU与CPU的不同环境下训练保存.加载使用使用模型的问题,如果保存 ...

  2. [深度学习] Pytorch学习(一)—— torch tensor

    [深度学习] Pytorch学习(一)-- torch tensor 学习笔记 . 记录 分享 . 学习的代码环境:python3.6 torch1.3 vscode+jupyter扩展 #%% im ...

  3. [置顶] 人工智能(深度学习)加速芯片论文阅读笔记 (已添加ISSCC17,FPGA17...ISCA17...)

    这是一个导读,可以快速找到我记录的关于人工智能(深度学习)加速芯片论文阅读笔记. ISSCC 2017 Session14 Deep Learning Processors: ISSCC 2017关于 ...

  4. 【6】TensorFlow光速入门-python模型转换为tfjs模型并使用

    本文地址:https://www.cnblogs.com/tujia/p/13862365.html 系列文章: [0]TensorFlow光速入门-序 [1]TensorFlow光速入门-tenso ...

  5. NLP与深度学习(四)Transformer模型

    1. Transformer模型 在Attention机制被提出后的第3年,2017年又有一篇影响力巨大的论文由Google提出,它就是著名的Attention Is All You Need[1]. ...

  6. [深度学习] pytorch学习笔记(2)(梯度、梯度下降、凸函数、鞍点、激活函数、Loss函数、交叉熵、Mnist分类实现、GPU)

    一.梯度 导数是对某个自变量求导,得到一个标量. 偏微分是在多元函数中对某一个自变量求偏导(将其他自变量看成常数). 梯度指对所有自变量分别求偏导,然后组合成一个向量,所以梯度是向量,有方向和大小. ...

  7. 深度学习PyTorch环境安装——mac

    参考:http://python.jobbole.com/87522/ 1.首先要安装Anaconda 1)什么是Anaconda Anaconda是Python的包管理器和环境管理器,是一个包含18 ...

  8. ER图/模型转换为关系模型

    ER图中的主要成分是实体类型和联系类型,转换规则就是如何把实体类型.联系类型转换成关系模式. 1. 二元联系转换 规则1.1(实体类型的转换):将每个实体类型转换成一个关系模式,实体的属性即为关系模式 ...

  9. NLP与深度学习(六)BERT模型的使用

    1. 预训练的BERT模型 从头开始训练一个BERT模型是一个成本非常高的工作,所以现在一般是直接去下载已经预训练好的BERT模型.结合迁移学习,实现所要完成的NLP任务.谷歌在github上已经开放 ...

随机推荐

  1. 糟了,线上服务出现OOM了

    前言 前一段时间,公司同事的一个线上服务OOM的问题,我觉得挺有意思的,在这里跟大家一起分享一下. 我当时其实也参与了一部分问题的定位. 1 案发现场 他们有个mq消费者服务,在某一天下午,出现OOM ...

  2. Java8新特性之Stream流(含具体案例)

    一.概述   Stream 流是 Java 8 新提供给开发者的一组操作集合的 API,将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选.排序.聚合等.元素 ...

  3. 齐博x1fun实例 鉴于很多人问列表的筛选怎么放到首页、内容页等等地方 贴出方法

    application\common\fun\Field.php 你可以复制一份 也可以直接改 直接改记得加锁 不然升级就覆盖了 我们把   public function list_filter($ ...

  4. Pyserial 学习

    # 连接串口 ser = serial.Serial("COM12", 115200, timeout=0.5, bytesize=8, parity=serial.PARITY_ ...

  5. perl中ENV的使用

    在打印环境变量的时候可以用到.实际上是%ENV,perl中的哈希变量,里面保存的是环境变量.键是环境变量名,值是环境变量值.例如,有一个环境变量是PATH,其值为C:\windows,那么,打印这个环 ...

  6. 浅谈HTTP缓存与CDN缓存的那点事

    HTTP缓存与CDN缓存一直是提升web性能的两大利器,合理的缓存配置可以降低带宽成本.减轻服务器压力.提升用户的体验.而不合理的缓存配置会导致资源界面无法及时更新,从而引发一系列的衍生问题.本文将分 ...

  7. 读书笔记:A Philosophy of Software Design

    今天一位同事在斯坦福的博士生导师John Ousterhout (注,Tcl语言的设计者)来公司做了他的新书<A Philosophy of Software Design>的演讲,介绍了 ...

  8. 重学c#系列——动态类型[二十二]

    前言 该系列准备继续完善,一共108篇,持续更新. 正文 为什么有动态类型呢? 是因为很多东西天生就是动态类型的. 比如xml 和 json.cvs.数据库表,这些本来就是数据类型的. 在反射系列中提 ...

  9. 决策树(二):后剪枝,连续值处理,数据加载器:DataLoader和模型评估

    在上一篇文章中,我们实现了树的构造,在下面的内容中,我们将中心放在以下几个方面 1.剪枝 2.连续值处理 3.数据加载器:DataLoader 4.模型评估 一,后剪枝 • 为什么剪枝  –" ...

  10. linux内核中的likely与unlikely

    前言 内核版本:linux 4.9.x.在linux内核中,经常可以看见if( likely(x))或if( unlikely(x))的语句,本文将基于likely和unlikely的定义和作用进行一 ...