欢迎浏览本博客
大家好,我是:我菜就爱学一名刚刚入行的小白
从事方向:计算机视觉 我菜就爱学,分享有误,欢迎大佬指出
本篇介绍:深度学习简单的入门之后,学习经典网络模型——AlexNet
论文题目: 嗯- ImageNet Classification with Deep Convolutional Neural Networks -嗯
个人理解: 这边论文虽然已经过时了,里面的很多技术也都改进了。但是作为以后所有高级模型的改进,新手还是可以看一下的。
主要讲作者们训练了一个大型的深度卷积神经网络,将ImageNet LSVRC-2010竞赛中的120万张高分辨率图像分类为1000个不同的类别。测试一下数据上,我们实现了37.5% 和17.0% 的前1和前5错误率,这比以前的最新技术要好得多。神经网络具有6000万的参数和650,000的神经元,由五个卷积层组成,其中一些是max池层,以及三个具有最终1000 softmax的全连接层。为了使训练更快,我们使用了非饱和神经元和卷积操作的非常有效的GPU实现。为了减少全连接层中的过拟合,我们采用了最近开发的称为 “dropout” 的正则化方法,该方法被证明非常有效。
Top-1:预测的label中,概率向量最大的作为预测的结果,分类结果正确则正确,错误则错误
Top-5: 预测的label中,概率向量最大的前5个最为预测结果只有五个全部预测错误,则分类错误
ImageNet是属于大致22,000个类别的超过1500万个标记的高分辨率图像的数据集。大致有120万训练图像、50,000验证图像和150,000测试图像。因为之前跑过一个最近发表的论文代码,他的数据集是自己打标签的。但是作为AlexNet的标签则是以文件名命名,然后在文件里面存放大量的这种类别的图片。我自己训练的时候图片比较少,然后最后测试效果也不咋滴。
一个B站Up主对于数据集的理解:训练集可以看成“小测” 。 验证集可以看成:“模拟考” 。测试集可以看成:‘高考”
import torch
from torch import nn
class MyAlexNet(nn.Module):
def __init__(self):
super(MyAlexNet, self).__init__()
self.model=nn.Sequential(
nn.Conv2d(3,48,11,stride=4,padding=2),
nn.ReLU(),
nn.MaxPool2d(2),
nn.Conv2d(48,128,5,stride=1,padding=2),
nn.ReLU(),
nn.Conv2d(128,192,3,stride=1,padding=1),
nn.ReLU(),
nn.MaxPool2d(2),
nn.Conv2d(192,192,3,stride=1,padding=1),
nn.ReLU(),
nn.Conv2d(192,128,3,stride=1,padding=1),
nn.ReLU(),
nn.MaxPool2d(2)
)
self.classfiler=nn.Sequential(
nn.Linear(128*6*6,2048),
nn.Dropout(p=0.5),
nn.Linear(2048,2048),
nn.Dropout(p=0.5),
nn.Linear(2048,1000),
nn.Dropout(p=0.5),
nn.Linear(1000,10)
)
def forward(self,x):
x=self.model(x)
x = torch.flatten(x, start_dim=1) #按照个数推平
x=self.classfiler(x)
return x
if __name__ == '__main__':
input=torch.ones([32,3,224,224])
aiy=MyAlexNet()
output=aiy(input)
print(output.shape)
import os
import torchvision
from matplotlib import pyplot as plt
from torchvision.datasets import ImageFolder
from torchvision import transforms
from torch import nn
from torch.utils.data import dataset, DataLoader
from MyModel import *
#画图中文的乱码解决问题
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
#数据集
train_root=r"data/train"
test_root=r"data/val"
#数据预处理
#1、归一化
normalize=transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5]) #三通道图像
train_transforms=transforms.Compose([
#将数据变换包装起来依次执行
transforms.Resize((224,224)),
transforms.RandomHorizontalFlip(),#随机垂直翻转,相对于以后的打乱
transforms.ToTensor(), #归一化到【0-1】
normalize, #标准化到【-1,1】
] )
test_transforms=transforms.Compose([
transforms.Resize((224,224)),
transforms.ToTensor(), #归一化到【0-1】
normalize, #标准化到【-1,1】
])
#默认数据集已经自觉按照要分配的类型分成了不同的文件夹,一种类型的文件夹下面只存放一种类型的图片
# train_data=ImageFolder('../data/train',transform=train_transforms)
train_data=torchvision.datasets.CIFAR10(root='./dataset',train=True,
transform=train_transforms,download=True)
# test_data=ImageFolder("../data/val",transform=test_transforms)
#测试
test_data=torchvision.datasets.CIFAR10(root='./dataset',train=False,
transform=test_transforms,download=True)
# print(test_data.classes) #根据分的文件夹的名字来确定的类别
train_dataloader=DataLoader(train_data,batch_size=32,shuffle=True)
test_dataloader=DataLoader(test_data,batch_size=32,shuffle=False)
device='cuda' if torch.cuda.is_available() else 'cpu'
#引入模型
model=MyAlexNet().to(device)
#创建损失函数
loss_fn=nn.CrossEntropyLoss().to(device)
#定义优化器
optimizer=torch.optim.SGD(model.parameters(),lr=0.001)
#params (iterable) – 待优化参数的iterable(w和b的迭代) 或者是定义了参数组的dict
# lr (float) – 学习率
# momentum (float, 可选) – 动量因子(默认:0)
#让学习率每10轮减半
# lr_scheduler=lr_scheduler.StepLR(optimizer,s)
#定义训练次数
total_train_step=0
#定义测试次数
total_test_step=0
#定义一个画图函数
def matplot_loss(train_loss,val_loss):
plt.plot(train_loss,label='train_loss')
plt.plot(val_loss,label='val_loss')
plt.legend(loc='best')
plt.xlabel('loss')
plt.ylabel('epoch')
plt.title("训练集和验证集的loss值对比图")
plt.show()
#定义一个画图函数
def matplot_acc(train_acc,val_acc):
plt.plot(train_acc,label='train_acc')
plt.plot(val_acc,label='val_acc')
plt.legend(loc='best')
plt.xlabel('acc')
plt.ylabel('epoch')
plt.title("训练集和验证集的acc值对比图")
plt.show()
#训练的次数
epoch=10
loss_train=[]
acc_train=[]
loss_val=[]
acc_val=[]
min_vcc=0.0
for i in range(epoch):
print("-----正在进行第{}轮训练------".format(i + 1))
model.train()
total_train_loss=0
total_train_acc=0
m=0.0
for data in train_dataloader:
images,targets=data
images=images.to(device)
targets=targets.to(device)
# print(images.shape)
output=model(images)
loss=loss_fn(output,targets)
total_train_loss=total_train_loss+loss.item()
accuracy = (output.argmax(1) == targets).sum() / output.shape[0] # 1代表横向,0代码代表纵向
total_train_acc=total_train_acc+accuracy.item()
optimizer.zero_grad()
loss.backward()
optimizer.step() #调整参数
total_train_step=total_train_step+1
if total_train_step % 100 ==0 :
print("训练次数:{},loss={}".format(total_test_step,loss))
m=m+1
#模型转化为验证模式
model.eval()
train_loss = total_train_loss / m
train_acc = total_train_acc / m
print("整体测试集上的loss:{}".format(train_loss))
print("整体测试集上的正确率:{}".format(train_acc))
loss_train.append(train_loss)
acc_train.append(train_acc)
total_test_loss=0
total_accuracy=0
'''
在使用pytorch时,并不是所有的操作都需要进行计算图的生成(计算过程的构建,以便梯度反向传播等操作)。
而对于tensor的计算操作,默认是要进行计算图的构建的,在这种情况下,可以使用 with torch.no_grad():,强制之后的内容不进行计算图构建。
'''
#每次运行完之后进行一次测试,类似于参数已经更新完毕,来测试一下
with torch.no_grad():
n=0.0
for data in test_dataloader:
images, targets = data
images = images.to(device)
targets = targets.to(device)
output = model(images)
loss=loss_fn(output,targets)
total_test_loss=total_test_loss+loss.item()
'''
1.item()取出张量具体位置的元素元素值
2.并且返回的是该位置元素值的高精度值
3.保持原元素类型不变;必须指定位置
'''
accuracy=(output.argmax(1)==targets).sum()/output.shape[0] #1代表横向,0代码代表纵向
total_accuracy=total_accuracy+accuracy.item()
n=n+1
val_loss=total_test_loss/n
val_acc=total_accuracy/n
print("整体测试集上的loss:{}".format(val_loss))
print("整体测试集上的正确率:{}".format(val_acc))
loss_val.append(val_loss)
acc_val.append(val_acc)
#保存最好的模型权重
if val_acc > min_vcc:
folder='save_model'
if not os.path.exists(folder):
os.mkdir('save_model')
min_vcc=val_acc
print("save best model,在第{}轮".format(i))
torch.save(model.state_dict(),'save_model/best_model.pth')
if i==epoch-1:
print("保存最后一轮权重:")
torch.save(model.state_dict(),'save_model/last_model.pth')
matplot_loss(loss_train,loss_val)
matplot_loss(acc_train,acc_val)
print("目前没有problem")
import torch
from PIL import Image
from torch import nn
from torchvision.transforms import transforms, ToPILImage
from torch.autograd import Variable
from MyAlexNet.MyModel import MyAlexNet
import os
import cv2
directory_name=r"F:/NetWork/AlexNet/data_test/"
def read_directory(directory_name):
for filename in os.listdir(directory_name): #os.listdir()方法用于返回指定文件夹包含的文件或文件夹的名字的列表
img = cv2.imread(directory_name + "/" + filename)
trans = transforms.Compose([transforms.ToTensor(),transforms.Resize((224, 224))])
classes = ["ants", "bees"] # 自己是几种,这里就改成自己种类的字符数组
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print("using {} device.".format(device))
model=MyAlexNet().to(device)
model.load_state_dict(torch.load("F:/NetWork/AlexNet/MyAlexNet/save_model/best_model.pth"))
model.eval()
for filename in os.listdir(directory_name): # os.listdir()方法用于返回指定文件夹包含的文件或文件夹的名字的列表
image = cv2.imread(directory_name + "/" + filename)
# image = Image.open(img)
# image = image.convert("RGB")
image = trans(image)
# show=ToPILImage()
# show(image).show()
image=Variable(torch.unsqueeze(image,dim=0).float()).to(device)
image=torch.tensor(image).to(device)
pred=model(image)
print(pred)
predicted=classes[torch.argmax(pred,dim=1)]
print("prdeicted:{}".format(predicted))