用Keras实现的VGG-16网络结构的图像分类(开箱即用,包含制作自己的数据集,最后有训练出来的现成模型,大家可以先睹为快)

1、前言

前段时间一直在研究Tensorflow,但是一直都没有出成果,学了大概两个多月,还是用不起来,真不知道是它太难了,还是自己太渣了,不过我感觉后者的可能性比较大。
后来发现了Keras框架,正好他就是基于Tensorflow的后端做的更高级的API,使用起来真的是比看小电影都爽。墙裂推荐入门Keras。
多的不说了,分享一下我最近的成果吧。
补一下实验环境:
1、英伟达显卡,960M
2、Anaconda下配置的Keras,使用jupyter notebook

所有需要加载的库在这里:

from keras.models import Sequential
from keras.models import load_model
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.layers.core import Activation, Flatten, Dense, Dropout
from keras import backend as K
from keras.utils import np_utils
from keras.optimizers import SGD, RMSprop, Adam
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
import seaborn as sns
from keras.preprocessing import image
import keras
from keras.preprocessing.image import ImageDataGenerator
from keras.utils import np_utils
from sklearn.model_selection import train_test_split
from keras.callbacks import TensorBoard
from keras.callbacks import ModelCheckpoint
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
import random, os, pickle

2、图片的下载与数据集的制作

相信很多人跟我一样,一开始有可能连自己的数据集都不会做,导致只能加载Keras自带的那几个数据集,玩两次发现不爽,训练别人的数据集多没意思啊,一定要搞一个自己的数据集出来才有意思,下面我就把我从网上爬的照片分享给大家(希望看到的大佬能给出一些意见,第一次弄数据集,感觉自己做的数据集不太好)。每个分类里面大概有3500张图片,一共分为4个类别——书、女人、手机、狗。
由于我的图片是在数据集制作的过程中才做的处理,所以图片集会很大,有2G左右。(所有图片仅限于学习交流,严禁用于商业,如有侵权,请联系我删除
链接如下:图片链接,提取码:0ppw。

制作成可用的数据集

"图片-标签数据"
def read_and_process_image(data_dir,width=32, height=32, channels=3, preprocess=False):
    train_classes= [data_dir + "/" +  i for i in os.listdir(data_dir) ]
    train_images = []
    for train_class in train_classes:
        train_images= train_images + [train_class + "/" + i for i in os.listdir(train_class)]
    random.shuffle(train_images)
#     print(train_images[0:10])

    def read_image(file_path, preprocess):
        img = image.load_img(file_path, target_size=(height, width))
        x = image.img_to_array(img)
        x = np.expand_dims(x, axis=0)
        # if preprocess:
            # x = preprocess_input(x)
        return x
    
    def prep_data(images, proprocess):
        count = len(images)
        data = np.ndarray((count, height, width, channels), dtype = np.float32)
        print(data.shape)
        for i, image_file in enumerate(images):
            image = read_image(image_file, preprocess)
            data[i] = image
        return data
    
    def read_labels(file_path):
        labels = []
        for i in file_path:
            if '狗' in i:
                label = 0
            elif '女人' in i:
                label = 1
            elif '手机' in i:
                label = 2
            elif '书' in i:
                label = 3
            labels.append(label)
        
        return labels
    
    X = prep_data(train_images, preprocess)
    labels = read_labels(train_images)
    
    assert X.shape[0] == len(labels)
    
    print("Train shape: {}".format(X.shape))
    print("Train shape: {}".format(len(labels)))
    return X, labels

x,y = read_and_process_image("E:\Keras\图像分类\第一次训练")   #注意这里传的是绝对路径

"制作训练集和测试集"
x_train , x_test, y_train, y_test = train_test_split(x,y,test_size=0.2,random_state=100)

y_train = keras.utils.to_categorical(y_train, 4)    #制作独热编码,后面的数字是分类的数目
y_test = keras.utils.to_categorical(y_test, 4)

上面的代码已经把数据集制作完成了,不过直接用来训练的话,可能会导致资源耗尽,建议大家把上面的数据加载到pkl格式的文件中。

#把数据集写入pkl文件
output = open("数据集.pkl", "wb")
pickle.dump({"x_train":x_train, "y_train":y_train, "x_test":x_test, "y_test":y_test}, output)
output.close()

#读取数据集
with open("数据集.pkl", 'rb') as fo:
    data = pickle.load(fo, encoding='bytes')
    
# print(data["x_train"].shape)
print(data["y_train"])

这里的制作过程是参考网上的一个大佬的,由于时间比较久,找不到大佬的链接了,看到的大佬可以联系我,加上您的链接。

3、确定网络模型

这里选用的是没有加BN操作的VGG-16模型,你们可以在我的基础上添加上BN操作,就是在每个卷积层后面紧接一个BN,Keras实现起来很简单,不过我懒得弄了。

"序贯模型的VGG-16的Kers模型"
class VGG_16:
    @staticmethod
    def build(input_shape, classes):
        model = Sequential()
        # block 1
        model.add(Conv2D(64, kernel_size=3, padding="same", activation="relu", input_shape=input_shape))
        model.add(Conv2D(64, kernel_size=3, padding="same", activation="relu"))
        model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2)))
        # block 2
        model.add(Conv2D(128, kernel_size=3, padding="same", activation="relu"))
        model.add(Conv2D(128, kernel_size=3, padding="same", activation="relu"))
        model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2)))
        # block 3
        model.add(Conv2D(256, kernel_size=3, padding="same", activation="relu"))
        model.add(Conv2D(256, kernel_size=3, padding="same", activation="relu"))
        model.add(Conv2D(256, kernel_size=3, padding="same", activation="relu"))  
        model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2)))
        # block 4
        model.add(Conv2D(512, kernel_size=3, padding="same", activation="relu"))
        model.add(Conv2D(512, kernel_size=3, padding="same", activation="relu"))
        model.add(Conv2D(512, kernel_size=3, padding="same", activation="relu"))  
        model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2)))
        #block 5
        model.add(Conv2D(512, kernel_size=3, padding="same", activation="relu"))
        model.add(Conv2D(512, kernel_size=3, padding="same", activation="relu"))
        model.add(Conv2D(512, kernel_size=3, padding="same", activation="relu"))  
        model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2)))
        # FC
        model.add(Flatten())
        model.add(Dense(4096, activation="relu"))
        model.add(Dropout(0.5))
        model.add(Dense(4096, activation="relu"))
        model.add(Dropout(0.5))
        model.add(Dense(classes, activation="softmax"))
        return model

这里你们可以参考Keras自己实现的VGG-16模型,链接如下:VGG-16

4、设置超参数

x_train, y_train, x_test, y_test = data["x_train"], data["y_train"], data["x_test"], data["y_test"]
"参数设置"
epoches = 50
batch_size = 32
verbose = 1                          # 可视化
optimizer = keras.optimizers.rmsprop(lr=0.0001, decay=1e-6)   # 优化器
validation_split = 0.2               #训练集中用于验证的比例
img_rows, img_cols = 32, 32    
num_classes = 4                      # 分类的类别
input_shape = (img_rows, img_cols, 3)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255

tensorboard = TensorBoard(log_dir='tensorboard', histogram_freq=1,)  #设置Tensorboard

filepath ="weights.{epoch:02d}-{val_loss:.2f}.hdf5"
checkpoint = ModelCheckpoint(filepath,
							 monitor='val_loss', 
							 verbose=1, 
							 save_best_only=False, 
							 save_weights_only=False, 
							 mode='auto', period=1)  #保存每一个epoch的模型
callbacks = [tensorboard, checkpoint]

5、开始训练

"初始化优化器和模型"
model = VGG_16.build(input_shape=input_shape, classes=num_classes)
model.compile(loss="categorical_crossentropy", optimizer=optimizer, metrics=["accuracy"])
model.summary()
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epoches, verbose=verbose, 
                    validation_split=0.2, callbacks=callbacks)  # 这里的nb_epoch参数容易出问题,要小心
score = model.evaluate(x_test, y_test, verbose=verbose)
print("Test score:", score[0])
print("Test accuracy:", score[1])

6、加载自己训练出来的模型,预测图片分类

我这里有一个训练好的模型,大家可以试一下先,
链接:weights.29-0.84.hdf5

model = load_model("weights.29-0.84.hdf5")  #加载模型

img = image.load_img("12.jpg", target_size=(32, 32))  #预测自己的图片
img = image.img_to_array(img)
img = np.expand_dims(img, axis=0)
img = img.astype('float32')
img /= 255
result = model.predict_classes(img)
proba = model.predict_proba(img)
# result = model.predict(img)
if np.array_equal(result, [0]):
    print("狗")
elif np.array_equal(result, [1]):
    print("女人")
elif np.array_equal(result, [2]):
    print("手机")
else:
    print("书")
print(result)
proba = np.max(proba[0])
print(proba)


文中有什么不对的地方,还望各位不吝赐教,大家共同学习进步。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值