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_
神经网络
一个神经网络类一般包含init、forward、initialize_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§一直为常数,可以忽略
所以在机器学习中,优化交叉熵等价于优化相对熵