Pytorch-搭建网络框架(一)

Hello

随机种子模块
transform模块
逆transform模块

神经网络模块
损失函数模块
优化器模块

一个框架的搭建,主要包括四个部分,数据模型损失函数优化器
模型:搭建出针对训练数据的算法结构,如神经网络的内部层结构等
损失函数:确定损失函数,计算损失值,反向传播
优化器:根据反向传播的梯度值更新

关系:
模型产生预测值损失函数根据预测值计算损失值,并反向传播得到梯度值优化器根据梯度值对模型参数更新

随机种子模块(可选)

设置随机种子模块,使结果可重复

def set_seed(seed=1):
	random.seed(seed)
	np.random.seed(seed)
	torch.manual_seed(seed)
	torch.cuda.manual_seed(seed)

set_seed(2)

transform模块

功能:可对原始图片进行中心裁剪、随即裁剪、缩放、转张量、数据标准化等操作
可增加训练数据的丰富性
输入:原始图像数据
输出:多样变形后的图像数据

train_transform = transforms.Compose([  # 定义transform,对读入图片进行怎样的处理
    # 可添加图像缩放或裁剪的操作
    # 1 CenterCrop
    # transforms.CenterCrop(512),     # 中心裁剪 512*512

    # 2 RandomCrop
    # transforms.RandomCrop(224, padding=16), #上下左右填充16之后进行随机裁剪
    # transforms.RandomCrop(224, padding=(16, 64)),  #左右填充16,上下填充64之后再进行裁剪
    # transforms.RandomCrop(224, padding=16, fill=(255, 0, 0)),  #都填充16,且像素值为(255, 0, 0)
    # transforms.RandomCrop(512, pad_if_needed=True),   # pad_if_needed=True 当裁剪大小超出原始图片大小时需要填写参数pad_if_needed=True
    # transforms.RandomCrop(224, padding=64, padding_mode='edge'), #使用边缘像素点填充
    # transforms.RandomCrop(224, padding=64, padding_mode='reflect'), #镜像填充,以原始图像边缘为对称轴
    # transforms.RandomCrop(1024, padding=1024, padding_mode='symmetric'), #另类镜像

    # 此三步一般都会有
    transforms.Resize((32, 32)),  # 一般也会有,将图片统一缩放为一样的大小,缩放之后的图像可能会大幅失真
    transforms.ToTensor(),  # 必须的操作,数据转为张量形式,并进行归一化操纵,将像素值从0~255归一化到0~1
    transforms.Normalize(norm_mean, norm_std),  # 数据标准化,可以加快收敛,加强训练效果

])

逆transform模块

输入:transform之后的图片数据,tensor
输出:原始图片数据,PIL格式数据

def transform_invert(img_, transform_train):
    """
    将data 进行反transfrom操作
    :param img_: tensor
    :param transform_train: torchvision.transforms
    :return: PIL image
    """
    if 'Normalize' in str(transform_train):
        norm_transform = list(filter(lambda x: isinstance(x, transforms.Normalize), transform_train.transforms))
        mean = torch.tensor(norm_transform[0].mean, dtype=img_.dtype, device=img_.device)
        std = torch.tensor(norm_transform[0].std, dtype=img_.dtype, device=img_.device)
        img_.mul_(std[:, None, None]).add_(mean[:, None, None])

    img_ = img_.transpose(0, 2).transpose(0, 1)  # C*H*W --> H*W*C
    if 'ToTensor' in str(transform_train) or img_.max() < 1:
        img_ = img_.detach().numpy() * 255

    if img_.shape[2] == 3:
        img_ = Image.fromarray(img_.astype('uint8')).convert('RGB')
    elif img_.shape[2] == 1:
        img_ = Image.fromarray(img_.astype('uint8').squeeze())
    else:
        raise Exception("Invalid img shape, expected 1 or 3 in axis 2, but got {}!".format(img_.shape[2]))

    return img_

神经网络

一个神经网络类一般包含initforwardinitialize_weights三个方法
对应实现网络初始化前向传播权值初始化三个功能

1、_init_部分
定义网络结构
在nn.sequential()中定义每层网络,用参数接收封装网络的返回值

每层网络结构可以使用:
nn.Conv2d(in_channel,out_channel,kernel_size) 二维卷积
nn.Linear(in_size,out_size) 全连接层
nn.ReLU()
nn.LogSoftmax(dim=?)
来搭建神经网络框架

2、forward部分:
根据你的需求,按照顺序来调用_init_中定义的神经网络

3、initialize_weights部分
权重初始化,即使不自己初始化,部分网络结构也会自己初始化,但自动初始化的参数可能会不理想

class net_test(nn.Module):  # 神经网络结构
    def __init__(self, classes): # 初始化时传入参数classes,即最后的分类数,也就是最后一层全连接层的输出
        super(net_test, self).__init__()
        self.net = nn.Sequential( # 定义网络结构
            nn.Conv2d(3, 6, 5),  # (in_channels,out_channels,kernel_size)
            nn.ReLU(),
            nn.Conv2d(6, 16, 5),
            nn.ReLU(),
        )
        self.classifier = nn.Sequential(
            nn.Linear(16 * 24 * 24, 120),
            nn.ReLU(),
            nn.Linear(120, 84),
            nn.ReLU(),
            nn.Linear(84, classes),
            nn.LogSoftmax(dim=0),
        )

    def forward(self, x):
        x = self.net(x)
        print('卷积之后size:', x.size())
        x = x.view(x.size()[0], -1)  # 将数据变为[1,?]
        print('尺寸变换后:', x.size())
        out = self.classifier(x)
        return out    
    
    def initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.xavier_normal_(m.weight.data)
                if m.bias is not None:
                    m.bias.data.zero_()
            elif isinstance(m, nn.BatchNorm2d):
                m.weight.data.fill_(1)
                m.bias.data.zero_()
            elif isinstance(m, nn.Linear):
                nn.init.normal_(m.weight.data, 0, 0.1)
                m.bias.data.zero_()

损失函数模块

见Pytorch-搭建网络框架(二)

优化器 Optimizer

待完成

其他数据处理部分:

inputs = img # 读入原始数据,三维
inputs.unsqueeze_(dim=0)  # 三维转四维,
net = net_test(3)  # 网络初始化
net.initialize_weights() # 权值初始化

循环结构:
outputs = net(inputs) # 输入数据
optimizer.zero_grad() # 梯度清零
loss = loss_function(outputs, labels) # 得到损失值
loss.backward() # 根据损失值,反向传播
optimizer.step() # 更新权值

知识补充:
1、交叉熵、信息熵(KL散度)、相对熵
交叉熵 = 信息熵 + 相对熵
在这里插入图片描述
在这里插入图片描述
P为训练集中的样本分布,是固定的,所以H§一直为常数,可以忽略
所以在机器学习中,优化交叉熵等价于优化相对熵

Bye

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值