随机种子模块
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_
神经网络
1、_init_部分:
1.1定义传入参数:classes
即最后的分类数,也就是最后一层全连接层的输出
1.2定义网络结构
需要在nn.sequential()中定义网络结构,并对其命名
可以使用:
nn.Conv2d(in_channel,out_channel,kernel_size) 二维卷积
nn.Linear(in_size,out_size) 全连接层
nn.ReLU()
nn.LogSoftmax(dim=?)
来搭建神经网络框架
2、forward部分:
执行并返回神经网络
3、initialize_weights部分
权重初始化,即使不自己初始化部分网络结构也会自己初始化,但会不理想
class net_test(nn.Module): # 神经网络结构
def __init__(self, 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_()
损失函数模块:
loss_function = nn.CrossEntropyLoss() # 确定要使用的损失函数 #训练之后,获得outputs loss = loss_function(outputs, labels) # 得到损失值 loss.backward() # 根据损失值,反向传播
损失函数的选择:
1、nn.CrossEntropyLoss(weight=None, size_average=None,ignore_index=-100,reduce=None,reduction=‘mean’)
交叉熵损失函数 功能:利用nn.LogSoftmax()与nn.NLLLoss(),进行交叉熵计算
参数:
weight: 想让模型更关注哪一类,可将其权重值设大一些,如将第0类权重设为1.2,则其loss就会放大1.2倍
ignore_index: 忽略哪一个类别,不计算其损失函数
reduction: 取值 none/sum/mean
none:逐个元素计算,有多少类别返回多少loss
sum:对所有loss进行求和,返回标量
mean:对所有loss加权平均,返回标量
数据运算形式:
不加权重形式推导
红框中,先对结果进行softmax处理,将结果化为0~1的概率形式
篮筐中,再对结果取交叉熵,
注释:LogSoftmax已经完成了softmax和取log的功能,NLLLoss只是对其取了负号
理论交叉熵公式:
与理论中的交叉熵公式对比,缺少了P(xi)这一项,这一项为1,因为xi已经被取出,为必然事件
2、nn.NLLLoss() 功能:实现负对数似然函数中的负号功能
3、nn.BCELoss() 功能:二分类交叉熵
4、nn.BCEWithLogitsLoss() 功能:结合Sigmoid与二分类交叉熵 。注意事项:网络最后不用再加Sigmoid
5、nn.L1Loss() 功能:计算inputs与target只差的绝对值
6、nn.MSELoss() 功能:计算inputs与target之差的平方
7、nn.SmoothL1Loss() 功能:
8. nn.PoissonNLLLoss()
9. nn.KLDivLoss()
10. nn.MarginRankingLoss()
11. nn.MultiLabelMarginLoss()
12. nn.SoftMarginLoss()
13. nn.MultiLabelSoftMarginLoss()
14. nn.MultiMarginLoss()
15. nn.TripletMarginLoss()
16. nn.HingeEmbeddingLoss()
17. nn.CosineEmbeddingLoss()
18. nn.CTCLoss()
其他数据处理部分:
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§一直为常数,可以忽略
所以在机器学习中,优化交叉熵等价于优化相对熵



