基于ResNet的猫十二分类

        在这次实战训练中,首先对下载的猫十二数据集进行预处理,使用了tensorflow构建resnet模型,在学习率调度上,使用了1周期调度,并且使用了动量优化和Nesterov加速梯度

 

1.导包

from tensorflow import keras
import tensorflow as tf
from keras.preprocessing import image
import random
from matplotlib import pyplot as plt
import cv2
from tqdm import tqdm
import numpy as np
import math

2.数据预处理

cat_12数据集包含3个部分,训练集cat_12_train,测试集cat_test,以及存储图片名称及标签的train_list.txt

(1)定义prepare_image函数从文件中分离路径和标签

def prepare_image(file_path):
    X_train = []
    y_train = []
 
    with open(file_path) as f:
        context = f.readlines()
    random.shuffle(context)
 
    for str in context:
        str = str.strip('\n').split('\t')
 
        X_train.append('./image/cat_12/' + str[0])
        y_train.append(str[1])
 
    return X_train, y_train

(2)定义preprocess_image函数进行图像的归一化

def preprocess_image(img):
    img = image.load_img(img, target_size=(224, 224))
    img = image.img_to_array(img)
    img = img / 255.0
    return img

(3)定义plot_image函数打印图像

def plot_image(images,classes):
    fig,axes = plt.subplots(4,3,figsize=(60,60),sharex=True)
    fig.subplots_adjust(hspace=0.3,wspace=0.3)
    for i,ax in enumerate(axes.flat):
        image = cv2.imread(images[i])
        image = cv2.resize(image,(224,224))
        ax.imshow(cv2.cvtColor(image,cv2.COLOR_BGR2RGB),cmap="hsv")
        ax.set_xlabel("Breed:{}".format(classes[i]))
        ax.xaxis.label.set_size(60)
        ax.set_yticks([])
    plt.show()

3.展示数据集

X_train, y_train = prepare_image('./image/cat_12/train_list.txt')
print(X_train)

x_array = np.array(X_train)
y_array = np.array(y_train)
y_unique = np.unique(y_array)
print(y_unique)
['0' '1' '10' '11' '2' '3' '4' '5' '6' '7' '8' '9']
imgs = []
classes = []
for i in y_unique:
    sort = x_array[y_array==i]
    idx = np.random.randint(len(sort)-1)
    imgs.append(sort[idx])
    classes.append(i)
print(imgs)    
plot_image(imgs,classes)

 

4.准备数据集

train_images = []
for i in tqdm(X_train):
    train_image = preprocess_image(i)
    train_images.append(train_image)
train_images = np.array(train_images)
y_train = keras.utils.to_categorical(y_train, 12)
print(train_images.shape)

5. 基于tensorflow构建ResNet

# 构建卷积块
def conv_2d(x,filters,kernel_size,strides,padding="same"):
    x = keras.layers.Conv2D(filters,kernel_size=kernel_size,strides=strides,padding=padding)(x)
    x = keras.layers.BatchNormalization()(x)
    x = keras.activations.relu(x)
    return x
# 构建残差块
def resual_block(inputs,filters,strides):
    x = inputs
    x = conv_2d(x,filters=filters,kernel_size=1,strides=strides)
    x = conv_2d(x,filters=filters,kernel_size=3,strides=1)
    x = conv_2d(x,filters=4*filters,kernel_size=1,strides=1)
    
    x_short = conv_2d(inputs,filters=4*filters,kernel_size=1,strides=strides)
    
    x = keras.layers.Add()([x,x_short])
    x = keras.activations.relu(x)
    return x
# 构建resnet_152
def resnet(input_shape,n_classes=1000):
    x_input = keras.layers.Input(shape=input_shape)
    x = conv_2d(x_input,filters=64,kernel_size=7,strides=2)
    x = keras.layers.MaxPooling2D(pool_size=(3,3),strides=2,padding="same")(x)
    # input 64*3
    x = resual_block(x,64,strides=1)
    x = resual_block(x,64,strides=1)
    x = resual_block(x,64,strides=1)
    # input 128*8
    x = resual_block(x,128,strides=2)
    for i in range(7):
        x = resual_block(x,128,strides=1)
    # input 256*36
    x = resual_block(x,256,strides=2)
    for i in range(35):
        x = resual_block(x,256,strides=1)
    # input 512*3
    x = resual_block(x,512,strides=2)
    for i in range(2):
        x = resual_block(x,512,strides=1)
    
    # 全局平均池化
    x = keras.layers.GlobalAveragePooling2D()(x)
    output = keras.layers.Dense(n_classes,activation="softmax")(x)
    model = keras.models.Model(inputs=[x_input],outputs=[output])
    return model
model = resnet([224,224,3],12)

6.1周期调度

k = keras.backend
class One_Cycle(keras.callbacks.Callback):
    def __init__(self,interations,max_rate,min_rate=None,start_rate=None,last_interations=None):
        self.interations = interations
        self.max_rate = max_rate
        self.min_rate = min_rate or self.max_rate/10000
        self.start_rate = start_rate or self.max_rate/100
        self.last_interations = last_interations or self.interations//10+1
        self.half_interations = (self.interations - self.last_interations)//2
        self.interation = 0
        self.loss = []
        self.learning_rate = []
        self.numbers = []
        
    def _interpolate(self,iter1,iter2,rate1,rate2):
        return ((rate2-rate1)*(self.interation-iter1)/(iter2-iter1)+rate1)
    
    def on_batch_begin(self,batch,logs=None):
        if self.interation < self.half_interations:
            rate = self._interpolate(0,self.half_interations,self.start_rate,self.max_rate)
        elif self.interation < 2*self.half_interations:
            rate = self._interpolate(self.half_interations,2*self.half_interations,self.max_rate,self.start_rate)
        else:
            rate = self._interpolate(2*self.half_interations,self.interations,self.max_rate,self.min_rate)
        self.interation += 1
        k.set_value(self.model.optimizer.learning_rate,rate)
        
    def on_batch_end(self,batch,logs=None):
        self.learning_rate.append(k.get_value(self.model.optimizer.learning_rate))
        self.loss.append(logs["loss"])
        self.numbers.append(self.interation)

7.训练模型

n_epochs = 100
one_cycle = One_Cycle(math.ceil(len(X_train)//16)*n_epochs,0.1,min_rate=1e-5)
optimizer = keras.optimizers.SGD(learning_rate=0.001,momentum=0.9,nesterov=True)
model.compile(loss="categorical_crossentropy",optimizer=optimizer,metrics=["accuracy"])
history = model.fit(train_images,y_train,epochs=n_epochs,validation_split=0.2,batch_size=16,callbacks=[one_cycle])

8.绘制损失变化情况

def show_training_history(train_history, train, val):
    plt.plot(train_history[train], linestyle='-', color='b')
    plt.plot(train_history[val], linestyle='--', color='r')
    plt.xlabel('Epoch', fontsize=12)
    plt.ylabel('train', fontsize=12)
    plt.legend(['train', 'validation'], loc='lower right')
    plt.show()

  • 0
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是一个基于ResNet18实现狗分类的程序,使用PyTorch框架: ```python import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms # 定义数据预处理 transform_train = transforms.Compose([ transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) transform_test = transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) # 加载数据集 trainset = torchvision.datasets.ImageFolder(root='./train', transform=transform_train) trainloader = torch.utils.data.DataLoader(trainset, batch_size=32, shuffle=True, num_workers=2) testset = torchvision.datasets.ImageFolder(root='./test', transform=transform_test) testloader = torch.utils.data.DataLoader(testset, batch_size=32, shuffle=False, num_workers=2) # 定义ResNet18模型 class ResNet18(nn.Module): def __init__(self, num_classes=2): super(ResNet18, self).__init__() self.resnet = torchvision.models.resnet18(pretrained=True) self.resnet.fc = nn.Linear(in_features=512, out_features=num_classes, bias=True) def forward(self, x): x = self.resnet(x) return x # 定义模型、损失函数、优化器 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") net = ResNet18().to(device) criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) # 训练模型 for epoch in range(10): running_loss = 0.0 for i, data in enumerate(trainloader, 0): inputs, labels = data inputs, labels = inputs.to(device), labels.to(device) optimizer.zero_grad() outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() if i % 100 == 99: print('[%d, %5d] loss: %.3f' % (epoch+1, i+1, running_loss/100)) running_loss = 0.0 print('Finished Training') # 测试模型 correct = 0 total = 0 with torch.no_grad(): for data in testloader: images, labels = data images, labels = images.to(device), labels.to(device) outputs = net(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Accuracy of the network on the test images: %d %%' % (100 * correct / total)) ``` 请注意,此程序假定您已经下载了狗数据集并将其分别放在train和test文件夹中。另外,此程序使用预训练的ResNet18模型,因此需要下载预训练权重。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

樱花的浪漫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值