我正在使用keras进行验证码识别问题,每张图片有四个字母。
我最后设置了四个“ S形”密集层,并将它们连接为一个张量(其中,网络形状的最终输出为(None,4 * 36))。其中4表示验证码长度,36表示字符大小。
我设置了自定义损失函数和准确性函数,但是损失没有减少吗?
这是怎么了?谁能解释一下,谢谢!
下面是我的代码:
- 验证码生成器
def deal_img(img):
kernel = np.ones((3,1), np.uint8)
img = img_to_array(img).astype(np.uint8)
img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
blur = cv.GaussianBlur(img, (5, 5), 0)
_, img = cv.threshold(blur, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)
img = cv.dilate(img, kernel, iterations=1)
img = cv.erode(img, kernel, iterations=1)
return img.reshape(height,width,1)
def gen(batch_size=32):
while True:
imgs=[]
labels = []
for i in range(batch_size):
random_str = ''.join([random.choice(characters) for j in range(4)])
img = generator.generate_image(random_str)
img = deal_img(img)
imgs.append(img)
y=np.zeros((len(characters)*4))
for i,char in enumerate(random_str):
y[characters.find(char)+i*len(characters)] = 1
labels.append(y)
train_x = np.array(imgs)
train_y = np.array(labels)
yield train_x, train_y
- 模型
input_tensor = Input(shape=(height, width, 1))
x = input_tensor
x = Conv2D(32, 3, padding='same', activation='relu')(x)
x = Conv2D(32, 3, padding='same', activation='relu')(x)
x = MaxPooling2D((2, 2))(x)
x = Conv2D(64, 3, padding='same', activation='relu')(x)
x = Conv2D(64, 3, padding='same', activation='relu')(x)
x = MaxPooling2D((2, 2))(x)
x = Conv2D(128, 3, padding='same', activation='relu')(x)
x = Conv2D(128, 3, padding='same',activation='relu')(x)
x = MaxPooling2D((2, 2))(x)
x = Flatten()(x)
x = Dropout(0.25)(x)
x = [Dense(n_class, activation='softmax', name='c%d'%(i+1))(x) for i in range(n_len)]
output = concatenate(x)
model = Model(inputs=input_tensor, outputs=output)
- 损失,acc和火车
def my_acc(y_true, y_pred):
predict = tf.reshape(y_pred, [-1, n_len, len(characters)])
max_idx_p = tf.argmax(predict, 2)
max_idx_l = tf.argmax(tf.reshape(y_true, [-1,n_len, len(characters)]), 2)
correct_pred = tf.reduce_all(tf.equal(max_idx_p, max_idx_l),axis=1)
return tf.reduce_mean(tf.cast(correct_pred, tf.float32))
def my_loss(y_true, y_pred):
loss = tf.Variable(initial_value=0.0)
for i in range(n_len):
a = y_pred[:,i*36:(i+1)*36]
b = y_true[:,i*36:(i+1)*36]
loss += tf.keras.losses.categorical_crossentropy(b,a)
return loss
model.compile(loss = my_loss,
optimizer=tf.train.AdamOptimizer(0.1),
metrics=[my_acc])
checkpointer = keras.callbacks.ModelCheckpoint(filepath='/output/weight.h5',#"output/weights.{epoch:02d}--{val_loss:.2f}-{val_my_acc:.4f}.hdf5",
verbose=2, save_weights_only=True)
model.fit_generator(gen(64),steps_per_epoch=10000,epochs=1,verbose=1,validation_data=gen(100),validation_steps=1,callbacks=[checkpointer])