〇、内容说明
主体部分资料来源于:
1、【深度学习图像识别课程】毕业项目:狗狗种类识别(2)代码实现
3、Kaggle相关比赛:Dog Breed Identification
一、加载数据
from sklearn.datasets import load_files
from keras.utils import np_utils
import numpy as np
from glob import glob
import time
t0=time.time()
print('显示此刻的时间:',time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
# 定义函数来加载train,test和validation数据集
def load_dataset(path):
data = load_files(path)
dog_files = np.array(data['filenames'])
dog_targets = np_utils.to_categorical(np.array(data['target']), 133)
return dog_files, dog_targets
# 加载train,test和validation数据集
train_files, train_targets = load_dataset('E:/dog/dogImages/train')
valid_files, valid_targets = load_dataset('E:/dog/dogImages/valid')
test_files, test_targets = load_dataset('E:/dog/dogImages/test')
# 加载狗品种列表
dog_names = [item[20:-1] for item in sorted(glob("E:/dog/dogImages/train/*/"))]
# 打印数据统计描述
print('There are %d total dog categories.' % len(dog_names))
print('There are %s total dog images.\n' % len(np.hstack([train_files, valid_files, test_files])))
print('There are %d training dog images.' % len(train_files))
print('There are %d validation dog images.' % len(valid_files))
print('There are %d test dog images.'% len(test_files))
t1=time.time()
print('显示结束的时间:',time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
print("用时:%.2fs"%(t1-t0))
二、处理数据
调整载入的图片数据格式,使其符合keras模型的输入的要求
from keras.preprocessing import image
from tqdm import tqdm
def path_to_tensor(img_path):
# 用PIL加载RGB图像为PIL.Image.Image类型
img = image.load_img(img_path, target_size=(224, 224))
# 将PIL.Image.Image类型转化为格式为(224, 224, 3)的3维张量
x = image.img_to_array(img)
# 将3维张量转化为格式为(1, 224, 224, 3)的4维张量并返回
return np.expand_dims(x, axis=0)
def paths_to_tensor(img_paths):
list_of_tensors = [path_to_tensor(img_path) for img_path in tqdm(img_paths)]
return np.vstack(list_of_tensors)
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
# Keras中的数据预处理过程
train_tensors = paths_to_tensor(train_files).astype('float32')/255
valid_tensors = paths_to_tensor(valid_files).astype('float32')/255
test_tensors = paths_to_tensor(test_files).astype('float32')/255
插个补充:Application应用-Keras中文文档(Resnet50)
这里处理数据的思路是类似的
from keras.applications.resnet50 import ResNet50
from keras.preprocessing import image
from keras.applications.resnet50 import preprocess_input, decode_predictions
import numpy as np
model = ResNet50(weights='imagenet',classes=12)
img_path = 'rubber.jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
a = np.expand_dims(x, axis=0)
b = preprocess_input(a)
preds = model.predict(b)
# 将结果解码为元组列表 (class, description, probability)
# (一个列表代表批次中的一个样本)
print('Predicted:', decode_predictions(preds, top=3)[0])
# Predicted: [(u'n02504013', u'Indian_elephant', 0.82658225), (u'n01871265'
三、Keras自建模型
from keras.layers import Conv2D, MaxPooling2D, GlobalAveragePooling2D
from keras.layers import Dropout, Flatten, Dense
from keras.models import Sequential
model = Sequential()
### TODO: 定义你的网络架构
model.add(Conv2D(filters=16, kernel_size=2, padding='valid', activation='relu', input_shape=(224,224,3)))
model.add(MaxPooling2D(pool_size=2))
model.add(Conv2D(filters=32, kernel_size=2, padding='valid', activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(Conv2D(filters=64, kernel_size=2, padding='valid', activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(GlobalAveragePooling2D(input_shape=(27,27,64)))
model.add(Dense(133, activation='softmax'))
model.summary()
这个模型的乍一看感觉很有Let-Net5的感觉,但确实也不是。
神经网络模型千变万化,稍微变化结果便会产生差异,玄之又玄。
补充一个经典Let-Net5模型:
from keras.models import Sequential, Model
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Flatten
from keras.layers import Dense,Input, Embedding, LSTM, Dropout
model = Sequential()
model.add(Conv2D(6, (5, 5), input_shape=(32, 32,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(16, (5, 5), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(120, activation='relu'))
model.add(Dense(84, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.summary()
四、编译训练模型
## 编译模型
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
from keras.callbacks import ModelCheckpoint
checkpointer = ModelCheckpoint(filepath='weights.best.from_scratch.hdf5',
verbose=1, save_best_only=True)
model.fit(train_tensors, train_targets,
validation_data=(valid_tensors, valid_targets),
epochs=20, batch_size=25, callbacks=[checkpointer], verbose=1)
过拟合:训练精度越来越高,验证数据精度不变
五、加载并测试
## 加载具有最好验证loss的模型
model.load_weights('saved_models/weights.best.from_scratch.hdf5')
# 获取测试数据集中每一个图像所预测的狗品种的index
dog_breed_predictions = [np.argmax(model.predict(np.expand_dims(tensor, axis=0))) for tensor in test_tensors]
# 报告测试准确率
test_accuracy = 100*np.sum(np.array(dog_breed_predictions)==np.argmax(test_targets, axis=1))/len(dog_breed_predictions)
print('Test accuracy: %.4f%%' % test_accuracy)
Test accuracy: 7.2967%
模型比较简陋,隐层也不多,20epoch,CPU训练时间将近一小时,结果还算可以!