网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
image_dir = 'D:/Notebook/cell\_images'
def imshow(image):
plt.figure(figsize=(6, 6))
plt.imshow(image)
plt.axis('off')
plt.show()
#可视化一张感染的图
x = Image.open(image_dir + '/Parasitized/C39P4thinF\_original\_IMG\_20150622\_111206\_cell\_84.png')
np.array(x).shape
imshow(x)
定义转换并加载进数据
转换是将一个图形、表达式或函数转换为另一个图形、表达式或函数的过程。
我们需要为训练、测试以及验证数据定义一些转换。值得注意的,可能有的类别图像太少,不够进行转换,为了增加网络识别的图像数量,我们执行所谓的数据增强。
在训练期间,我们随机裁剪、缩放和旋转图像,以便在每个时期,网络会看到同一图像的不同变化,提高实验的准确性。
# Define transforms for the training, validation, and testing sets
train_transforms = transforms.Compose([transforms.RandomResizedCrop(size=256, scale=(0.8, 1.0)),
transforms.RandomRotation(degrees=15),
transforms.ColorJitter(),
transforms.RandomHorizontalFlip(),
transforms.CenterCrop(size=224), # Image net standards
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])
test_transforms = transforms.Compose([transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])])
validation_transforms = transforms.Compose([transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])])
接下来加载数据集。最简单的方法是用torchvision的dataset.ImageFolder。
加载imageFolder后,我们将数据拆分为20%验证集和10%测试集; 然后将它传递给DataLoader。
它接收一个类似从ImageFolder获得的数据集,并返回批量图像及其相应的标签(可以将改组设置为true以在时期内引入变化)。
# Loading in the dataset
train_data = datasets.ImageFolder(image_dir, transform=train_transforms)
# number of subprocesses to use for data loading
num_workers = 0
# percentage of training set to use as validation
valid_size = 0.2
test_size = 0.1
# obtain training indices that will be used for validation
num_train = len(train_data)
indices = list(range(num_train))
np.random.shuffle(indices)
valid_split = int(np.floor((valid_size) \* num_train))
test_split = int(np.floor((valid_size + test_size) \* num_train))
valid_idx, test_idx, train_idx = indices[:valid_split], indices[valid_split:test_split], indices[test_split:]
print(len(valid_idx), len(test_idx), len(train_idx))
# define samplers for obtaining training and validation batches
train_sampler = SubsetRandomSampler(train_idx)
valid_sampler = SubsetRandomSampler(valid_idx)
test_sampler = SubsetRandomSampler(test_idx)
# prepare data loaders (combine dataset and sampler)
train_loader = torch.utils.data.DataLoader(train_data, batch_size=32, sampler=train_sampler, num_workers=num_workers)
valid_loader = torch.utils.data.DataLoader(train_data, batch_size=32, sampler=valid_sampler, num_workers=num_workers)
test_loader = torch.utils.data.DataLoader(train_data, batch_size=32, sampler=test_sampler, num_workers=num_workers)
5511 2756 19291
模型训练流程
- 加载预先训练的模型
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# pretrained=True will download a pretrained network for us
model = models.densenet121(pretrained=True)
#model
PyTorch以及几乎所有其他深度学习框架,都使用CUDA来有效地计算GPU上的前向和后向传递。
在PyTorch中,我们使用model.cuda()将模型参数和其他张量移动到GPU内存,或者从GPU移回,
import tensorwatch as tw
import os
os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin'
tw.draw_model(model, [1, 3, 224, 224])
Pytorch网络结构可视化
所需库文件:
- graphviz
- tensorwatch
draw_model函数需要传入三个参数,第一个为model,第二个参数为input_shape,第三个参数为orientation,可以选择’LR’或者’TB’,分别代表左右布局与上下布局。
统计网络参数
可以通过model_stats方法统计各层的参数情况。
tw.draw_model(model, [1, 3, 224, 224], orientation='LR')
tw.model_stats(model, [1, 3, 224, 224])
- 冻结卷积层并使用自定义分类器替换全连接层
#Freezing model parameters and defining the fully connected network to be attached to the model, loss function and the optimizer.
#We there after put the model on the GPUs
for param in model.parameters():
param.require_grad = False
fc = nn.Sequential(
nn.Linear(1024, 460),
nn.ReLU(),
nn.Dropout(0.4),
nn.Linear(460,2),
nn.LogSoftmax(dim=1)
)
model.classifier = fc
criterion = nn.NLLLoss()
#Over here we want to only update the parameters of the classifier so
optimizer = torch.optim.Adam(model.classifier.parameters(), lr=0.003)
model.cuda()
冻结模型参数允许我们为早期卷积层保留预训练模型的权重,其目的是用于特征提取。
然后我们定义我们的全连接网络,示例代码中是1024。
我们还定义了要使用的激活函数,和有助于通过随机关闭层中的神经元,以强制在剩余节点之间共享信息,来避免过度拟合。
在我们定义了自定义全连接网络之后,我们将其连接到预先训练好的模型的完全连接网络。
接下来我们定义损失函数,优化器,并通过将模型移动到GPU来准备训练模型。
- 为特定任务训练自定义分类器
在训练期间,我们遍历每个时期的DataLoader。 对于每个batch,使用标准函数计算损失。
使用loss.backward()方法计算相对于模型参数的损失梯度。
optimizer.zero_grad()负责清除任何累积的梯度,因为我们会一遍又一遍地计算梯度。
optimizer.step()使用具有动量的随机梯度下降(Adam)更新模型参数。
为了防止过度拟合,我们使用一种称为早期停止的强大技术。背后的想法很简单,当验证数据集上的性能开始降低时停止训练。
epochs = 10
valid_loss_min = 0.0
torch.device('cuda')
torch.backends.cudnn.benchmark = True
import time
for epoch in range(epochs):
start = time.time()
# scheduler.step()
model.to(device)
model.train()
train_loss = 0.0
valid_loss = 0.0
for index, (inputs, labels) in enumerate(train_loader):
# Move input and label tensors to the default device
inputs, labels = inputs.cuda(), labels.cuda()
logps = model(inputs)
loss = criterion(logps, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
train_loss += loss.item()
model.eval()
with torch.no_grad():
accuracy = 0
for inputs, labels in valid_loader:
inputs, labels = inputs.to(device), labels.to(device)
logps = model.forward(inputs)
batch_loss = criterion(logps, labels)
valid_loss += batch_loss.item()
# Calculate accuracy
![img](https://img-blog.csdnimg.cn/img_convert/774b6fbccc7fee6b3af5bdb6c5c6c93d.png)
![img](https://img-blog.csdnimg.cn/img_convert/8ec4981fe87a15f136a38db46b7552e3.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**
g-uo2h9IL9-1715881431384)]
[外链图片转存中...(img-cxogT334-1715881431384)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**