2000年初期最主要的机器学习算法是核方法。其核心是特征提取、选择和函数来计算相关性、凸优化问题(凸优化问题指的是在定义域内具有全局最优解的问题)、漂亮的定理。
ImageNet(2010)
AlexNet
正是因为ImageNet变大,才使得AlexNet神经网络可以更深更大。
?上图右边两张部分分别是深度学习神经网络前后对图片的处理。在深度学习神经网络之后的优点是CNN更易学习,不必了解过多计算机视觉的知识;CNN与softmax一起训练,效率更高。
?
?
?
?
?VGG
?
?
?
VGG16是13层卷积层+3层全连接层
?
?VGG使用可重复的卷积块来构建深度卷积神经网络。
不同的卷积块个数和超参数可以得到不同复杂度的变种。
NiN
?
?
1X1卷积唯一就是可以进行通道数的改变。
?
使用全局平均池化,即当输入通道数是类别数时,全局平均池化后相当于每个通道取出一个平均值作为结果。
?
?
?GoogLeNet
?
?
由图中可以看到最后输出高宽比不变。
?
?由图中看到只有通道数的改变,白色框进行通道数改变,深蓝框进行通道信息或空间信息提取。
?
?
?
?
?
?
?批量归一化
?
?
?
?批量归一化固定小批量中的均值和方差,然后学习出合适的偏移和缩放。
可以加速收敛速度,但一般不改变模型精度。
ResNet
增加神经网络深度即增加层数总是可以改进精度吗
?如上图,蓝色星星是最优模型,下方大小表示模型复杂度,左边随着模型复杂度增加,离最优解距离并没有逐渐减小,只有像右边,大模型始终包含小模型,才会不至于模型越大反而不如之前模型效果。
?以函数来举例,最差f(x)结果是g(x)没有学习到东西。
?
?
?
宽高减半即在第一个ResNet块中一个卷积层将宽高减半。
?
?也是5部分。
?代码:
import numpy as np
import matplotlib.pyplot as plt
import os
import torch
import torch.nn as nn
import torchvision
from torchvision import models,transforms,datasets
import csv
import cv2
from torch.autograd import Variable
from PIL import Image
# 判断是否存在GPU设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print('Using gpu: %s ' % torch.cuda.is_available())
#数据处理
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
data_transform = transforms.Compose([
transforms.CenterCrop(224),
transforms.ToTensor(),
normalize,
])
'''加载数据'''
!wget https://static.leiphone.com/cat_dog.rar
!unrar x cat_dog.rar
'''数据集路径'''
train_path='./cat_dog/train/'
val_path='./cat_dog/val/'
test_path='./cat_dog/test/'
此处数据处理使用的齐昊同学的代码?!!!
'''装载数据'''
def get_data(file_path):
file_lst = os.listdir(file_path) #获得所有文件名称 xxxx.jpg
data_lst = []
for i in range(len(file_lst)):
clas = file_lst[i][:3] #cat和dog在文件名的开头
img_path = os.path.join(file_path,file_lst[i])#将文件名与路径合并得到完整路径,以备读取
if clas == 'cat':
data_lst.append((img_path, 0))
else:
data_lst.append((img_path, 1))
return data_lst
class catdog_set(torch.utils.data.Dataset):
def __init__(self, path, transform):
super(catdog_set).__init__()
self.data_lst = get_data(path)#调用刚才的函数获得数据列表
self.trans = transform
def __len__(self):
return len(self.data_lst)
def __getitem__(self,index):
(img,cls) = self.data_lst[index]
image = self.trans(Image.open(img))
label = torch.tensor(cls,dtype=torch.float32)
return image,label
# 将输入图像缩放为 128*128,每一个 batch 中图像数量为128
# 训练时,每一个 epoch 随机打乱图像的顺序,以实现样本多样化
train_loader = torch.utils.data.DataLoader(
catdog_set(train_path,data_transform),batch_size=128, shuffle=True)
val_loader=torch.utils.data.DataLoader(
catdog_set(val_path,data_transform),batch_size=5,shuffle=False)
#创建ResNet Model
#使用ResNet-50的预训练模型。
resnet50 = models.resnet50(pretrained=True)
#resnet50=resnet50.to(device)
#修改最后一层,冻结前面层的参数。
# 修改模型的全连接层使其输出为你需要类型数,这里是2
# 由于使用了预训练的模型 而预训练的模型输出为1000类,所以要修改全连接层
for param in resnet50.parameters():
param.requires_grad = False
fc_inputs = resnet50.fc.in_features
resnet50.fc = nn.Sequential(
nn.Linear(fc_inputs, 256),
nn.ReLU(),
nn.Dropout(0.4),
nn.Linear(256, 2),
nn.LogSoftmax(dim=1)
)
resnet50 = resnet50.to(device)
#训练并测试全连接层
'''
第一步:创建损失函数和优化器
损失函数 NLLLoss() 的 输入 是一个对数概率向量和一个目标标签.
它不会为我们计算对数概率,适合最后一层是log_softmax()的网络.
'''
criterion = nn.NLLLoss()
# 学习率
lr = 0.0001
#优化函数
optimizer = torch.optim.Adam(resnet50.parameters(),lr = lr)
'''
第二步:训练模型
'''
def train_model(model,dataloader,size,epochs=3,optimizer=None):
model.train()
for epoch in range(epochs):
running_loss = 0.0
running_corrects = 0
count = 0
for inputs,classes in dataloader:
inputs = inputs.to(device)
classes = classes.to(device)
outputs = model(inputs)
loss = criterion(outputs,classes.long())
optimizer = optimizer
optimizer.zero_grad()
loss.backward()
optimizer.step()
_,preds = torch.max(outputs.data,1)
# statistics
running_loss += loss.data.item()
running_corrects += torch.sum(preds == classes.data)
count += len(inputs)
print('Training: No. ', count, ' process ... total: ', size)
epoch_loss = running_loss / size
epoch_acc = running_corrects.data.item() / size
print('Loss: {:.4f} Acc: {:.4f}'.format(
epoch_loss, epoch_acc))
# 模型训练
train_model(resnet50,train_loader,size=catdog_set(
train_path,data_transform).__len__(),epochs=3, optimizer=optimizer)
?
def test_model(model,dataloader,size):
model.eval()
predictions = np.zeros(size)
all_classes = np.zeros(size)
all_proba = np.zeros((size,2))
i = 0
running_loss = 0.0
running_corrects = 0
for inputs,classes in dataloader:
inputs = inputs.to(device)
classes = classes.to(device)
outputs = model(inputs)
loss = criterion(outputs,classes.long()) #label不加long会报错
_,preds = torch.max(outputs.data,1)
# statistics
running_loss += loss.data.item()
running_corrects += torch.sum(preds == classes.data)
predictions[i:i+len(classes)] = preds.to('cpu').numpy()
all_classes[i:i+len(classes)] = classes.to('cpu').numpy()
all_proba[i:i+len(classes),:] = outputs.data.to('cpu').numpy()
i += len(classes)
print('Testing: No. ', i, ' process ... total: ', size)
epoch_loss = running_loss / size
epoch_acc = running_corrects.data.item() / size
print('Loss: {:.4f} Acc: {:.4f}'.format(
epoch_loss, epoch_acc))
test_model(resnet50,val_loader,size=catdog_set(val_path,data_transform).__len__())
?
'''写入csv文件'''
f=open('catdog.csv','w',encoding='utf-8', newline='')
csv_writer=csv.writer(f)
n=0
for i in range(2000):
img=cv2.imread(test_path+'/'+str(i)+'.jpg')
img = cv2.imread(test_path+'/'+str(file))
img=Image.fromarray(img)
newImg = data_transform(img) #想调整的大小
newImg=Variable(torch.unsqueeze(newImg, dim=0).float(), requires_grad=False)
newImg=newImg.to(device)
pred=resnet50(newImg)
predict=torch.max(pred,1)[1]
csv_writer.writerow([n,str(file),predict.item()])
n+=1
f.close()
'''下载csv文件'''
from google.colab import files
files.download('catdog.csv')
?
?
|