我参考了一个指南来制作一个对象分类器。我的分类器的任务是判断它正在查看的图像是否是动漫,因为我想将其集成到一个机器人中,用于在群聊中标记动漫。网络在训练后输出的图表显示结果尚可但有待改进,但分类脚本的准确性似乎并不理想。我的数据集有1000张图像,这是我最后一次训练尝试的图表。如你所见,val_loss值相当可行但波动较大。
我在训练并保存权重后,用两张图像来测试训练后的模型,一张是普通的室内植物,另一张是一般的动漫女孩。模型预测室内植物的动漫概率为0.37%,动漫照片的动漫概率为0.00%。这些照片在视觉上与它们各自的数据集相似,分别是“动漫”和“其他”(包括汽车、植物、房屋和其他“随机”对象的图像)。这些图像通过其子文件夹进行类别标记。
这是我的模型代码:
from tensorflow.keras.layers import BatchNormalizationfrom tensorflow.keras.layers import Conv2Dfrom tensorflow.keras.layers import MaxPooling2Dfrom tensorflow.keras.layers import Activationfrom tensorflow.keras.layers import Flattenfrom tensorflow.keras.layers import Dropoutfrom tensorflow.keras.layers import Densefrom tensorflow.keras import backend as Kclass SmallerVGGNet: @staticmethod def build(width, height, depth, classes): # initialize the model along with the input shape to be # "channels last" and the channels dimension itself model = Sequential() inputShape = (height, width, depth) chanDim = -1 # if we are using "channels first", update the input shape # and channels dimension if K.image_data_format() == "channels_first": inputShape = (depth, height, width) chanDim = 1 # CONV => RELU => POOL model.add(Conv2D(32, (3, 3), padding="same", input_shape=inputShape)) model.add(Activation("relu")) model.add(BatchNormalization(axis=chanDim)) model.add(MaxPooling2D(pool_size=(3, 3))) model.add(Dropout(0.25)) # (CONV => RELU) * 2 => POOL model.add(Conv2D(64, (3, 3), padding="same")) model.add(Activation("relu")) model.add(BatchNormalization(axis=chanDim)) model.add(Conv2D(64, (3, 3), padding="same")) model.add(Activation("relu")) model.add(BatchNormalization(axis=chanDim)) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) # (CONV => RELU) * 2 => POOL model.add(Conv2D(128, (3, 3), padding="same")) model.add(Activation("relu")) model.add(BatchNormalization(axis=chanDim)) model.add(Conv2D(128, (3, 3), padding="same")) model.add(Activation("relu")) model.add(BatchNormalization(axis=chanDim)) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) # first (and only) set of FC => RELU layers model.add(Flatten()) model.add(Dense(1024)) model.add(Activation("relu")) model.add(BatchNormalization()) model.add(Dropout(0.5)) # 1 node model.add(Dense(1)) model.add(Activation("sigmoid")) return model
我的训练器:
最后,这是我的分类器:
我尝试过的一些方法包括减少训练周期、尝试sigmoid的替代方案、使用不同的损失函数以及更具体的类别。
回答:
您的模型以单个使用sigmoid激活的Dense单元结束,然而,您随后使用np.argmax()和一系列标签,好像您在使用softmax激活。您无意中对每个样本预测了标记为“0”的类别。您的模型训练得很好,只是您之后的预测方式有问题。