最新消息

欢迎来到 DH Hub!

我们是 南信大 DH 互联网技术社团

在这里收集当下火热的技术文章,并且分到对应板块内,作为社团的技术积累,供历届社友学习

本站不开放注册,访客可以正常浏览

  • 由于一些解析原因,建议先在本地编辑器写完以后再上传
  • 由于服务器原因,在编辑主题 / 回复时会有一定卡顿,请谅解。

人智 深度学习入门总结

主题 作者
成员
荣誉成员
09
4
4
文章类型
完全原创 —— 自由转载
各种层的用法

CONV2D(卷积层
对图形矩阵进行卷积运算

基础参数(NCHW),N batch_size,C Channels通道数,H Height 图片的像素高度, W width 图片的像素宽度

一般彩色图片通道数为3(RGB),相应的黑白图片通道数就只有1.

卷积的参数

Stride步长,卷积核每次移动距离的大小

Padding 填充 ,卷积核移动到边缘时,对不齐的像素进行补充的数值,便于更好利用图片周边的特征。

Dilation 空洞卷积,控制卷积核上每个点的间距,默认为1(此时为正常卷积)

以上三个参数,形式可以是int(宽高设置为一个数字),也可以是tuple(高宽的设置不同)

Kernel size 控制卷积核大小,参数为一个数字,卷积核为正方形,参数是元组,卷积核是(h,w)的矩形



在官方的文档里可以看到padding,dilation,kernel_size在宽高方面都是可以单独设置的。



实操代码

以官方的代码为例
图片1.jpg

图片2.jpg

图片3.jpg



步长,卷积核,填充数据为元组的情况,可以看到在高宽一样的情况下,输出的高宽不同
图片4.jpg

图片5.jpg



MAXPOOL2D(池化层)

对图形矩阵进行取最大值的运算

此层对数据的通道数没有影响,仅对现有的数据进行处理

Stride Padding Dilation意义与CONV2D中的相同

Kernel_Size 这里控制进行取最大值运算的窗口的大小,MAXPOOL的Kernel负责对对应的数据进行取最大值操作。

Ceil_Mode控制当剩余数据不足以填充Kernel时,是否保留数据计算,默认False,直接舍去数据,True则在剩余数据中进行取最大值运算。

实验代码

Ceil_Mode = True


图片7.jpg








Ceil_Mode = False


图片9.jpg







从公式中可以看出,Celi_Mode控制的是两边的取整符号,True向上取整,False向下取整,当步长=1时,此项对于Shape没有影响。

ReLU(非线性激活层)

非负数据保持原样,数值为负的变为0

代码示例





增加模型的非线性表达能力

Linear层(全连接层)


图解:

图片13.jpg


代码示例
Python:
import torch
from torch import nn

m = nn.Linear(2,1)
input = torch.randn(3, 2)
print(input)
output = m(input)
print(output)

这里Linear层把二维张量转化为一维张量(input=2,output =1)

实战MNIST数据集
Python:
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
import torchvision.datasets

train_data = torchvision.datasets.MNIST("./MINST", train=True, download=True,
                                        transform=torchvision.transforms.ToTensor())
train_dataloader = DataLoader(train_data, 64, True)

test_data = torchvision.datasets.MNIST("./MNIST", train=False, download=True,
                                       transform=torchvision.transforms.ToTensor())
test_dataloader = DataLoader(test_data, 64, True)

print(type(test_dataloader))


class Mnistmodule(nn.Module):
    def __init__(self):
        super().__init__()
        self.module = nn.Sequential(
            nn.Conv2d(1, 6, 1, 1),
            nn.MaxPool2d(1, 2),
            nn.Conv2d(6, 16, 5, 1),
            nn.MaxPool2d(1, 2, ceil_mode=True),
            nn.Flatten(),
            nn.Linear(16 * 5 * 5, 120),
            nn.Linear(120, 84),
            nn.Linear(84, 10)
        )

    def forward(self, x):
        x = self.module(x)
        return x


mnistmodule = Mnistmodule()
mnistmodule.to(torch.device("cuda"))

loss_cal = nn.CrossEntropyLoss()
loss_cal.cuda()

learn_rate = 1e-2
optimizer = torch.optim.SGD(mnistmodule.parameters(), learn_rate)

total_train_step = 0
total_test_step = 0
epoch = 10
train_loss = 0
test_losses = []


def test():
    mnistmodule.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_dataloader:
            data = data.cuda()
            target = target.cuda()
            output = mnistmodule(data)
            test_loss += torch.nn.functional.nll_loss(output, target, size_average=False).item()
            pred = output.data.max(1, keepdim=True)[1]
            correct += pred.eq(target.data.view_as(pred)).sum()
    test_loss /= len(test_dataloader.dataset)
    print('\nTest set: Avg. loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_dataloader.dataset),
        100. * correct / len(test_dataloader.dataset)))


for i in range(epoch):
    print("*************第{}轮训练开始****************".format(i + 1))
    train_loss = 0
    for data in train_dataloader:
        imgs, targets = data
        imgs = imgs.cuda()
        targets = targets.cuda()
        outputs = mnistmodule(imgs)
        loss = loss_cal(outputs, targets)
        # 优化器和loss的使用
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        total_train_step += 1
        train_loss += loss
    print("当前训练次数{}, Loss={}".format(total_train_step, train_loss / len(test_dataloader.dataset)))
    test()
训练10轮,正确率达到91%
 

附件

  • 图片6.jpg
    图片6.jpg
    15.9 KB · 查看: 67
  • 图片8.jpg
    图片8.jpg
    15.5 KB · 查看: 70
成员
荣誉成员
09
17
5
## CONV2D(卷积层)Numpy 实现
Python:
# 简单实现:stride=1, padding=0

import numpy as np

def conv(A, B):
    N, CI, H, W = A.shape
    CO, _, K, _ = B.shape
    OUT_H, OUT_W = H - K + 1, W - K + 1
    C = np.zeros((N, CO, OUT_H, OUT_W), dtype=np.int64)

    for n in range(N):
        for c in range(CO):
            for h in range(OUT_H):
                for w in range(OUT_W):
                    for i in range(CI):
                        for k1 in range(K):
                            for k2 in range(K):
                                C[n, c, h, w] += A[n, i, h + k1, w + k2] * B[c, i, k1, k2]

    return C
 
成员
荣誉成员
09
17
5
手写TVM算子
Python:
@tvm.script.ir_module
class MyConv:
  @T.prim_func
  def conv(A: T.Buffer((N, CI, H, W), "int64"),
          B: T.Buffer((CO, CI, K, K), "int64"),
          C: T.Buffer((N, CO, H-K+1, W-K+1), "int64")):
    T.func_attr({"global_symbol": "conv", "tir.noalias": True})
    for n, c, h, w, i, k1, k2 in T.grid(N, CO, OUT_H, OUT_W, CI, K, K):
        with T.block("C"):
            vn = T.axis.spatial(1, n)
            vc = T.axis.spatial(2, c)
            vh = T.axis.spatial(6, h)
            vw = T.axis.spatial(6, w)
            vi = T.axis.spatial(1, i)
            vk1 = T.axis.reduce(3, k1)
            vk2 = T.axis.reduce(3, k2)
            with T.init():
                C[vn, vc, vh, vw] = T.int64(0)
            C[vn, vc, vh, vw] = C[vn, vc, vh, vw] + A[vn, vi, vh + vk1, vw + vk2] * B[vc, vi, vk1, vk2]

rt_lib = tvm.build(MyConv, target="llvm")
data_tvm = tvm.nd.array(data)
weight_tvm = tvm.nd.array(weight)
conv_tvm = tvm.nd.array(np.empty((N, CO, OUT_H, OUT_W), dtype=np.int64))
rt_lib["conv"](data_tvm, weight_tvm, conv_tvm)
conv_tvm
 
顶部