写在前面:
数据集和模型文件下载链接(不需要付费和积分,直接可以下载,这个模型文件老师没给,里面是我训练的,精度比较差,建议自己修改代码并训练):
https://download.csdn.net/download/qq_43554335/28807432
这个和前一个实验的区别指导书上也写了:以前是直接从.npz文件中读取已经创建好的Numpy数组,第二个实验的数据室原始图片文件。
首先先要了解Keras数据增强生成器的各个参数所代表的含义,我参考用的是这个:
https://blog.csdn.net/jacke121/article/details/79245732
这里主要说一下rescale
rescale:对图片的每个像素值均乘以放缩因子(这里缩放因子为1/255),在某些模型中,直接输入原图的像素值可能会落入激活函数的“死亡区”,把像素值放缩到[0,1]有利于模型的收敛,避免神经元挂掉。(图片经过rescale之后,保存到本地的图片用肉眼看是没有任何区别的,可以在内存中直接打印图片数值观察结果。)
原图片数值结果:
处理后:
其他的没什么新内容。
同上一篇,这里两个地方需要改一下:
精度好差,呜呜呜,待提升(坐等大佬完成我来抄作业)。
下面是第二个实验的代码(注意文件路径修改成你自己的路径):(代码来源指导书,我把问题处已经改了,仅供存档)
from keras.utils.np_utils import to_categorical
import pydot
import graphviz
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
from keras.utils.vis_utils import plot_model
from keras.models import Sequential, Model, load_model
from keras.layers import Dense, Flatten, Dropout
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.applications.vgg16 import VGG16
from keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array
from keras import backend as K
import numpy as np
import matplotlib.pyplot as plt
datagen = ImageDataGenerator(rescale=1./255, validation_split=0.2)
train_generator = datagen.flow_from_directory('../sources/image_class5', target_size=(64, 64), batch_size=400, subset='training', seed=123)
test_generator = datagen.flow_from_directory('../sources/image_class5', target_size=(64, 64), batch_size=100, subset='validation', seed=123)
#调用从文件夹中加载图片数据的迭代器的函数next()得到图片数据的Numpy数组。
x_train, y_train = train_generator.next()
x_test, y_test = test_generator.next()
#使用从文件夹中加载图片数据的迭代器的属性class_indices得到以类别名称为键、类别序号为值的字典,交换字典的键和值。
labels = {y:x for x,y in train_generator.class_indices.items()}
print(labels)
#调用程序包matplotlib.pyplot中的函数imshow()绘制4个物体图片。
plt.figure()
for i in range(4):
plt.subplot(221 + i)
plt.title(labels[np.argwhere(y_train[i]==1)[0][0]])
plt.imshow(x_train[i])
plt.axis('off')
plt.show()
#使用属性shape得到4个数据子集经过预处理后的维度。
print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)
model_cnn = Sequential()
model_cnn.add(Conv2D(filters=32, kernel_size=(3, 3), padding='same', input_shape=(64,64, 3), activation='relu'))
model_cnn.add(Conv2D(filters=32, kernel_size=(3, 3), activation='relu'))
model_cnn.add(MaxPooling2D(pool_size=(2, 2)))
model_cnn.add(Dropout(0.25))
model_cnn.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
model_cnn.add(Conv2D(64, (3, 3), activation='relu'))
model_cnn.add(MaxPooling2D(pool_size=(2, 2)))
model_cnn.add(Dropout(0.25))
model_cnn.add(Flatten())
model_cnn.add(Dense(512, activation='relu'))
model_cnn.add(Dropout(0.5))
model_cnn.add(Dense(5, activation='softmax'))
model_cnn.summary()
#调用模型的函数compile()编译模型,配置Adam优化器、分类交叉熵损失函数和精度性能指标。
model_cnn.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
#调用模型的函数fit()训练模型。
history_cnn=model_cnn.fit(x_train, y_train, epochs=20, batch_size=32, verbose=2, validation_data=(x_test, y_test))
#调用模型的函数evaluate()评估模型。
score = model_cnn.evaluate(x_test, y_test, batch_size=128)
print("Test loss: ",score[0])
print("Test accuracy: ",score[1])
plt.figure()
plt.plot(history_cnn.history['accuracy'], color='b', linestyle='-', label='training')
plt.plot(history_cnn.history['val_accuracy'], color='r', linestyle='--', label='validation')
plt.title("Model accuracy")
plt.ylabel("accuracy")
plt.xlabel("epoch")
plt.legend(loc="upper left")
plt.show()
plt.figure()
plt.plot(history_cnn.history['loss'], color='b', linestyle='-', label='training')
plt.plot(history_cnn.history['val_loss'], color='r', linestyle='--', label='validation')
plt.title("Model loss")
plt.ylabel("loss")
plt.xlabel("epoch")
plt.legend(loc="upper right")
plt.show()
#调用模型的函数save()保存为HDF5格式的文件,便于以后使用。
model_cnn.save("../models/image_classs5_cnn.h5")
#调用函数load_model()加载HDF5格式的模型文件。
model_cnn = load_model("../models/image_classs5_cnn.h5")
#调用序贯模型的函数predict_classes()预测类别标签。
#y_pred = model_cnn.predict_classes(x_test, batch_size=128)
y_pred = model_cnn.predict(x_test, batch_size=128, verbose = 0)
y_pred = np.argmax(y_pred,axis=1)
#调用程序包numpy的函数where()得到预测错误的样本序号。
y_test_ohd = np.argmax(y_test, axis=1)
misclassified = np.where(y_pred!=y_test_ohd)[0]
print(misclassified)
## [15 23 52 73 83]
#调用程序包matplotlib.pyplot中的函数imshow()绘制4个预测错误的物体。
plt.figure()
for i in range(min(4,len(misclassified))):
plt.subplot(221 + i)
plt.title('predicted: ' + labels[y_pred[misclassified[i]]] + ', true: ' + labels[y_test_ohd[misclassified[i]]])
plt.imshow(x_test[misclassified[i]])
plt.axis('off')
plt.show()
绘制4个预测错误的物体结果:
后记:
研究生学姐提到:注意这个图片的尺寸和实验要求的尺寸。rescale那一步要调整。(上述代码中图片数据生成器那里我还没改,大概这个就是精度比较差的原因吧,回去研究研究,陶大佬给了我个链接:https://zhuanlan.zhihu.com/p/49893017咱们可以一起学学)



