使用keras实现猫狗数据集分类

1.数据集获取

获取猫狗数据集kaggle提取码:kfhw
数据集中有train.zip和test.zip两个压缩包,但是对test.zip中图片文件的名称中没有cat和dog进行区分,没法分类,所以只用到了train.zip一个文件,对train.zip进行解压,一共有25000张图片,图片名中指明了cat or dog

2.对图片进行预处理

#data_preprocess.py
import cv2
import os
import numpy as np

import random
import time

import pickle

data_dir = './data'  # 解压后数据

start_time = time.time()

print("正在制作数据....")

# 图片统一大小100*100
# 训练集 20000张
# 测试集 剩下的所有,在训练集中进行切分,因为测试集没有标签

all_data_files = os.listdir(os.path.join(data_dir, "train/"))

random.shuffle(all_data_files)  # 打乱文件顺序

all_train_files = all_data_files[:20000]  # 前20000个图片用来训练
all_test_files = all_data_files[20000:]  # 后5000个图片用来测试

train_images = []  # 存储图片对应的narry数组的
train_labels = []  # 存储图片对应标签
train_files = []  # 存储对应图片名

test_images = []
test_labels = []
test_files = []

for each in all_train_files:
    img = cv2.imread(os.path.join(data_dir, "train", each), 1)
    # print(img.shape)  # 每张图片的大小不一致,需要转换成统一大小
    resized_img = cv2.resize(img, (100, 100))

    img_data = np.array(resized_img)  # 统一转换成narray数组类型,因为tensorflow支持narray
    train_images.append(img_data)
    if 'cat' in each:
        train_labels.append(0)  # 0表示猫
    elif 'dog' in each:
        train_labels.append(1)  # 1表示狗
    else:
        raise Exception("\n%s is a wrong train file" % (each))
    train_files.append(each)

for each in all_test_files:
    img = cv2.imread(os.path.join(data_dir, "train", each), 1)
    # print(img.shape)  # 每张图片的大小不一致,需要转换成统一大小
    resized_img = cv2.resize(img, (100, 100))

    img_data = np.array(resized_img)  # 统一转换成narray数组类型,因为tensorflow支持narray
    test_images.append(img_data)
    if 'cat' in each:
        test_labels.append(0)  # 0表示猫
    elif 'dog' in each:
        test_labels.append(1)  # 1表示狗
    else:
        raise Exception("\n%s is a wrong test file" % (each))
    test_files.append(each)

# print(len(train_images), len(test_images))

train_data = {
    'images': train_images,
    'labels': train_labels,
    'files': train_files
}

test_data = {
    'images': test_images,
    'labels': test_labels,
    'files': test_files
}

with open(os.path.join(data_dir,"train-data"),'wb') as f:
    pickle.dump(train_data,f)

with open(os.path.join(data_dir,'test-data'),'wb') as f:
    pickle.dump(test_data,f)

end_time = time.time()

print('制作结束,用时{}秒.'.format(end_time-start_time))

预处理完成以后在data文件夹下面会多出两个文件train-data和test-data
预处理的代码参考自

image.png

3.训练

#train.py
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, Dropout, Convolution2D, MaxPool2D, Flatten
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.utils import to_categorical
import pickle
import numpy as np


def load_data(filename):
    with open(filename, 'rb') as f:
        data = pickle.load(f, encoding='utf-8')
    return np.array(data['images']), to_categorical(np.array(data['labels']), num_classes=2), np.array(data['files'])


TRAIN_DIR = "data/train-data"

train_images, train_labels, train_files = load_data(TRAIN_DIR)

model = Sequential([
    Convolution2D(16, kernel_size=(3, 3), strides=(1, 1), padding="same", input_shape=(100, 100, 3), activation='relu'),
    # 100*100*96
    MaxPool2D((2, 2), strides=(2, 2), padding='same'),  # 50*50*96
    Convolution2D(32, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu'),  # 50*50*192
    MaxPool2D((2, 2), strides=(2, 2), padding='same'),  # 25*25*192
    Convolution2D(64, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu'),  # 25*25*384
    MaxPool2D((2, 2), strides=(2, 2), padding='same'),  #
    Convolution2D(128, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu'),
    MaxPool2D((2, 2), strides=(2, 2), padding='same'),
    Flatten(),
    Dense(512, activation='relu'),
    Dropout(0.3),
    Dense(256, activation='relu'),
    Dropout(0.3),
    Dense(2)
])
# 模型编译
model.compile(optimizer=Adam(), loss='categorical_crossentropy', metrics=['accuracy'])
# 模型训练
model.fit(train_images, train_labels, batch_size=200, epochs=10)

model.save("cat_and_dog.h5") # hdf5文件 pip intall h5py

训练完成以后将训练的模型进行保存

4.对训练好的模型可以进行更多的训练

#more_train.py
from tensorflow.keras.models import load_model
from tensorflow.keras.utils import to_categorical
import pickle
import numpy as np


def load_data(filename):
    with open(filename, 'rb') as f:
        data = pickle.load(f, encoding='utf-8')
    return np.array(data['images']), to_categorical(np.array(data['labels']), num_classes=2), np.array(data['files'])

TRAIN_DIR = "data/train-data"

train_images, train_labels, train_files = load_data(TRAIN_DIR)

model = load_model("cat_and_dog.h5") # 同时加载结构和参数

# 模型训练
model.fit(train_images, train_labels, batch_size=200, epochs=10)
model.save("cat_and_dog.h5") # hdf5文件 pip intall h5py

更多的训练是基于之前已经训练过的模型

5.模型训练好以后可以进行测试

#test.py
from tensorflow.keras.models import load_model
from tensorflow.keras.utils import to_categorical
import pickle
import numpy as np


def load_data(filename):
    with open(filename, 'rb') as f:
        data = pickle.load(f, encoding='utf-8')
    return np.array(data['images']), to_categorical(np.array(data['labels']), num_classes=2), np.array(data['files'])

TEST_DIR = "data/test-data"              

test_image, test_labels, test_files = load_data(TEST_DIR)

model = load_model("cat_and_dog.h5") # 同时加载结构和参数

# 模型评估

loss, accuracy = model.evaluate(test_image, test_labels)
print("test loss", loss)
print("test accuracy", accuracy)

6.工程的目录结构

image.png

其中被框住的文件是有用的文件,绿色的被框住的是预处理后生成的文件

7结果

经过train.py训练以后
image.png

是用测试集评估结果
image.png
image.png

这是我在训练一遍之后的准确度,其实经过多次训练还有一定的上升空间

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容