使用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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352