import torch
import torchvision
import torchvision.models
from matplotlib import pyplot as plt
from tqdm import tqdm
from torch import nn
from torch.utils.data import DataLoader
from torchvision.transforms import transforms
data_transform = {
"train": transforms.Compose([transforms.RandomResizedCrop(120),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]),
"val": transforms.Compose([transforms.Resize((120, 120)), # cannot 224, must (224, 224)
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])}
train_data = torchvision.datasets.ImageFolder(root = "./data/train" , transform = data_transform["train"])
traindata = DataLoader(dataset=train_data, batch_size=128, shuffle=True, num_workers=0) # 将训练数据以每次32张图片的形式抽出进行训练
test_data = torchvision.datasets.ImageFolder(root = "./data/val" , transform = data_transform["val"])
train_size = len(train_data) # 训练集的长度
test_size = len(test_data) # 测试集的长度
print(train_size) #输出训练集长度看一下,相当于看看有几张图片
print(test_size) #输出测试集长度看一下,相当于看看有几张图片
testdata = DataLoader(dataset=test_data, batch_size=128, shuffle=True, num_workers=0) # 将训练数据以每次32张图片的形式抽出进行测试
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print("using {} device.".format(device))
def _make_divisible(ch, divisor=8, min_ch=None):
"""
This function is taken from the original tf repo.
It ensures that all layers have a channel number that is divisible by 8
It can be seen here:
https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py
"""
if min_ch is None:
min_ch = divisor
new_ch = max(min_ch, int(ch + divisor / 2) // divisor * divisor)
# Make sure that round down does not go down by more than 10%.
if new_ch < 0.9 * ch:
new_ch += divisor
return new_ch
class ConvBNReLU(nn.Sequential):
def __init__(self, in_channel, out_channel, kernel_size=3, stride=1, groups=1):
padding = (kernel_size - 1) // 2
super(ConvBNReLU, self).__init__(
nn.Conv2d(in_channel, out_channel, kernel_size, stride, padding, groups=groups, bias=False),
nn.BatchNorm2d(out_channel),
nn.ReLU6(inplace=True)
)
class InvertedResidual(nn.Module):
def __init__(self, in_channel, out_channel, stride, expand_ratio):
super(InvertedResidual, self).__init__()
hidden_channel = in_channel * expand_ratio
self.use_shortcut = stride == 1 and in_channel == out_channel
layers = []
if expand_ratio != 1:
# 1x1 pointwise conv
layers.append(ConvBNReLU(in_channel, hidden_channel, kernel_size=1))
layers.extend([
# 3x3 depthwise conv
ConvBNReLU(hidden_channel, hidden_channel, stride=stride, groups=hidden_channel),
# 1x1 pointwise conv(linear)
nn.Conv2d(hidden_channel, out_channel, kernel_size=1, bias=False),
nn.BatchNorm2d(out_channel),
])
self.conv = nn.Sequential(*layers)
def forward(self, x):
if self.use_shortcut:
return x + self.conv(x)
else:
return self.conv(x)
class MobileNetV2(nn.Module):
def __init__(self, num_classes=2, alpha=1.0, round_nearest=8):
super(MobileNetV2, self).__init__()
block = InvertedResidual
input_channel = _make_divisible(32 * alpha, round_nearest)
last_channel = _make_divisible(1280 * alpha, round_nearest)
inverted_residual_setting = [
# t, c, n, s
[1, 16, 1, 1],
[6, 24, 2, 2],
[6, 32, 3, 2],
[6, 64, 4, 2],
[6, 96, 3, 1],
[6, 160, 3, 2],
[6, 320, 1, 1],
]
features = []
# conv1 layer
features.append(ConvBNReLU(3, input_channel, stride=2))
# building inverted residual residual blockes
for t, c, n, s in inverted_residual_setting:
output_channel = _make_divisible(c * alpha, round_nearest)
for i in range(n):
stride = s if i == 0 else 1
features.append(block(input_channel, output_channel, stride, expand_ratio=t))
input_channel = output_channel
# building last several layers
features.append(ConvBNReLU(input_channel, last_channel, 1))
# combine feature layers
self.features = nn.Sequential(*features)
# building classifier
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
self.classifier = nn.Sequential(
nn.Dropout(0.2),
nn.Linear(last_channel, num_classes)
)
# weight initialization
for m in self.modules():
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out')
if m.bias is not None:
nn.init.zeros_(m.bias)
elif isinstance(m, nn.BatchNorm2d):
nn.init.ones_(m.weight)
nn.init.zeros_(m.bias)
elif isinstance(m, nn.Linear):
nn.init.normal_(m.weight, 0, 0.01)
nn.init.zeros_(m.bias)
def forward(self, x):
x = self.features(x)
x = self.avgpool(x)
x = torch.flatten(x, 1)
x = self.classifier(x)
return x
mobilenet = MobileNetV2(num_classes=2) #将模型命名为mobilenet
mobilenet.to(device)
print(mobilenet.to(device)) #输出模型结构
test1 = torch.ones(64, 3, 120, 120) # 测试一下输出的形状大小 输入一个64,3,120,120的向量
test1 = mobilenet(test1.to(device)) #将向量打入神经网络进行测试
print(test1.shape) #查看输出的结果
epoch = 1 # 迭代次数即训练次数
learning = 0.0001 # 学习率
optimizer = torch.optim.Adam(mobilenet.parameters(), lr=learning) # 使用Adam优化器-写论文的话可以具体查一下这个优化器的原理
loss = nn.CrossEntropyLoss() # 损失计算方式,交叉熵损失函数
train_loss_all = [] # 存放训练集损失的数组
train_accur_all = [] # 存放训练集准确率的数组
test_loss_all = [] # 存放测试集损失的数组
test_accur_all = [] # 存放测试集准确率的数组
for i in range(epoch): #开始迭代
train_loss = 0 #训练集的损失初始设为0
train_num = 0.0 #
train_accuracy = 0.0 #训练集的准确率初始设为0
mobilenet.train() #将模型设置成 训练模式
train_bar = tqdm(traindata) #用于进度条显示,没啥实际用处
for step, data in enumerate(train_bar): #开始迭代跑, enumerate这个函数不懂可以查查,将训练集分为 data是序号,data是数据
img, target = data #将data 分位 img图片,target标签
optimizer.zero_grad() # 清空历史梯度
outputs = mobilenet(img.to(device)) # 将图片打入网络进行训练,outputs是输出的结果
loss1 = loss(outputs, target.to(device)) # 计算神经网络输出的结果outputs与图片真实标签target的差别-这就是我们通常情况下称为的损失
outputs = torch.argmax(outputs, 1) #会输出10个值,最大的值就是我们预测的结果 求最大值
loss1.backward() #神经网络反向传播
optimizer.step() #梯度优化 用上面的abam优化
train_loss = train_loss + loss1.item() #将所有损失的绝
使用pytorch写的mobilenet v2代码,详细注释,可以生成训练集和测试集的损失和准确率的折线图
需积分: 0 5 浏览量
更新于2023-05-01
3
收藏 8.06MB RAR 举报
在本项目中,我们主要探讨的是使用PyTorch框架实现的Mobilenet V2神经网络模型,这是一个轻量级的深度学习模型,适用于资源有限的设备。 Mobilenet V2是MobileNet系列的第二版,它在保持高效计算的同时提高了模型的准确性。以下是关于这个项目的一些关键知识点:
1. **PyTorch框架**:PyTorch是Facebook开源的一个深度学习库,以其动态计算图和易用性而受到开发者喜爱。在本项目中,我们将利用PyTorch构建和训练神经网络。
2. **Mobilenet V2结构**:Mobilenet V2的核心创新在于其“倒残差块”(Inverted Residual Blocks),与传统的ResNet中残差块不同,它将扩张卷积(Dilated Convolution)用于输入层,而瓶颈层则使用标准卷积。这种设计使得模型更轻巧且能提高特征提取效率。
3. **模型搭建**:代码中的注释详细解释了如何构建Mobilenet V2的网络架构。这包括定义卷积层、批量归一化层(Batch Normalization)、ReLU激活函数以及残差连接。
4. **训练过程**:在PyTorch中,我们将定义损失函数(如交叉熵损失)和优化器(如Adam或SGD),然后在训练数据上迭代更新模型参数。每个训练周期后,我们会记录损失和准确率。
5. **验证与测试**:除了训练集,我们还会在验证集上评估模型性能,以避免过拟合。同时,代码还能生成训练集和测试集的损失及准确率的折线图,这有助于我们直观地理解模型的训练过程和泛化能力。
6. **数据预处理**:在使用图像数据之前,通常需要进行预处理,包括归一化、尺寸调整等。在PyTorch中,这些步骤可以通过DataLoader类实现,它能够加载数据并处理成模型可以接受的格式。
7. **模型保存与加载**:训练过程中,我们可以保存模型的权重以便后续使用。PyTorch提供了`torch.save()`和`torch.load()`函数来实现模型的持久化。
8. **可视化工具**:生成损失和准确率的折线图可能需要用到可视化库,如matplotlib或tensorboard,它们可以帮助我们监控训练进度。
9. **超参数调优**:为了达到最佳性能,可能需要调整学习率、批次大小、网络层数等超参数。这些参数的选择会影响模型的训练速度和最终性能。
10. **模型评估**:训练完成后,我们会在测试集上评估模型,以确定其在未见过的数据上的表现。评估指标通常包括准确率、精度、召回率和F1分数等。
通过这个项目,读者不仅可以了解PyTorch的基本用法,还可以深入理解Mobilenet V2的设计原理和实现细节,为自己的深度学习实践提供宝贵经验。在实际应用中,可以根据具体任务的需求对模型进行调整和优化。
小馨馨的小翟
- 粉丝: 2w+
- 资源: 10
最新资源
- C# Winform Excel 转 Chart示例视频
- uniapp-小程序-vue
- 台球检测11-YOLO(v5至v11)、COCO、CreateML、Paligemma、TFRecord、VOC数据集合集.rar
- 富芮坤FR8003作为主机连接FR8003抓包文件20241223-135206.pcapng
- 谷歌股票数据集,google股票数据集,Alphabet股份数据集(2004-2024)
- nuget 库官方下载包,可使用解压文件打开解压使用
- 非wine、原生Linux迅雷安装包deb文件,支持Ubuntu、UOS统信、深度Deepin、LinuxMint、Debain系通用
- KUKA机器人安装包,与PROFINET软件包
- 船舶燃料消耗和二氧化碳排放分析数据集,燃料消耗和碳排放关联分析数据
- req-sign、bd-ticket-ree-public加密算法(JS)