#tensorflow #deep-learning #ocr #transfer-learning #pre-trained-model
#tensorflow #глубокое обучение #ocr #передача-обучение #предварительно обученная модель
Вопрос:
прежде всего: я новичок в глубоком обучении и Tensorflow, поэтому извините за глупые вопросы. Может быть, кто-нибудь может помочь мне получить больше понимания и ясности. Я работаю над проектом OCR, где у меня есть только 4000 помеченных изображений с пунктирным шрифтом и белым фоном. Я решил использовать этот код для решения задачи: https://github.com/Pay20Y/FOTS_TF
Я использовал предварительно обученную модель для набора данных Synthtext и продолжил обучение с моим собственным набором данных, но результаты были не такими хорошими. Я думаю, что одна из проблем может заключаться в том, что количество классов моего пользовательского набора данных меньше, чем количество классов предварительно обученной модели. Я читал об обучении передаче, где вы обучаете только последние слои, а затем вы можете использовать другое количество классов, но я не знаю, как это сделать. Итак, чтобы быть более точным, я не знаю, как определить последние слои графика?
Вот код построения графика:
def cnn(self, rois):
with tf.variable_scope("recog/cnn"):
conv1 = slim.conv2d(rois, 64, 3, stride=1, padding='SAME', activation_fn=tf.nn.relu, normalizer_fn=None)
conv1 = slim.conv2d(conv1, 64, 3, stride=1, padding='SAME', activation_fn=tf.nn.relu, normalizer_fn=None)
pool1 = slim.max_pool2d(conv1, [2, 1], stride=[2, 1])
conv2 = slim.conv2d(pool1, 128, 3, stride=1, padding='SAME', activation_fn=tf.nn.relu, normalizer_fn=None)
conv2 = slim.conv2d(conv2, 128, 3, stride=1, padding='SAME', activation_fn=tf.nn.relu, normalizer_fn=None)
pool2 = slim.max_pool2d(conv2, [2, 1], stride=[2, 1])
conv3 = slim.conv2d(pool2, 256, 3, stride=1, padding='SAME', activation_fn=tf.nn.relu, normalizer_fn=None)
conv3 = slim.conv2d(conv3, 256, 3, stride=1, padding='SAME', activation_fn=tf.nn.relu, normalizer_fn=None)
pool3 = slim.max_pool2d(conv3, [2, 1], stride=[2, 1])
return pool3
def bilstm(self, input_feature, seq_len):
with tf.variable_scope("recog/rnn"):
lstm_fw_cell = rnn.LSTMCell(self.rnn_hidden_num)
lstm_fw_cell = tf.nn.rnn_cell.DropoutWrapper(lstm_fw_cell, input_keep_prob=self.keepProb, output_keep_prob=self.keepProb)
lstm_bw_cell = rnn.LSTMCell(self.rnn_hidden_num)
lstm_bw_cell = tf.nn.rnn_cell.DropoutWrapper(lstm_bw_cell, input_keep_prob=self.keepProb, output_keep_prob=self.keepProb)
# infer_output, _ = tf.nn.bidirectional_dynamic_rnn(lstm_fw_cell, lstm_bw_cell, input_feature, seq_len, dtype=tf.float32)
# infer_output, _ = tf.nn.bidirectional_dynamic_rnn(lstm_fw_cell, lstm_bw_cell, input_feature, sequence_length=seq_len, time_major=True, dtype=tf.float32)
infer_output, _ = tf.nn.bidirectional_dynamic_rnn(lstm_fw_cell, lstm_bw_cell, input_feature, sequence_length=seq_len, dtype=tf.float32)
# stack_lstm_layer, _, _ = rnn.stack_bidirectional_dynamic_rnn(lstm_fw_cell, lstm_bw_cell, input_feature, dtype=tf.float32)
infer_output = tf.concat(infer_output, axis=-1)
return infer_output
# return stack_lstm_layer
def build_graph(self, rois, seq_len):
num_rois = tf.shape(rois)[0]
cnn_feature = self.cnn(rois) # N * 1 * W * C
print cnn_feature
cnn_feature = tf.reshape(cnn_feature, [nums, -1, 256]) # squeeze B x W x C
cnn_feature = tf.squeeze(cnn_feature, axis=1) # N * W * C
reshape_cnn_feature = tf.transpose(cnn_feature, (1, 0, 2))
reshape_cnn_feature = cnn_feature
# print "final cnn: ", reshape_cnn_feature.shape
lstm_output = self.bilstm(reshape_cnn_feature, seq_len) # N * T * 2H
# print "lstm_output: ", lstm_output
logits = tf.reshape(lstm_output, [-1, self.rnn_hidden_num * 2]) # (N * T) * 2H
W = tf.Variable(tf.truncated_normal([self.rnn_hidden_num * 2, self.num_classes], stddev=0.1), name="W")
b = tf.Variable(tf.constant(0., shape=[self.num_classes]), name="b")
logits = tf.matmul(logits, W) b # (N * T) * Class
logits = tf.reshape(logits, [num_rois, -1, self.num_classes])
logits = tf.reshape(logits, [nums, -1, self.num_classes])
logits = tf.reshape(logits, [num_rois, -1, self.num_classes])
logits = tf.transpose(logits, (1, 0, 2))
return logits
Я не знаю, разумно ли проводить обучение передаче?
Есть ли еще другой способ использовать предварительно обученную модель и выполнить точную настройку в моем собственном наборе данных, но с другим количеством классов символов?
Я действительно не понимаю, как решить эту задачу и что попытаться улучшить результаты. Я уже пробовал обучать с нуля без предварительно обученной модели, но модель переобучается.
Комментарии:
1. вы пробовали разные модели для решения вашей проблемы распознавания?
2. что вы имеете в виду под разными моделями? Вы имеете в виду разные предварительно обученные модели?
3. Как вы сказали, вы не получили лучшего результата, используя эту модель, так почему бы не использовать модель SOTA (т. Е. ABCNet). К вашему сведению, для проблемы распознавания текста вам не нужно обучать последний слой или что-то в этом роде (в отличие от проблемы компьютерного зрения в целом); просто инициализируйте с предварительно подготовленными весами и запустите с несколькими эпохами. AFAIK, вы не можете переобучить только последний слой модели распознавания.
4. Последний уровень любой модели распознавания текста — это, по сути, ветвь распознавания для распознавания текста. Это сочетается с ветвью обнаружения. Чтобы точно настроить определенный тип текста, вам необходимо потренироваться на наборе данных synth-text и точно настроить целевой набор данных.
5. Теперь, когда выбранная модель уже обучена синтезаторному тексту и настроена на эталонный набор данных (т. Е. total-text, icdar и т. Д.), Мы можем взять их предварительно обученный вес и инициализировать его для нашей задачи или нашего конкретного набора данных.