利用resnet 做kaggle猫狗大战图像识别,秒上98准确率

本文介绍了使用Keras框架进行猫狗图像分类的具体实践过程。包括构建卷积神经网络(CNN)、应用数据增强技术以减少过拟合现象,并利用预训练模型ResNet50等进行特征提取,最终融合多种模型预测结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、数据介绍

这份数据集来源于Kaggle,数据集有12500只猫和12500只狗。在这里简单介绍下整体思路
1、1从图片中直接训练一个小网络(作为基准方法),也就是普通的cnn方法
2、2后面我会用到最新的预训练好的resnet等方法进行训练

2 数据提升与cnn

为了尽量利用我们有限的训练数据,我们将通过一系列随机变换堆数据进行提升,这样我们的模型将看不到任何两张完全相同的图片,这有利于我们抑制过拟合,使得模型的泛化能力更好。
在Keras中,这个步骤可以通过keras.preprocessing.image.ImageGenerator来实现,这个类使你可以:
在训练过程中,设置要施行的随机变换
通过.flow或.flow_from_directory(directory)方法实例化一个针对图像batch的生成器,这些生成器可以被用作keras模型相关方法的输入,如fit_generator,evaluate_generator和predict_generator
2、1 代码与解释

import os  # 处理字符串路径
import glob  # 查找文件
from keras.models import Sequential  # 导入Sequential模型
from keras.layers.core import Flatten, Dense, Dropout
from keras.layers.convolutional import Convolution2D, MaxPooling2D, ZeroPadding2D
from keras.optimizers import SGD
import numpy as np
from pandas import Series, DataFrame
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.advanced_activations import PReLU
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras.optimizers import SGD, Adadelta, Adagrad
from keras.utils import np_utils, generic_utils
from six.moves import range
#加载数据
model = Sequential()
#第一个卷积层,4个卷积核,每个卷积核大小5*5。1表示输入的图片的通道,灰度图为1通道。
#激活函数用relu
#你还可以在model.add(Activation('relu'))后加上dropout的技巧,防止过拟合
model.add(Dropout(0.5))
model.add(Convolution2D(4, 5, 5,input_shape=(224, 224,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
#第二个卷积层,8个卷积核,每个卷积核大小3*3。4表示输入的特征图个数,等于上一层的卷积核个数
#激活函数用relu
#采用maxpooling,poolsize为(2,2)
model.add(Convolution2D(8, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
#第三个卷积层,16个卷积核,每个卷积核大小3*3
#激活函数用relu
#采用maxpooling,poolsize为(2,2)
model.add(Convolution2D(16, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
#全连接层,先将前一层输出的二维特征图flatten为一维的。
#全连接有128个神经元节点,初始化方式为normal
model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.5))
#sigmoid分类,输出是2类别
model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

train_datagen = ImageDataGenerator(
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)

# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1./255)

# this is a generator that will read pictures found in
# subfolers of 'data/train', and indefinitely generate
# batches of augmented image data
train_generator = train_datagen.flow_from_directory(
        'd:/train2',  # this is the target directory
        target_size=(224, 224),  # all images will be resized to 150x150
        batch_size=32,
        class_mode='binary')  # since we use binary_crossentropy loss, we need binary labels

# this is a similar generator, for validation data
validation_generator = test_datagen.flow_from_directory(
        'd:/validation',
        target_size=(224, 224),
        batch_size=32,
        class_mode='binary')
model.fit_generator(
        train_generator,
        samples_per_epoch=2000,
        nb_epoch=50,
        validation_data=validation_generator,
        nb_val_samples=800)

from keras.utils import plot_model
plot_model(model, to_file='d:/model.png')

3、resnet及其他方法融合

从知乎看到的一种方法,在这里介绍给大家,通过已训练好的imagenet权重对我们的数据进行特征提取,然后再用提取的特征做一个简单的全连接。代码如下:

from keras.models import *
from keras.layers import *
from keras.applications import *
from keras.preprocessing.image import *

import h5py

def write_gap(MODEL, image_size, lambda_func=None):
    width = image_size[0]
    height = image_size[1]
    input_tensor = Input((height, width, 3))
    x = input_tensor
    if lambda_func:
        x = Lambda(lambda_func)(x)

    base_model = MODEL(input_tensor=x, weights='imagenet', include_top=False)
    model = Model(base_model.input, GlobalAveragePooling2D()(base_model.output))

    gen = ImageDataGenerator()
    train_generator = gen.flow_from_directory("d:/train2", image_size, shuffle=False,
                                              batch_size=16)
    test_generator = gen.flow_from_directory("d:/test2", image_size, shuffle=False,
                                             batch_size=16, class_mode=None)

    train = model.predict_generator(train_generator, train_generator.nb_sample)
    test = model.predict_generator(test_generator, test_generator.nb_sample)
    with h5py.File("d:/mymodel/gap_%s.h5"%MODEL.func_name) as h:
        h.create_dataset("train", data=train)
        h.create_dataset("test", data=test)
        h.create_dataset("label", data=train_generator.classes)

write_gap(ResNet50, (224, 224))
write_gap(InceptionV3, (299, 299), inception_v3.preprocess_input)
write_gap(Xception, (299, 299), xception.preprocess_input)



import h5py
import numpy as np
from sklearn.utils import shuffle
np.random.seed(2017)

X_train = []
X_test = []

for filename in ["gap_ResNet50.h5", "gap_Xception.h5", "gap_InceptionV3.h5"]:
    with h5py.File(filename, 'r') as h:
        X_train.append(np.array(h['train']))
        X_test.append(np.array(h['test']))
        y_train = np.array(h['label'])

X_train = np.concatenate(X_train, axis=1)
X_test = np.concatenate(X_test, axis=1)

X_train, y_train = shuffle(X_train, y_train)





from keras.models import *
from keras.layers import *

np.random.seed(2017)

input_tensor = Input(X_train.shape[1:])
x = Dropout(0.5)(input_tensor)
x = Dense(1, activation='sigmoid')(x)
model = Model(input_tensor, x)

model.compile(optimizer='adadelta',
              loss='binary_crossentropy',
              metrics=['accuracy'])



model.fit(X_train, y_train, batch_size=128, nb_epoch=8, validation_split=0.2)

y_pred = model.predict(X_test, verbose=1)
y_pred = y_pred.clip(min=0.005, max=0.995)

import pandas as pd
from keras.preprocessing.image import *

df = pd.read_csv("sample_submission.csv")

gen = ImageDataGenerator()
test_generator = gen.flow_from_directory("test2", (224, 224), shuffle=False,
                                         batch_size=16, class_mode=None)

for i, fname in enumerate(test_generator.filenames):
    index = int(fname[fname.rfind('/')+1:fname.rfind('.')])
    df.set_value(index-1, 'label', y_pred[i])

df.to_csv('pred.csv', index=None)
df.head(10)

4、参考文献

https://zhuanlan.zhihu.com/p/25978105?utm_source=weibo
https://zhuanlan.zhihu.com/p/25978105?utm_source=weibo

基于PyTorch的ResNet是一个深度卷积神经网络模型,用于图像分类任务,可以用于猫狗识别ResNet是由微软研究院提出的,其主要特点是通过残差连接解决了深度网络训练中的梯度消失和梯度爆炸问题。 ResNet的结构非常深,通常有几十层甚至上百层。它的核心思想是引入了残差块(Residual Block),每个残差块包含了两个或三个卷积层,其中包括了跳跃连接(skip connection)。跳跃连接将输入直接添加到输出中,使得网络可以学习到残差,从而更好地优化模型。 在PyTorch中,可以使用torchvision库中的预训练模型来实现ResNet猫狗识别。首先,需要导入torchvision和torch库: ```python import torch import torchvision.models as models ``` 然后,可以使用`models.resnet50()`来加载预训练的ResNet-50模型: ```python model = models.resnet50(pretrained=True) ``` 接下来,需要对模型进行微调,将最后一层全连接层替换为适合猫狗分类的新的全连接层: ```python num_classes = 2 # 猫狗分类任务,共2个类别 num_features = model.fc.in_features model.fc = torch.nn.Linear(num_features, num_classes) ``` 最后,可以使用该模型进行猫狗识别。首先,需要将图像进行预处理,然后将其输入到模型中进行推理: ```python from PIL import Image import torchvision.transforms as transforms # 加载图像并进行预处理 image = Image.open('cat.jpg') preprocess = transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ]) input_tensor = preprocess(image) input_batch = input_tensor.unsqueeze(0) # 将输入传入模型进行推理 model.eval() with torch.no_grad(): output = model(input_batch) # 获取预测结果 _, predicted_idx = torch.max(output, 1) ``` 以上就是基于PyTorch的ResNet猫狗识别的简要介绍。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值