我正在尝试构建一个图像分类模型,用于预测是否戴了口罩。这是第一次自己制作模型,训练时准确率在50%左右波动,并且每次预测结果总是显示“未戴口罩”。我尝试过改变epoch数、批量大小、训练数据量,甚至修改模型代码,但都没有效果。以下是我的代码:
import osimport cv2import randomimport numpy as npfrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Dense, Flatten,Dropoutfrom tensorflow.keras.optimizers import SGDdef preproccesImage(img): img = cv2.resize(img,dsize=(150,150 ), interpolation = cv2.INTER_CUBIC) return imgdef getData(): training = [] for image in os.listdir("src/data/with_mask"): img = cv2.imread(f"src/data/with_mask/{image}",cv2.IMREAD_GRAYSCALE) proccesed = preproccesImage(img) training.append([proccesed.tolist(),1]) for image in os.listdir("src/data/without_mask"): img = cv2.imread(f"src/data/without_mask/{image}",cv2.IMREAD_GRAYSCALE) proccesed = preproccesImage(img) training.append([proccesed.tolist(),0]) random.shuffle(training) train_x = np.array([x[0] for x in training],dtype=np.float32) train_y = np.array([x[1] for x in training],dtype=np.float32) print(train_x) print(train_y) return (train_x ,train_y)train_x , train_y = getData()model = Sequential()model.add(Dense(32,input_shape=(len(train_x[0]),150),activation="relu"))model.add(Flatten())model.add(Dense(128,activation="relu"))model.add(Dropout(0.2))model.add(Dense(128,activation="relu"))model.add(Flatten())model.add(Dense(1,activation="softmax"))model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])hist = model.fit( train_x,train_y, epochs=200, batch_size=2, verbose=1)model.save("model.h5", hist)img = cv2.imread("src/me.png",cv2.IMREAD_GRAYSCALE)resized = cv2.resize(img,dsize=(150,150 ), interpolation = cv2.INTER_CUBIC)def predict(): res = model.predict([resized.tolist()])[0] resoult = [[i, r] for i, r in enumerate(res)] predicted = [] for r in resoult: predicted.append({"intent": 1 if r[0] == 1 else 0, "probability": r[1]}) if predicted[0]["intent"] == 1: print("mask on") else: print('no mask') predict()
如果有人能帮忙,我将不胜感激
回答:
这不是二元分类所需的正确组合;你应该将损失函数改为binary_crossentropy
,并将最后一层的激活函数改为sigmoid
,例如:
model.add(Dense(1,activation="sigmoid")) # 最后一层model.compile(loss="binary_crossentropy", optimizer="adam", metrics=["accuracy"])
更一般地说,你的模型在早期阶段可以从一些卷积层中受益;还要注意,在Dense
层之后放置Flatten
层是没有意义的。