resnext和SEresnet代码详解(一行一行代码详解)

resnext和SEresnet代码详解(⼀⾏⼀⾏代码详解)resnext是由resnet50演变⽽来,于resnet50的区别就是在卷积块和激活函数之间其增加了bn板块,是为了对数据进⾏归⼀化处理,还有就是增加了分组,在论⽂中是将resnet⾥的图像channel分成了32组再加上bn板块即构成了resnext,⽽SEresnet实在resnext的基础上演变⽽来的,其是在resnext上在每个block⾥⾯增加了对原图像进⾏加权操作,主要通过全局平均池化、全连接线性层、ReLU操作、全连接线性层以及Sigmoid函数求得各个通道的权重值,再通过Scale(乘积)操作完成加权。在实例中,⽤卷积层代替全连接层,试图减少图⽚的语义损失。具体参见这个博主的博客,讲的是⾮常的详细!
下⾯分别附上resnext的代码还有seresnet的代码,可以直接运⾏!!
下⾯是resnext的代码:
1resnext的代码
2
3import torch
4from torch import nn
5
6import torch
as nn
8
9class Block(nn.Module):
10    def __init__(self,in_channels, out_channels, stride=1, is_shortcut=False):
11        super(Block,self).__init__()
12        # 继承block的⽗类进⾏初始化。⽽且是⽤⽗类的初始化⽅法来初始化继承的属性
13        lu = nn.ReLU(inplace=True)
14        # inplace-选择是否进⾏覆盖运算,即是否将得到的值计算得到的值覆盖之前的值
15        self.is_shortcut = is_shortcut
16        v1 = nn.Sequential(
17            # Sequential⼀个有序的容器,神经⽹络模块将按照在传⼊构造器的顺序依次被添加到计算图中执⾏,
18            nn.Conv2d(in_channels, out_channels // 2, kernel_size=1,stride=stride,bias=False),
19            nn.BatchNorm2d(out_channels // 2),
20            # 添加BatchNorm2d进⾏数据的归⼀化处理,这使得数据在进⾏Relu之前不会因为数据过⼤⽽导致⽹络性能的不稳定
21            nn.ReLU()
22        )
23        v2 = nn.Sequential(
24            nn.Conv2d(out_channels // 2, out_channels // 2, kernel_size=3, stride=1, padding=1, groups=32,
25                                  bias=False),
26            nn.BatchNorm2d(out_channels // 2),
27            nn.ReLU()
28        )
29        v3 = nn.Sequential(
30            nn.Conv2d(out_channels // 2, out_channels, kernel_size=1,stride=1,bias=False),
31            nn.BatchNorm2d(out_channels),
32        )
33        if is_shortcut:
34            self.shortcut = nn.Sequential(
35            nn.Conv2d(in_channels,out_channels,kernel_size=1,stride=stride,bias=1),
36            nn.BatchNorm2d(out_channels)
37        )
38    def forward(self, x):
39        x_shortcut = x
40        x = v1(x)
41        x = v2(x)
42        x = v3(x)
43        if self.is_shortcut:
44            x_shortcut = self.shortcut(x_shortcut)
45        x = x + x_shortcut
46        x = lu(x)
47        return x
48
48
49class Resnext(nn.Module):
50    def __init__(self,num_classes,layer=[3,4,6,3]):
51        super(Resnext,self).__init__()
52        v1 = nn.Sequential(
53            nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False),
54            nn.BatchNorm2d(64),
55            nn.ReLU(),
56            nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
57        )
58        v2 = self._make_layer(64,256,1,num=layer[0])
59        v3 = self._make_layer(256,512,2,num=layer[1])
激光修复机
60        v4 = self._make_layer(512,1024,2,num=layer[2])
61        v5 = self._make_layer(1024,2048,2,num=layer[3])
62        self.global_average_pool = nn.AdaptiveAvgPool2d((1, 1))
63        self.fc = nn.Linear(2048,num_classes)
64        # in_features指的是输⼊的⼆维张量的⼤⼩,即输⼊的[batch_size, size]中的size。
65        # out_features指的是输出的⼆维张量的⼤⼩,即输出的⼆维张量的形状为[batch_size,output_size],当然,它也代表了该全连接层的神经元个数。
66        # 从输⼊输出的张量的shape⾓度来理解,相当于⼀个输⼊为[batch_size, in_features]的张量变换成了[batch_size, out_features]的输出张量。
67    def forward(self, x):
68        x = v1(x)
69        x = v2(x)
70        x = v3(x)
71        x = v4(x)
72        x = v5(x)
73        x = self.global_average_pool(x)
74        x = torch.flatten(x,1)
75        # 1)flatten(x,1)是按照x的第1个维度拼接(按照列来拼接,横向拼接);
76        # 2)flatten(x,0)是按照x的第0个维度拼接(按照⾏来拼接,纵向拼接);
77        # 3)有时候会遇到flatten⾥⾯有两个维度参数,flatten(x, start_dim, end_dimension),此时flatten函数执⾏的功能是将从start_dim到end_dim之间的所有维
78        # 其他的维度保持不变。例如x是⼀个size为[4,5,6]的tensor, flatten(x, 0, 1)的结果是⼀个size为[20,6]的tensor。
79        x = self.fc(x)
80        return x
81
82    # 形成单个Stage的⽹络结构
83    def _make_layer(self,in_channels,out_channels,stride,num):
84        layers = []
85        block_1=Block(in_channels, out_channels,stride=stride,is_shortcut=True)
86        layers.append(block_1)
87        # 该部分是将每个blocks的第⼀个残差结构保存在layers列表中。
88        for i in range(1, num): # Identity Block结构叠加; 基于[3, 4, 6, 3]
89            layers.append(Block(out_channels,out_channels,stride=1,is_shortcut=False))
90            # 该部分是将每个blocks的剩下残差结构保存在layers列表中,这样就完成了⼀个blocks的构造。
91        return nn.Sequential(*layers)
92    # 返回Conv Block和Identity Block的集合,形成⼀个Stage的⽹络结构
93
94
95
96
97import time
98import torch
99import torchvision
ansforms as transforms
101import matplotlib.pyplot as plt
102
103
104def load_dataset(batch_size):
105    # 下载训练
106    train_set = torchvision.datasets.CIFAR10(
107        root="data/cifar-10", train=True,
108        download=True, transform=transforms.ToTensor()
109        # transforms.ToTensor()的操作对象有PIL格式的图像以及numpy(即cv2读取的图像也可以)这两种。对象不能是tensor格式的,因为是要转换为tensor的110    )
111    # 下载测试
112    test_set = torchvision.datasets.CIFAR10(
113        root="data/cifar-10", train=False,
113        root="data/cifar-10", train=False,
114        download=True, transform=transforms.ToTensor()
115    )
116    train_iter = torch.utils.data.DataLoader(
117        train_set, batch_size=batch_size, shuffle=True, num_workers=0
118        # 该接⼝主要⽤来将⾃定义的数据读取接⼝的输出或者PyTorch已有的数据读取接⼝的输⼊按照batch size封装成Tensor,后续只需要再包装成Variable即可119        # shuffle 将训练模型的数据集进⾏打乱的操作
120        # num_workers,从注释可以看出这个参数必须⼤于等于0,0的话表⽰数据导⼊在主进程中进⾏,其他⼤于0的数表⽰通过多个进程来导⼊数据,可以加快121    )
122    test_iter = torch.utils.data.DataLoader(
123        test_set, batch_size=batch_size, shuffle=True, num_workers=0
124    )
125    return train_iter, test_iter
126
127# 训练模型
128def train(net, train_iter, criterion, optimizer, num_epochs, device, num_print, lr_scheduler=None, test_iter=None):
129    ain()
130    record_train = list()
131    # 记录每⼀Epoch下训练集的准确率
132    # List() ⽅法⽤于将元组转换为列表。
133    record_test = list()
134
135    for epoch in range(num_epochs):
136        print("========== epoch: [{}/{}] ==========".format(epoch + 1, num_epochs))
137        total, correct, train_loss = 0, 0, 0
138        start = time.time()
139
140        for i, (X, y) in enumerate(train_iter):
141            # enumerate就是枚举的意思,把元素⼀个个列举出来,第⼀个是什么,第⼆个是什么,所以他返回的是元素以及对应的索引。
142            device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
143            X, y = X.to(device), y.to(device)
144            output = net(X)
145            loss = criterion(output, y) # 计算LOSS
146
147            _grad()  # 梯度归零
148            loss.backward()  # 反向传播
149            optimizer.step()  # 更新参数
150
151            train_loss += loss.item()
152            total += y.size(0)
153            correct += (output.argmax(dim=1) == y).sum().item() # 累积预测正确的样本数
154            # output.argmax(dim=1) 返回指定维度最⼤值的序号,dim=1,把dim=1这个维度的,变成这个维度的最⼤值的index
采空区处理方法
155            # 即 dim=1是取每⼀列最⼤值的下标,dim=2是取每⼀⾏最⼤值的下标
156            train_acc = 100.0 * correct / total
157
158            if (i + 1) % num_print == 0:
159                print("step: [{}/{}], train_loss: {:.3f} | train_acc: {:6.3f}% | lr: {:.6f}" \
160                    .format(i + 1, len(train_iter), train_loss / (i + 1), \
161                            train_acc, get_cur_lr(optimizer)))
162
163
164        if lr_scheduler is not None:
165            # 调整梯度下降算法的学习率
166            lr_scheduler.step()
电极箔
167        # 输出训练的时间
168        print("--- cost time: {:.4f}s ---".format(time.time() - start))
169
170        if test_iter is not None:  # 判断测试集是否为空 (注意这⾥将调⽤test函数)
171            record_test.append(test(net, test_iter, criterion, device)) # 每训练⼀个Epoch模型,使⽤测试集进⾏测试模型的准确度
172        record_train.append(train_acc)
173        # append() ⽅法⽤于在列表末尾追加新的对象。
174    # 返回每⼀个Epoch下测试集和训练集的准确率
175    return record_train, record_test
176
177# 验证模型
178def test(net, test_iter, criterion, device):
178def test(net, test_iter, criterion, device):
179    total, correct = 0, 0
180    net.eval()# 测试模式
181
182    _grad():
183        print("*************** test ***************")
184        for X, y in test_iter:
185            X, y = X.to(device), y.to(device)# CPU or GPU运⾏
186
187            output = net(X)  # 计算输出
188            loss = criterion(output, y)  # 计算损失
189
190            total += y.size(0)  # 计算测试集总样本数
191            correct += (output.argmax(dim=1) == y).sum().item()  # 计算测试集预测准确的样本数
192
193        test_acc = 100.0 * correct / total  # 测试集准确率
194
195        # 输出测试集的损失
196    print("test_loss: {:.3f} | test_acc: {:6.3f}%" \
197          .format(loss.item(), test_acc))
审批流
198    print("************************************\n")
199
200    # 训练模式(因为这⾥是因为每经过⼀个Epoch就使⽤测试集⼀次,使⽤测试集后,进⼊下⼀个Epoch前将模型重新置于训练模式)201    ain()
202
203    return test_acc
204
205
运钞箱206# 返回学习率lr的函数
207def get_cur_lr(optimizer):
208    for param_group in optimizer.param_groups:
209        return param_group['lr']
210
211
212# 画出每⼀个Epoch下测试集和训练集的准确率
213def learning_curve(record_train, record_test=None):
214    plt.style.use("ggplot")
215    # 画图⼯具:blog.csdn/viviliving/article/details/107690844
216    plt.plot(range(1, len(record_train) + 1), record_train, label="train acc")
217    # plt.plot的⽤法 zhuanlan.zhihu/p/258106097
218    if record_test is not None:
219        plt.plot(range(1, len(record_test) + 1), record_test, label="test acc")
220
221    plt.legend(loc=4)
222    # loc:图例位置
223    plt.title("learning curve")
224    icks(range(0, len(record_train) + 1, 5))
225    icks(range(0, 101, 5))
226    plt.xlabel("epoch")
227    plt.ylabel("accuracy")
228
229    plt.show()
230
231
232import torch.optim as optim
233
234
235BATCH_SIZE = 128  # 批⼤⼩
236NUM_EPOCHS = 12  # Epoch⼤⼩
237NUM_CLASSES = 10  # 分类的个数
238LEARNING_RATE = 0.01  # 梯度下降学习率
239MOMENTUM = 0.9  # 冲量⼤⼩
240WEIGHT_DECAY = 0.0005  # 权重衰减系数
241NUM_PRINT = 100
242DEVICE = "cuda" if torch.cuda.is_available() else "cpu"  # GPU or CPU运⾏
243
243
244
245def main():
246    net = Resnext(NUM_CLASSES)
247    net = (DEVICE)
248
249    train_iter, test_iter = load_dataset(BATCH_SIZE)  # 导⼊训练集和测试集
250
251    criterion = nn.CrossEntropyLoss()  # 交叉熵损失函数损失计算器
252    # 优化器
253    optimizer = optim.SGD(
254        net.parameters(),
255        # 构建好神经⽹络后,⽹络的参数都保存在parameters()函数当中
256        lr=LEARNING_RATE,
257        momentum=MOMENTUM,
258        weight_decay=WEIGHT_DECAY,
259        nesterov=True
260    )
261    # 调整学习率 (step_size:每训练step_size个epoch,更新⼀次参数; gamma:更新lr的乘法因⼦) 262    lr_scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)
263
264    record_train, record_test = train(net, train_iter, criterion, optimizer, \
265          NUM_EPOCHS, DEVICE, NUM_PRINT, lr_scheduler, test_iter)
266
267    learning_curve(record_train, record_test) # 画出准确率曲线
268
269
270
271main()
272
273
下⾯是SEresnet的代码
1## 导⼊第三⽅库
2from torch import nn
3import time
4import torch
5import torchvision
ansforms as transforms
7import matplotlib.pyplot as plt
8import torch.optim as optim
9
10
11# 搭建基于SENet的Conv Block和Identity Block的⽹络结构
12class Block(nn.Module):
13    def __init__(self, in_channels, filters, stride=1, is_1x1conv=False):
14        super(Block, self).__init__()
15
16        # 各个Stage中的每⼀⼤块中每⼀⼩块的输出维度,即channel(filter1 = filter2 = filter3 / 4)
17        filter1, filter2, filter3 = filters
18
19        self.is_1x1conv = is_1x1conv  # 判断是否是Conv Block
20        lu = nn.ReLU(inplace=True)  # RELU操作
21
22        # 第⼀⼩块, stride = 1(stage = 1) or stride = 2(stage = 2, 3, 4)
23        v1 = nn.Sequential(
24            nn.Conv2d(in_channels, filter1, kernel_size=1, stride=stride, bias=False),
25            nn.BatchNorm2d(filter1),
26            nn.ReLU()
油田载荷传感器27        )
28
29        # 中间⼩块
30        v2 = nn.Sequential(

本文发布于:2024-09-21 20:40:09,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/1/279397.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:测试   数据   训练
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议