基于Keras的卷积神经网络模型预测–狗的品种识别
from sklearn.datasets import load_files
from keras.utils import np_utils
import numpy as np
from glob import glob
import os
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from matplotlib import image
from keras.preprocessing import image as image1
from tqdm import tqdm
from PIL import ImageFile
from keras.callbacks import ModelCheckpoint
#定义加载数据集函数
def load_dataset(path):
data=load_files(path)
dog_files=np.array(data['filenames'])
raw_targets=np.array(data['target'])
dog_targets=np_utils.to_categorical(raw_targets,num_classes)
return dog_files,raw_targets,dog_targets
#加载数据集
def draw_random_9_dog_images(dogpath_prefix_len):
fig,axes=plt.subplots(nrows=3,ncols=3)
fig.set_size_inches(10,9)
random_9_nums=np.random.choice(len(x_train),9)
random_9_imgs=x_train[random_9_nums]
print(random_9_imgs)
imgname_list=[]
for imgpath in random_9_imgs:
imgname=imgpath[dogpath_prefix_len:]
imgname=imgname[:imgname.find('/')]
imgname_list.append(imgname)
index=0
for row_index in range(3):
for col_index in range(3):
img=image.imread(random_9_imgs[index])
ax=axes[row_index,col_index]
ax.imshow(img)
ax.set_xlabel(imgname_list[index])
index+=1
plt.show()
def path_to_tensor(img_path):
img=image1.load_img(img_path,target_size=(224,224,3))
x=image1.img_to_array(img)
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)
if __name__ == '__main__':
num_classes = 120
path0=os.path.join(os.getcwd(),'Images')
# path0=r'Images/'
dog_filepaths,dog_raw_targets,dog_targets=load_dataset(path0)
print(dog_filepaths)
print(dog_raw_targets)
print(dog_targets)
dogpath_prefix_len=len(os.path.join(path0,'n02085602-'))
dog_names=[item[dogpath_prefix_len:] for item in sorted(glob(os.path.join(path0,'*')))]
print("dog_names=",dog_names)
print(glob(path0))
print("狗的品种有{}种".format(len(dog_names)))
print("狗的图片一共有{}张".format(len(dog_filepaths)))
print(dog_names[:5])
print(dog_filepaths[:5])
print(dog_raw_targets[:10])
print(dog_targets[:3])
dog_filepaths=dog_filepaths[:9000]
dog_targets=dog_targets[:9000]
x_train,x_test,y_train,y_test=train_test_split(dog_filepaths,dog_targets,test_size=0.2)
half_test_count=int(len(x_test)/2)
x_valid=x_test[:half_test_count]
y_valid=y_test[:half_test_count]
x_test=x_test[half_test_count:]
y_test=y_test[half_test_count:]
print("x_train.shape={},y_train.shape={}".format(x_train.shape,y_train.shape))
print("x_valid.shape={},y_valid.shape={}".format(x_valid.shape, y_valid.shape))
print("x_test.shape={},y_test.shape={}".format(x_test.shape, y_test.shape))
plt.style.use('default')
draw_random_9_dog_images(dogpath_prefix_len)
dogs_shape_list=[]
for filepath in dog_filepaths:
shape=image.imread(filepath).shape
if len(shape)==3:
dogs_shape_list.append(shape)
dogs_shapes=np.asarray(dogs_shape_list)
print("总共{}张".format(len(dogs_shapes)))
print("随机抽取3张照片的维度是{}。".format(dogs_shapes[np.random.choice(len(dogs_shapes),3)]))
dogs_mean_width=np.mean(dogs_shapes[:,0])
dogs_mean_height=np.mean(dogs_shapes[:,1])
print("狗的图片的平均宽:{}*平均高:{}。".format(dogs_mean_width,dogs_mean_height))
plt.plot(dogs_shapes[:,0],dogs_shapes[:,1],'o')
plt.title("The Image Sizes of All Categories of Dog")
plt.xlabel("Image Width")
plt.ylabel("Image Height")
plt.show()
plt.hist(dogs_shapes[:,0],bins=100)
plt.title("Dog Images Width Distribution")
plt.show()
plt.hist(dogs_shapes[:,1],bins=100)
plt.title("Dog Images Height Distribution")
plt.show()
#数据预处理
ImageFile.LOAD_TRUNCATED_IMAGES=True
train_tensors=paths_to_tensor(x_train).astype(np.float32)/255
valid_tensors=paths_to_tensor(x_valid).astype(np.float32)/255
test_tensors=paths_to_tensor(x_test).astype(np.float32)/255
#创建模型
from keras.layers import Conv2D,MaxPooling2D,GlobalAveragePooling2D
from keras.layers import Dropout,Flatten,Dense
from keras.models import Sequential
model=Sequential()
model.add(Conv2D(filters=16,kernel_size=(2,2),strides=(1,1),padding='same',activation='relu',
input_shape=train_tensors.shape[1:]))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.2))
model.add(Conv2D(filters=32,kernel_size=(2,2),strides=(1,1),padding='same',activation='relu'))
model.add(Conv2D(filters=64, kernel_size=(2, 2), strides=(1, 1), padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.2))
model.add(GlobalAveragePooling2D())
model.add(Dropout(0.5))
model.add(Dense(num_classes,activation='softmax'))
model.summary()
model.compile(optimizer='rmsprop',loss='categorical_crossentropy',metrics=['accuracy'])
path1=os.path.join(os.getcwd(),'saved_models','weights.best.from_scratch.hdf5')
checkpointer=ModelCheckpoint(filepath=path1,
verbose=1,save_best_only=True)
epochs=20
model.fit(train_tensors,
y_train,
validation_data=(valid_tensors,y_valid),
epochs=epochs,
batch_size=20,
callbacks=[checkpointer],
verbose=1)
##加载具有最好验证权重的模型
model.load_weights(path1)
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(y_test,axis=1))/len(dog_breed_predictions))
print('Test Accuracy:{}'.format(test_accuracy))
这个神经网络比较简单,准确率不高。